-
Notifications
You must be signed in to change notification settings - Fork 45
Expand file tree
/
Copy pathtest_exceptions.py
More file actions
174 lines (143 loc) · 5.73 KB
/
Copy pathtest_exceptions.py
File metadata and controls
174 lines (143 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
"""
test_exceptions.py
Copyright 2020 Slycot team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
"""
import os
import subprocess
import sys
import pytest
from slycot import _wrapper
from slycot.exceptions import (SlycotError, SlycotParameterError,
SlycotWarning, raise_if_slycot_error)
def assert_docstring_parse(docstring, exception_class, erange, checkvars={}):
"""To check that a docstring can be parsed into exceptions
See also raise_if_slycot_error
Parameters
----------
docstring: str
Documentation string with exception definitions
exception_class: SlycotError or SlycotWarning
Subclass of Slycot specific Errors or Warnings expected to raise
erange: int or iterable with int or iterable of two-element iterables
of [IWARN, INFO] for which the documentation should have exception
text
checkvars: dict, optional
dict of variables for evaluation of <infospec> and formatting the
exception message
"""
# if erange is a simple integer, assume a continous range of errors
try:
erange = range(1, erange+1)
except TypeError:
pass
for e in erange:
try:
iwarn, info = e
except TypeError:
iwarn = None
info = e
if issubclass(exception_class, SlycotError):
with pytest.raises(exception_class) as ex_info:
raise_if_slycot_error(e, [], docstring, checkvars)
assert ex_info.value.info == info
elif issubclass(exception_class, SlycotWarning):
with pytest.warns(exception_class) as wm:
raise_if_slycot_error(e, [], docstring, checkvars)
assert wm[0].message.iwarn == iwarn
assert wm[0].message.info == info
else:
raise RuntimeError("Invalid test exception")
def test_standard_info_error():
"""Test the standard case of illegal arguments"""
with pytest.raises(SlycotParameterError) as ex_info:
raise_if_slycot_error(-2, ["a", "b"])
assert ex_info.value.info == -2
def test_unhandled_info_iwarn():
with pytest.raises(SlycotError) as ex_info:
raise_if_slycot_error(100, [], docstring="no valid docstring")
assert ex_info.value.info == 100
with pytest.warns(SlycotWarning) as wm:
raise_if_slycot_error([101, 0], [], docstring="no valid docstring")
raise_if_slycot_error(0, [], docstring="no valid docstring",
checkvars={'iwarn': 102})
assert wm[0].message.iwarn == 101
assert wm[0].message.info == 0
assert wm[1].message.iwarn == 102
assert wm[1].message.info == 0
def test_info_standard_i():
"""Test the handling of standard "`info = -i`
Raises
------
SlycotError
:info = -i: Non-standard msg, info is {info}, -i is -{i}
"""
# No i in check_vars: keep silent
raise_if_slycot_error(-1, docstring=test_info_standard_i.__doc__,
checkvars={'a': 1})
# -i does not match
raise_if_slycot_error(-1, docstring=test_info_standard_i.__doc__,
checkvars={'i': 2})
# -i matches, raise the error
with pytest.raises(SlycotError) as ex_info:
raise_if_slycot_error(-1, docstring=test_info_standard_i.__doc__,
checkvars={'i': 1})
assert str(ex_info.value) == "\nNon-standard msg, info is -1, -i is -1"
def test_infospec_nameerror():
"""Test infospec with unknown variable.
Raises
------
SlycotError
:info = v: We do not know {v}
"""
with pytest.raises(RuntimeError) as ex_info:
raise_if_slycot_error(-1, docstring=test_infospec_nameerror.__doc__,
checkvars={'a': 1})
assert str(ex_info.value) == "Unknown variable in infospec: info = v"
def test_infospec_syntaxerror():
"""Test invalid infospec.
Raises
------
SlycotError
:info i: Invalid expression
"""
with pytest.raises(RuntimeError) as ex_info:
raise_if_slycot_error(-1, docstring=test_infospec_syntaxerror.__doc__,
checkvars={'i': 1})
assert str(ex_info.value) == "Invalid infospec: info i"
# Test code for test_xerbla_override
CODE = """
import sys
sys.path.pop(0) # do not import from current directory ('')
from slycot._wrapper import __file__, ab08nd
print(__file__)
# equil='X' is invalid
out = ab08nd(1, 1, 1, [1], [1], [1], [1], equil='X')
print("INFO={}".format(out[-1]))
"""
def test_xerbla_override():
"""Test that Fortran routines calling XERBLA do not print to stdout."""
try:
out = subprocess.check_output([sys.executable, '-c', CODE],
stderr=subprocess.STDOUT,
universal_newlines=True)
except subprocess.CalledProcessError as cpe:
raise RuntimeError("Trying to call _wrapper.ab08nd() failed with "
"returncode {}.\n"
"Captured STDOUT: \n {}\n"
"Captured STDERR: \n {}\n"
"".format(cpe.returncode, cpe.stdout, cpe.stderr))
outlines = out.splitlines()
assert len(outlines) == 2
assert os.path.samefile(outlines[0], _wrapper.__file__)
assert outlines[1] == "INFO=-1"