mirror of
https://github.com/github/codeql.git
synced 2026-05-14 11:19:27 +02:00
These tests consist of various Python constructions (hopefully a somewhat comprehensive set) with specific timestamp annotations scattered throughout. When the tests are run using the Python 3 interpreter, these annotations are checked and compared to the "current timestamp" to see that they are in agreement. This is what makes the tests "self-validating". There are a few different kinds of annotations: the basic `t[4]` style (meaning this is executed at timestamp 4), the `t.dead[4]` variant (meaning this _would_ happen at timestamp 4, but it is in a dead branch), and `t.never` (meaning this is never executed at all). In addition to this, there is a query, MissingAnnotations, which checks whether we have applied these annotations maximally. Many expression nodes are not actually annotatable, so there is a sizeable list of excluded nodes for that query.
183 lines
3.9 KiB
Python
183 lines
3.9 KiB
Python
"""Exception handling control flow: try/except/else/finally evaluation order."""
|
|
|
|
from timer import test
|
|
|
|
|
|
# 1. try/except — no exception raised (except block skipped)
|
|
@test
|
|
def test_try_no_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
y = 2 @ t[1]
|
|
except ValueError:
|
|
z = 3 @ t.dead[2]
|
|
after = 0 @ t[2]
|
|
|
|
|
|
# 2. try/except — exception raised and caught
|
|
@test
|
|
def test_try_with_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])() @ t[2])
|
|
y = 2 @ t.never
|
|
except ValueError:
|
|
z = 3 @ t[3]
|
|
after = 0 @ t[4]
|
|
|
|
|
|
# 3. try/except/else — no exception (else runs)
|
|
@test
|
|
def test_try_except_else_no_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
except ValueError:
|
|
y = 2 @ t.dead[1]
|
|
else:
|
|
z = 3 @ t[1]
|
|
after = 0 @ t[2]
|
|
|
|
|
|
# 4. try/except/else — exception raised (else skipped)
|
|
@test
|
|
def test_try_except_else_with_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])() @ t[2])
|
|
except ValueError:
|
|
y = 2 @ t[3]
|
|
else:
|
|
z = 3 @ t.dead[3]
|
|
after = 0 @ t[4]
|
|
|
|
|
|
# 5. try/finally — no exception
|
|
@test
|
|
def test_try_finally_no_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
y = 2 @ t[1]
|
|
finally:
|
|
z = 3 @ t[2]
|
|
after = 0 @ t[3]
|
|
|
|
|
|
# 6. try/finally — exception raised (finally runs, then exception propagates)
|
|
@test
|
|
def test_try_finally_exception(t):
|
|
try:
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])() @ t[2])
|
|
finally:
|
|
y = 2 @ t[3]
|
|
except ValueError:
|
|
z = 3 @ t[4]
|
|
|
|
|
|
# 7. try/except/finally — no exception
|
|
@test
|
|
def test_try_except_finally_no_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
except ValueError:
|
|
y = 2 @ t.dead[1]
|
|
finally:
|
|
z = 3 @ t[1]
|
|
after = 0 @ t[2]
|
|
|
|
|
|
# 8. try/except/finally — exception caught
|
|
@test
|
|
def test_try_except_finally_exception(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])() @ t[2])
|
|
except ValueError:
|
|
y = 2 @ t[3]
|
|
finally:
|
|
z = 3 @ t[4]
|
|
after = 0 @ t[5]
|
|
|
|
|
|
# 9. Multiple except clauses — first matching
|
|
@test
|
|
def test_multiple_except_first(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])() @ t[2])
|
|
except ValueError:
|
|
y = 2 @ t[3]
|
|
except TypeError:
|
|
z = 3 @ t.dead[3]
|
|
after = 0 @ t[4]
|
|
|
|
|
|
# 10. Multiple except clauses — second matching
|
|
@test
|
|
def test_multiple_except_second(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((TypeError @ t[1])() @ t[2])
|
|
except ValueError:
|
|
y = 2 @ t.dead[3]
|
|
except TypeError:
|
|
z = 3 @ t[3]
|
|
after = 0 @ t[4]
|
|
|
|
|
|
# 11. except with `as` binding
|
|
@test
|
|
def test_except_as_binding(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])("msg" @ t[2]) @ t[3])
|
|
except ValueError as e:
|
|
y = (str @ t[4])(e @ t[5]) @ t[6]
|
|
after = 0 @ t[7]
|
|
|
|
|
|
# 12. Nested try/except
|
|
@test
|
|
def test_nested_try_except(t):
|
|
try:
|
|
x = 1 @ t[0]
|
|
try:
|
|
y = 2 @ t[1]
|
|
raise ((ValueError @ t[2])() @ t[3])
|
|
except ValueError:
|
|
z = 3 @ t[4]
|
|
w = 4 @ t[5]
|
|
except TypeError:
|
|
v = 5 @ t.dead[6]
|
|
after = 0 @ t[6]
|
|
|
|
|
|
# 13. try/except in a loop
|
|
@test
|
|
def test_try_in_loop(t):
|
|
total = 0 @ t[0]
|
|
for i in (range @ t[1])(3 @ t[2]) @ t[3]:
|
|
try:
|
|
if (i @ t[4, 11, 20] == 1 @ t[5, 12, 21]) @ t[6, 13, 22]:
|
|
raise ((ValueError @ t[14])() @ t[15])
|
|
total = (total @ t[7, 23] + 1 @ t[8, 24]) @ t[9, 25]
|
|
except ValueError:
|
|
total = (total @ t[16] + 10 @ t[17]) @ t[18]
|
|
r = 0 @ t[10, 19, 26]
|
|
|
|
|
|
# 14. Re-raise with bare `raise`
|
|
@test
|
|
def test_reraise(t):
|
|
try:
|
|
try:
|
|
x = 1 @ t[0]
|
|
raise ((ValueError @ t[1])() @ t[2])
|
|
except ValueError:
|
|
y = 2 @ t[3]
|
|
raise
|
|
except ValueError:
|
|
z = 3 @ t[4]
|
|
after = 0 @ t[5]
|