|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +""" |
| 3 | +Unit tests from mathics.builtin.evaluation. |
| 4 | +""" |
| 5 | + |
| 6 | + |
| 7 | +from test.helper import check_evaluation, session |
| 8 | + |
| 9 | +import pytest |
| 10 | + |
| 11 | + |
| 12 | +@pytest.mark.parametrize( |
| 13 | + ("str_expr", "msgs", "str_expected", "fail_msg"), |
| 14 | + [ |
| 15 | + ("ClearAll[a];$RecursionLimit = 20", None, "20", None), |
| 16 | + ("a = a + a", ("Recursion depth of 20 exceeded.",), "$Aborted", None), |
| 17 | + ("$RecursionLimit = 200", None, "200", None), |
| 18 | + ( |
| 19 | + "ClearAll[f];f[x_, 0] := x; f[x_, n_] := f[x + 1, n - 1];Block[{$RecursionLimit = 20}, f[0, 100]]", |
| 20 | + None, |
| 21 | + "100", |
| 22 | + None, |
| 23 | + ), |
| 24 | + ( |
| 25 | + "ClearAll[f];f[x_, 0] := x; f[x_, n_] := Module[{y = x + 1}, f[y, n - 1]];Block[{$RecursionLimit = 20}, f[0, 100]]", |
| 26 | + ("Recursion depth of 20 exceeded.",), |
| 27 | + "$Aborted", |
| 28 | + None, |
| 29 | + ), |
| 30 | + ( |
| 31 | + "ClearAll[f]; f[x_] := f[x + 1];f[x]", |
| 32 | + ("Iteration limit of 1000 exceeded.",), |
| 33 | + "$Aborted", |
| 34 | + None, |
| 35 | + ), |
| 36 | + ( |
| 37 | + "$IterationLimit = x;", |
| 38 | + ( |
| 39 | + "Cannot set $IterationLimit to x; value must be an integer between 20 and Infinity.", |
| 40 | + ), |
| 41 | + None, |
| 42 | + None, |
| 43 | + ), |
| 44 | + ( |
| 45 | + "ClearAll[f];f[x_, 0] := x; f[x_, n_] := f[x + 1, n - 1];Block[{$IterationLimit = 20}, f[0, 100]]", |
| 46 | + ("Iteration limit of 20 exceeded.",), |
| 47 | + "$Aborted", |
| 48 | + None, |
| 49 | + ), |
| 50 | + ("ClearAll[f];", None, None, None), |
| 51 | + ( |
| 52 | + "Attributes[h] = Flat;h[items___] := Plus[items];h[1, Unevaluated[Sequence[Unevaluated[2], 3]], Sequence[4, Unevaluated[5]]]", |
| 53 | + None, |
| 54 | + "15", |
| 55 | + None, |
| 56 | + ), |
| 57 | + # FIX Later |
| 58 | + ( |
| 59 | + "ClearAll[f];f[x_, 0] := x; f[x_, n_] := Module[{y = x + 1}, f[y, n - 1]];Block[{$IterationLimit = 20}, f[0, 100]]", |
| 60 | + None, |
| 61 | + "100", |
| 62 | + "Fix me!", |
| 63 | + ), |
| 64 | + ("ClearAll[f];", None, None, None), |
| 65 | + ], |
| 66 | +) |
| 67 | +def test_private_doctests_evaluation(str_expr, msgs, str_expected, fail_msg): |
| 68 | + """These tests check the behavior of $RecursionLimit and $IterationLimit""" |
| 69 | + |
| 70 | + # Here we do not use the session object to check the messages |
| 71 | + # produced by the exceptions. If $RecursionLimit / $IterationLimit |
| 72 | + # are reached during the evaluation using a MathicsSession object, |
| 73 | + # an exception is raised. On the other hand, using the `Evaluation.evaluate` |
| 74 | + # method, the exception is handled. |
| 75 | + # |
| 76 | + # TODO: Maybe it makes sense to clone this exception handling in |
| 77 | + # the check_evaluation function. |
| 78 | + # |
| 79 | + def eval_expr(expr_str): |
| 80 | + query = session.evaluation.parse(expr_str) |
| 81 | + res = session.evaluation.evaluate(query) |
| 82 | + session.evaluation.stopped = False |
| 83 | + return res |
| 84 | + |
| 85 | + res = eval_expr(str_expr) |
| 86 | + if msgs is None: |
| 87 | + assert len(res.out) == 0 |
| 88 | + else: |
| 89 | + assert len(res.out) == len(msgs) |
| 90 | + for li1, li2 in zip(res.out, msgs): |
| 91 | + assert li1.text == li2 |
| 92 | + |
| 93 | + assert res.result == str_expected |
0 commit comments