Skip to content

Commit a5094e2

Browse files
authored
Merge pull request #135 from jed-frey/InputSanitization
Cleanup TransferFunction Input Sanitization
2 parents c4f1c34 + 8c997ff commit a5094e2

File tree

4 files changed

+377
-48
lines changed

4 files changed

+377
-48
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ __conda_*.txt
99
record.txt
1010
build.log
1111
*.egg-info/
12+
.eggs/
1213
.coverage
1314
doc/_build
1415
doc/generated
@@ -18,3 +19,7 @@ examples/.ipynb_checkpoints/
1819
.project
1920
Untitled*.ipynb
2021
*.idea/
22+
23+
# Files created by or for emacs (RMM, 29 Dec 2017)
24+
*~
25+
TAGS
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# input_element_int_test.py
2+
#
3+
# Author: Kangwon Lee (kangwonlee)
4+
# Date: 22 Oct 2017
5+
#
6+
# Unit tests contributed as part of PR #158, "SISO tf() may not work
7+
# with numpy arrays with numpy.int elements"
8+
#
9+
# Modified:
10+
# * 29 Dec 2017, RMM - updated file name and added header
11+
12+
import unittest
13+
import numpy as np
14+
import control as ctl
15+
16+
class TestTfInputIntElement(unittest.TestCase):
17+
# currently these do not pass
18+
def test_tf_den_with_numpy_int_element(self):
19+
num = 1
20+
den = np.convolve([1, 2, 1], [1, 1, 1])
21+
22+
sys = ctl.tf(num, den)
23+
24+
self.assertAlmostEqual(1.0, ctl.dcgain(sys))
25+
26+
def test_tf_num_with_numpy_int_element(self):
27+
num = np.convolve([1], [1, 1])
28+
den = np.convolve([1, 2, 1], [1, 1, 1])
29+
30+
sys = ctl.tf(num, den)
31+
32+
self.assertAlmostEqual(1.0, ctl.dcgain(sys))
33+
34+
# currently these pass
35+
def test_tf_input_with_int_element_works(self):
36+
num = 1
37+
den = np.convolve([1.0, 2, 1], [1, 1, 1])
38+
39+
sys = ctl.tf(num, den)
40+
41+
self.assertAlmostEqual(1.0, ctl.dcgain(sys))
42+
43+
def test_ss_input_with_int_element(self):
44+
ident = np.matrix(np.identity(2), dtype=int)
45+
a = np.matrix([[0, 1],
46+
[-1, -2]], dtype=int) * ident
47+
b = np.matrix([[0],
48+
[1]], dtype=int)
49+
c = np.matrix([[0, 1]], dtype=int)
50+
d = 0
51+
52+
sys = ctl.ss(a, b, c, d)
53+
sys2 = ctl.ss2tf(sys)
54+
self.assertAlmostEqual(ctl.dcgain(sys), ctl.dcgain(sys2))

control/tests/xferfcn_input_test.py

