@@ -1300,52 +1300,86 @@ def foo():
1300
1300
assert e .value ._hint == "try importing lib1 first"
1301
1301
1302
1302
1303
- def test_nonreentrant_exports (make_input_bundle ):
1303
+ @pytest .fixture
1304
+ def nonreentrant_library_bundle (make_input_bundle ):
1305
+ # test simple case
1304
1306
lib1 = """
1305
1307
# lib1.vy
1306
- @external
1308
+ @internal
1307
1309
@nonreentrant
1308
1310
def bar():
1309
1311
pass
1312
+
1313
+ # lib1.vy
1314
+ @external
1315
+ @nonreentrant
1316
+ def ext_bar():
1317
+ pass
1310
1318
"""
1311
- main = """
1319
+ # test case with recursion
1320
+ lib2 = """
1321
+ @internal
1322
+ def bar():
1323
+ self.baz()
1324
+
1325
+ @external
1326
+ def ext_bar():
1327
+ self.baz()
1328
+
1329
+ @nonreentrant
1330
+ @internal
1331
+ def baz():
1332
+ return
1333
+ """
1334
+ # test case with nested recursion
1335
+ lib3 = """
1312
1336
import lib1
1337
+ uses: lib1
1313
1338
1314
- exports: lib1.bar # line 4
1339
+ @internal
1340
+ def bar():
1341
+ lib1.bar()
1342
+
1343
+ @external
1344
+ def ext_bar():
1345
+ lib1.bar()
1346
+ """
1347
+
1348
+ return make_input_bundle ({"lib1.vy" : lib1 , "lib2.vy" : lib2 , "lib3.vy" : lib3 })
1349
+
1350
+
1351
+ @pytest .mark .parametrize ("lib" , ("lib1" , "lib2" , "lib3" ))
1352
+ def test_nonreentrant_exports (nonreentrant_library_bundle , lib ):
1353
+ main = f"""
1354
+ import { lib }
1355
+
1356
+ exports: { lib } .ext_bar # line 4
1315
1357
1316
1358
@external
1317
1359
def foo():
1318
1360
pass
1319
1361
"""
1320
- input_bundle = make_input_bundle ({"lib1.vy" : lib1 })
1321
1362
with pytest .raises (ImmutableViolation ) as e :
1322
- compile_code (main , input_bundle = input_bundle )
1323
- assert e .value ._message == "Cannot access `lib1 ` state!" + NONREENTRANT_NOTE
1324
- hint = "add `uses: lib1 ` or `initializes: lib1 ` as a top-level statement to your contract"
1363
+ compile_code (main , input_bundle = nonreentrant_library_bundle )
1364
+ assert e .value ._message == f "Cannot access `{ lib } ` state!" + NONREENTRANT_NOTE
1365
+ hint = f "add `uses: { lib } ` or `initializes: { lib } ` as a top-level statement to your contract"
1325
1366
assert e .value ._hint == hint
1326
1367
assert e .value .annotations [0 ].lineno == 4
1327
1368
1328
1369
1329
- def test_internal_nonreentrant_import (make_input_bundle ):
1330
- lib1 = """
1331
- # lib1.vy
1332
- @internal
1333
- @nonreentrant
1334
- def bar():
1335
- pass
1336
- """
1337
- main = """
1338
- import lib1
1370
+ @pytest .mark .parametrize ("lib" , ("lib1" , "lib2" , "lib3" ))
1371
+ def test_internal_nonreentrant_import (nonreentrant_library_bundle , lib ):
1372
+ main = f"""
1373
+ import { lib }
1339
1374
1340
1375
@external
1341
1376
def foo():
1342
- lib1 .bar() # line 6
1377
+ { lib } .bar() # line 6
1343
1378
"""
1344
- input_bundle = make_input_bundle ({"lib1.vy" : lib1 })
1345
1379
with pytest .raises (ImmutableViolation ) as e :
1346
- compile_code (main , input_bundle = input_bundle )
1347
- assert e .value ._message == "Cannot access `lib1 ` state!" + NONREENTRANT_NOTE
1380
+ compile_code (main , input_bundle = nonreentrant_library_bundle )
1381
+ assert e .value ._message == f "Cannot access `{ lib } ` state!" + NONREENTRANT_NOTE
1348
1382
1349
- hint = "add `uses: lib1 ` or `initializes: lib1 ` as a top-level statement to your contract"
1383
+ hint = f "add `uses: { lib } ` or `initializes: { lib } ` as a top-level statement to your contract"
1350
1384
assert e .value ._hint == hint
1351
1385
assert e .value .annotations [0 ].lineno == 6
0 commit comments