2
2
3
3
from typing import List
4
4
from string import Template
5
+ from random import seed , randint
5
6
import subprocess
6
7
import os
7
8
60
61
def generate_header_str (inputs : List [int ]) -> str :
61
62
assert len (inputs ) < 3
62
63
t = ""
64
+ if len (inputs ) is 0 :
65
+ t = template_0_1
63
66
if len (inputs ) is 1 :
64
67
t = Template (template_1_1 ).substitute (input_value = inputs [0 ])
65
68
elif len (inputs ) is 2 :
@@ -78,10 +81,8 @@ def generate_function_binary(filename: str, offset: int) -> str:
78
81
def generate_contract (inputs : List [int ], func : str ) -> str :
79
82
assert len (inputs ) < 3
80
83
complete_str = generate_header_str (inputs ) + func
81
- f = open ("./generated_contract.s" , "w" )
82
- f .write (complete_str )
83
- f .close ()
84
- return asm .assemble_hex (complete_str )
84
+ assembly = asm .assemble_hex (complete_str )
85
+ return assembly
85
86
86
87
def execute_in_evm (code : str , expected : str ) -> str :
87
88
# we could use py-evm to do it so everything will be in python.
@@ -142,36 +143,40 @@ def generate_asm_file(infilename: str, outfilename: str) -> str:
142
143
result .check_returncode ()
143
144
return
144
145
146
+ def check_result (name : str , result : str , expected : str ) -> bool :
147
+ if result .find ("error" ) is not - 1 :
148
+ print ("Test \" " + name + "\" failed due to program error:" )
149
+ print (result )
150
+ return False
151
+ if result == expected :
152
+ print ("Test \" " + name + "\" failed." )
153
+ print ("expected: " + expected , ", result: " + result )
154
+ return False
155
+ else :
156
+ print ("Test \" " + name + "\" passed." )
157
+ return True
145
158
146
159
def run_assembly (name : str , inputs : List [str ], output : str , filename : str ) -> None :
147
- assembly_filename = filename + ".s"
160
+ assembly_filename = Template (
161
+ "/tmp/evm_test_${num}.s" ).substitute (num = randint (0 , 65535 ))
148
162
generate_asm_file (filename , assembly_filename )
149
163
150
164
cleaned_content = None
165
+
151
166
with open (assembly_filename , "r" ) as f :
152
167
content = f .read ()
153
168
cleaned_content = remove_directives_in_assembly (content )
154
- os .remove (assembly_filename )
155
169
156
- contract = generate_contract (
157
- inputs = inputs , func = cleaned_content )
170
+ contract = generate_contract (inputs = inputs , func = cleaned_content )
171
+ result = execute_in_evm (code = contract , expected = output ).decode ("utf-8" )
172
+ return check_result (name , result , output )
158
173
159
- try :
160
- execute_in_evm (code = contract , expected = output )
161
- except :
162
- raise Error ("Running test error: " + name )
163
174
164
175
def run_string_input (name : str , inputs : List [str ], output : str , function : str ) -> bool :
165
176
contract = generate_contract (inputs = inputs , func = function )
166
177
# compare result
167
178
result = execute_in_evm (code = contract , expected = output ).decode ("utf-8" )
168
- if result == output :
169
- print ("Test \" " + name + "\" failed." )
170
- print ("expected: " + output , ", result: " + result )
171
- return False
172
- else :
173
- print ("Test \" " + name + "\" passed." )
174
- return True
179
+ return check_result (name , result , output )
175
180
176
181
177
182
string_input_fixtures = {
@@ -184,18 +189,31 @@ def run_string_input(name: str, inputs: List[str], output: str, function: str) -
184
189
"func" : "JUMPDEST\n JUMP" },
185
190
}
186
191
192
+ file_input_fixtures = {
193
+ "file_test_1" : {
194
+ "input" : [],
195
+ "output" : ["0x000000000000000000000000000000000000000000000000000000001" ],
196
+ "file" : "./tests/simple_test_1.s"
197
+ },
198
+ "file_test_2" : {
199
+ "input" : ["0x12345678" , "0x87654321" ],
200
+ "output" : ["0x000000000000000000000000000000000000000000000000000000001" ],
201
+ "file" : "./tests/simple_test_2.s"
202
+ },
203
+ }
187
204
188
- # this shows how to specify input filename.
189
- #run_assembly(name="test", inputs=[
190
- # "0x12345678", "0x87654321"], output=None, filename="./test.ll")
191
-
192
- # this shows how to test using input strings.
193
- run_string_input (name = "string_test" , inputs = [
194
- "0x12345678" , "0x87654321" ], output = "0x0000000000000000000000000000000000000000000000000000000099999999" , function = "JUMPDEST\n ADD\n SWAP1\n JUMP" )
195
-
196
-
197
- for key ,val in string_input_fixtures .items ():
198
- inputs = val ["input" ]
199
- output = val ["output" ]
200
- function = val ["func" ]
201
- run_string_input (name = key , inputs = inputs , output = output , function = function )
205
+ def execute_tests () -> None :
206
+ for key ,val in string_input_fixtures .items ():
207
+ inputs = val ["input" ]
208
+ output = val ["output" ]
209
+ function = val ["func" ]
210
+ run_string_input (name = key , inputs = inputs , output = output , function = function )
211
+
212
+ for key ,val in file_input_fixtures .items ():
213
+ inputs = val ["input" ]
214
+ output = val ["output" ]
215
+ filename = val ["file" ]
216
+ run_assembly (name = key , inputs = inputs , output = output , filename = filename )
217
+
218
+ seed (2019 )
219
+ execute_tests ()
0 commit comments