+261
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
#!/usr/bin/env python
2+
#
3+
# xferfcn_input_test.py - test inputs to TransferFunction class
4+
# jed-frey, 18 Feb 2017 (based on xferfcn_test.py)
5+
6+
import unittest
7+
import numpy as np
8+
9+
from numpy import int, int8, int16, int32, int64
10+
from numpy import float, float16, float32, float64, float128
11+
from numpy import all, ndarray, array
12+
13+
from control.xferfcn import _cleanPart
14+
15+
class TestXferFcnInput(unittest.TestCase):
16+
"""These are tests for functionality of cleaning and validating
17+
XferFucnInput."""
18+
19+
# Tests for raising exceptions.
20+
def testBadInputType(self):
21+
"""Give the part cleaner invalid input type."""
22+
23+
self.assertRaises(TypeError, _cleanPart, [[0., 1.], [2., 3.]])
24+
25+
def testBadInputType2(self):
26+
"""Give the part cleaner another invalid input type."""
27+
self.assertRaises(TypeError, _cleanPart, [1,"a"])
28+
29+
def testScalar(self):
30+
"""Test single scalar value."""
31+
num = 1
32+
num_ = _cleanPart(num)
33+
34+
assert isinstance(num_, list)
35+
assert np.all([isinstance(part, list) for part in num_])
36+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
37+
38+
def testListScalar(self):
39+
"""Test single scalar value in list."""
40+
num = [1]
41+
num_ = _cleanPart(num)
42+
43+
assert isinstance(num_, list)
44+
assert np.all([isinstance(part, list) for part in num_])
45+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
46+
47+
def testTupleScalar(self):
48+
"""Test single scalar value in tuple."""
49+
num = (1)
50+
num_ = _cleanPart(num)
51+
52+
assert isinstance(num_, list)
53+
assert np.all([isinstance(part, list) for part in num_])
54+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
55+
56+
def testList(self):
57+
"""Test multiple values in a list."""
58+
num = [1, 2]
59+
num_ = _cleanPart(num)
60+
61+
assert isinstance(num_, list)
62+
assert np.all([isinstance(part, list) for part in num_])
63+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
64+
65+
def testTuple(self):
66+
"""Test multiple values in tuple."""
67+
num = (1, 2)
68+
num_ = _cleanPart(num)
69+
70+
assert isinstance(num_, list)
71+
assert np.all([isinstance(part, list) for part in num_])
72+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
73+
74+
def testAllScalarTypes(self):
75+
"""Test single scalar value for all valid data types."""
76+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
77+
num = dtype(1)
78+
num_ = _cleanPart(num)
79+
80+
assert isinstance(num_, list)
81+
assert np.all([isinstance(part, list) for part in num_])
82+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
83+
84+
def testNpArray(self):
85+
"""Test multiple values in numpy array."""
86+
num = np.array([1, 2])
87+
num_ = _cleanPart(num)
88+
89+
assert isinstance(num_, list)
90+
assert np.all([isinstance(part, list) for part in num_])
91+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
92+
93+
def testAllNumpyArrayTypes(self):
94+
"""Test scalar value in numpy array of ndim=0 for all data types."""
95+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
96+
num = np.array(1, dtype=dtype)
97+
num_ = _cleanPart(num)
98+
99+
assert isinstance(num_, list)
100+
assert np.all([isinstance(part, list) for part in num_])
101+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
102+
103+
def testAllNumpyArrayTypes2(self):
104+
"""Test numpy array for all types."""
105+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
106+
num = np.array([1, 2], dtype=dtype)
107+
num_ = _cleanPart(num)
108+
109+
assert isinstance(num_, list)
110+
assert np.all([isinstance(part, list) for part in num_])
111+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
112+
113+
def testListAllTypes(self):
114+
"""Test list of a single value for all data types."""
115+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
116+
num = [dtype(1)]
117+
num_ = _cleanPart(num)
118+
assert isinstance(num_, list)
119+
assert np.all([isinstance(part, list) for part in num_])
120+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
121+
122+
def testListAllTypes2(self):
123+
"""List of list of numbers of all data types."""
124+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
125+
num = [dtype(1), dtype(2)]
126+
num_ = _cleanPart(num)
127+
assert isinstance(num_, list)
128+
assert np.all([isinstance(part, list) for part in num_])
129+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
130+
131+
def testTupleAllTypes(self):
132+
"""Test tuple of a single value for all data types."""
133+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
134+
num = (dtype(1),)
135+
num_ = _cleanPart(num)
136+
assert isinstance(num_, list)
137+
assert np.all([isinstance(part, list) for part in num_])
138+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
139+
140+
def testTupleAllTypes2(self):
141+
"""Test tuple of a single value for all data types."""
142+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
143+
num = (dtype(1), dtype(2))
144+
num_ = _cleanPart(num)
145+
assert isinstance(num_, list)
146+
assert np.all([isinstance(part, list) for part in num_])
147+
np.testing.assert_array_equal(num_[0][0], array([1, 2], dtype=float))
148+
149+
def testListListListInt(self):
150+
""" Test an int in a list of a list of a list."""
151+
num = [[[1]]]
152+
num_ = _cleanPart(num)
153+
assert isinstance(num_, list)
154+
assert np.all([isinstance(part, list) for part in num_])
155+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
156+
157+
def testListListListFloat(self):
158+
""" Test a float in a list of a list of a list."""
159+
num = [[[1.0]]]
160+
num_ = _cleanPart(num)
161+
assert isinstance(num_, list)
162+
assert np.all([isinstance(part, list) for part in num_])
163+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
164+
165+
def testListListListInts(self):
166+
"""Test 2 lists of ints in a list in a list."""
167+
num = [[[1,1],[2,2]]]
168+
num_ = _cleanPart(num)
169+
170+
assert isinstance(num_, list)
171+
assert np.all([isinstance(part, list) for part in num_])
172+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
173+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
174+
175+
def testListListListFloats(self):
176+
"""Test 2 lists of ints in a list in a list."""
177+
num = [[[1.0,1.0],[2.0,2.0]]]
178+
num_ = _cleanPart(num)
179+
180+
assert isinstance(num_, list)
181+
assert np.all([isinstance(part, list) for part in num_])
182+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
183+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
184+
185+
def testListListArray(self):
186+
"""List of list of numpy arrays for all valid types."""
187+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
188+
num = [[array([1,1], dtype=dtype),array([2,2], dtype=dtype)]]
189+
num_ = _cleanPart(num)
190+
191+
assert isinstance(num_, list)
192+
assert np.all([isinstance(part, list) for part in num_])
193+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
194+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
195+
196+
def testTupleListArray(self):
197+
"""Tuple of list of numpy arrays for all valid types."""
198+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
199+
num = ([array([1,1], dtype=dtype),array([2,2], dtype=dtype)],)
200+
num_ = _cleanPart(num)
201+
202+
assert isinstance(num_, list)
203+
assert np.all([isinstance(part, list) for part in num_])
204+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
205+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
206+
207+
def testListTupleArray(self):
208+
"""List of tuple of numpy array for all valid types."""
209+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
210+
num = [(array([1,1], dtype=dtype),array([2,2], dtype=dtype))]
211+
num_ = _cleanPart(num)
212+
213+
assert isinstance(num_, list)
214+
assert np.all([isinstance(part, list) for part in num_])
215+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
216+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
217+
218+
def testTupleTuplesArrays(self):
219+
"""Tuple of tuples of numpy arrays for all valid types."""
220+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
221+
num = ((array([1,1], dtype=dtype),array([2,2], dtype=dtype)),
222+
(array([3,4], dtype=dtype),array([4,4], dtype=dtype)))
223+
num_ = _cleanPart(num)
224+
225+
assert isinstance(num_, list)
226+
assert np.all([isinstance(part, list) for part in num_])
227+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
228+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
229+
230+
def testListTuplesArrays(self):
231+
"""List of tuples of numpy arrays for all valid types."""
232+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
233+
num = [(array([1,1], dtype=dtype),array([2,2], dtype=dtype)),
234+
(array([3,4], dtype=dtype),array([4,4], dtype=dtype))]
235+
num_ = _cleanPart(num)
236+
237+
assert isinstance(num_, list)
238+
assert np.all([isinstance(part, list) for part in num_])
239+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
240+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
241+
242+
def testListListArrays(self):
243+
"""List of list of numpy arrays for all valid types."""
244+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
245+
num = [[array([1,1], dtype=dtype),array([2,2], dtype=dtype)],
246+
[array([3,3], dtype=dtype),array([4,4], dtype=dtype)]]
247+
num_ = _cleanPart(num)
248+
249+
assert len(num_) == 2
250+
assert np.all([isinstance(part, list) for part in num_])
251+
assert np.all([len(part) == 2 for part in num_])
252+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
253+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
254+
np.testing.assert_array_equal(num_[1][0], array([3.0, 3.0], dtype=float))
255+
np.testing.assert_array_equal(num_[1][1], array([4.0, 4.0], dtype=float))
256+
257+
def suite():
258+
return unittest.TestLoader().loadTestsFromTestCase(TestXferFcnInput)
259+
260+
if __name__ == "__main__":
261+
unittest.main()

0 commit comments

Comments
 (0)