tests: fix remove unnecessary workaround for some unittest assertions.
This commit is contained in:
parent
c75fa45fd8
commit
8117ef6692
|
@ -46,19 +46,19 @@ class PinsTestCase(FHDLTestCase):
|
|||
self.assertEqual(p.map_names(mapping, p), ["A1"])
|
||||
|
||||
def test_wrong_names(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Names must be a whitespace-separated string, not ['A0', 'A1', 'A2']"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Names must be a whitespace-separated string, not \['A0', 'A1', 'A2'\]$"):
|
||||
p = Pins(["A0", "A1", "A2"])
|
||||
|
||||
def test_wrong_dir(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not 'wrong'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not 'wrong'$"):
|
||||
p = Pins("A0 A1", dir="wrong")
|
||||
|
||||
def test_wrong_conn(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Connector must be None or a pair of string (connector name) and "
|
||||
"integer/string (connector number), not ('foo', None)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Connector must be None or a pair of string \(connector name\) and "
|
||||
r"integer\/string \(connector number\), not \('foo', None\)$")):
|
||||
p = Pins("A0 A1", conn=("foo", None))
|
||||
|
||||
def test_wrong_map_names(self):
|
||||
|
@ -66,14 +66,14 @@ class PinsTestCase(FHDLTestCase):
|
|||
mapping = {
|
||||
"pmod_0:0": "A0",
|
||||
}
|
||||
with self.assertRaises(NameError,
|
||||
msg="Resource (pins io pmod_0:0 pmod_0:1 pmod_0:2) refers to nonexistent "
|
||||
"connector pin pmod_0:1"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
(r"^Resource \(pins io pmod_0:0 pmod_0:1 pmod_0:2\) refers to nonexistent "
|
||||
r"connector pin pmod_0:1$")):
|
||||
p.map_names(mapping, p)
|
||||
|
||||
def test_wrong_assert_width(self):
|
||||
with self.assertRaises(AssertionError,
|
||||
msg="3 names are specified (0 1 2), but 4 names are expected"):
|
||||
with self.assertRaisesRegex(AssertionError,
|
||||
r"^3 names are specified \(0 1 2\), but 4 names are expected$"):
|
||||
Pins("0 1 2", assert_width=4)
|
||||
|
||||
|
||||
|
@ -108,14 +108,14 @@ class DiffPairsTestCase(FHDLTestCase):
|
|||
self.assertEqual(dp.n.dir, "o")
|
||||
|
||||
def test_wrong_width(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Positive and negative pins must have the same width, but (pins io A0) "
|
||||
"and (pins io B0 B1) do not"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Positive and negative pins must have the same width, but \(pins io A0\) "
|
||||
r"and \(pins io B0 B1\) do not$")):
|
||||
dp = DiffPairs("A0", "B0 B1")
|
||||
|
||||
def test_wrong_assert_width(self):
|
||||
with self.assertRaises(AssertionError,
|
||||
msg="3 names are specified (0 1 2), but 4 names are expected"):
|
||||
with self.assertRaisesRegex(AssertionError,
|
||||
r"^3 names are specified \(0 1 2\), but 4 names are expected$"):
|
||||
DiffPairs("0 1 2", "3 4 5", assert_width=4)
|
||||
|
||||
|
||||
|
@ -137,8 +137,8 @@ class AttrsTestCase(FHDLTestCase):
|
|||
self.assertEqual(repr(a), "(attrs FOO={!r})".format(fn))
|
||||
|
||||
def test_wrong_value(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Value of attribute FOO must be None, int, str, or callable, not 1.0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Value of attribute FOO must be None, int, str, or callable, not 1\.0$"):
|
||||
a = Attrs(FOO=1.0)
|
||||
|
||||
|
||||
|
@ -187,42 +187,42 @@ class SubsignalTestCase(FHDLTestCase):
|
|||
self.assertEqual(s.clock.frequency, 1e6)
|
||||
|
||||
def test_wrong_empty_io(self):
|
||||
with self.assertRaises(ValueError, msg="Missing I/O constraints"):
|
||||
with self.assertRaisesRegex(ValueError, r"^Missing I\/O constraints$"):
|
||||
s = Subsignal("a")
|
||||
|
||||
def test_wrong_io(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Constraint must be one of Pins, DiffPairs, Subsignal, Attrs, or Clock, "
|
||||
"not 'wrong'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Constraint must be one of Pins, DiffPairs, Subsignal, Attrs, or Clock, "
|
||||
r"not 'wrong'$")):
|
||||
s = Subsignal("a", "wrong")
|
||||
|
||||
def test_wrong_pins(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Pins and DiffPairs are incompatible with other location or subsignal "
|
||||
"constraints, but (pins io A1) appears after (pins io A0)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Pins and DiffPairs are incompatible with other location or subsignal "
|
||||
r"constraints, but \(pins io A1\) appears after \(pins io A0\)$")):
|
||||
s = Subsignal("a", Pins("A0"), Pins("A1"))
|
||||
|
||||
def test_wrong_diffpairs(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Pins and DiffPairs are incompatible with other location or subsignal "
|
||||
"constraints, but (pins io A1) appears after (diffpairs io (p A0) (n B0))"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Pins and DiffPairs are incompatible with other location or subsignal "
|
||||
r"constraints, but \(pins io A1\) appears after \(diffpairs io \(p A0\) \(n B0\)\)$")):
|
||||
s = Subsignal("a", DiffPairs("A0", "B0"), Pins("A1"))
|
||||
|
||||
def test_wrong_subsignals(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Pins and DiffPairs are incompatible with other location or subsignal "
|
||||
"constraints, but (pins io B0) appears after (subsignal b (pins io A0))"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Pins and DiffPairs are incompatible with other location or subsignal "
|
||||
r"constraints, but \(pins io B0\) appears after \(subsignal b \(pins io A0\)\)$")):
|
||||
s = Subsignal("a", Subsignal("b", Pins("A0")), Pins("B0"))
|
||||
|
||||
def test_wrong_clock(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Clock constraint can only be applied to Pins or DiffPairs, not "
|
||||
"(subsignal b (pins io A0))"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Clock constraint can only be applied to Pins or DiffPairs, not "
|
||||
r"\(subsignal b \(pins io A0\)\)$")):
|
||||
s = Subsignal("a", Subsignal("b", Pins("A0")), Clock(1e6))
|
||||
|
||||
def test_wrong_clock_many(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Clock constraint can be applied only once"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Clock constraint can be applied only once$"):
|
||||
s = Subsignal("a", Pins("A0"), Clock(1e6), Clock(1e7))
|
||||
|
||||
|
||||
|
@ -309,20 +309,20 @@ class ConnectorTestCase(FHDLTestCase):
|
|||
self.assertEqual(c.number, "A")
|
||||
|
||||
def test_conn_wrong_name(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Connector must be None or a pair of string (connector name) and "
|
||||
"integer/string (connector number), not ('foo', None)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Connector must be None or a pair of string \(connector name\) and "
|
||||
r"integer\/string \(connector number\), not \('foo', None\)$")):
|
||||
Connector("ext", "A", "0 1 2", conn=("foo", None))
|
||||
|
||||
def test_wrong_io(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Connector I/Os must be a dictionary or a string, not []"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Connector I\/Os must be a dictionary or a string, not \[\]$"):
|
||||
Connector("pmod", 0, [])
|
||||
|
||||
def test_wrong_dict_key_value(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Connector pin name must be a string, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Connector pin name must be a string, not 0$"):
|
||||
Connector("pmod", 0, {0: "A"})
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Platform pin name must be a string, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Platform pin name must be a string, not 0$"):
|
||||
Connector("pmod", 0, {"A": 0})
|
||||
|
|
|
@ -36,17 +36,17 @@ class PlatformTestCase(FHDLTestCase):
|
|||
self.assertEqual(self.platform.extra_files["x.txt"], f.read())
|
||||
|
||||
def test_add_file_wrong_filename(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="File name must be a string, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^File name must be a string, not 1$"):
|
||||
self.platform.add_file(1, "")
|
||||
|
||||
def test_add_file_wrong_contents(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="File contents must be str, bytes, or a file-like object, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^File contents must be str, bytes, or a file-like object, not 1$"):
|
||||
self.platform.add_file("foo", 1)
|
||||
|
||||
def test_add_file_wrong_duplicate(self):
|
||||
self.platform.add_file("foo", "")
|
||||
with self.assertRaises(ValueError,
|
||||
msg="File 'foo' already exists"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^File 'foo' already exists$"):
|
||||
self.platform.add_file("foo", "bar")
|
||||
|
|
|
@ -208,43 +208,43 @@ class ResourceManagerTestCase(FHDLTestCase):
|
|||
])
|
||||
|
||||
def test_wrong_resources(self):
|
||||
with self.assertRaises(TypeError, msg="Object 'wrong' is not a Resource"):
|
||||
with self.assertRaisesRegex(TypeError, r"^Object 'wrong' is not a Resource$"):
|
||||
self.cm.add_resources(['wrong'])
|
||||
|
||||
def test_wrong_resources_duplicate(self):
|
||||
with self.assertRaises(NameError,
|
||||
msg="Trying to add (resource user_led 0 (pins o A1)), but "
|
||||
"(resource user_led 0 (pins o A0)) has the same name and number"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
(r"^Trying to add \(resource user_led 0 \(pins o A1\)\), but "
|
||||
r"\(resource user_led 0 \(pins o A0\)\) has the same name and number$")):
|
||||
self.cm.add_resources([Resource("user_led", 0, Pins("A1", dir="o"))])
|
||||
|
||||
def test_wrong_connectors(self):
|
||||
with self.assertRaises(TypeError, msg="Object 'wrong' is not a Connector"):
|
||||
with self.assertRaisesRegex(TypeError, r"^Object 'wrong' is not a Connector$"):
|
||||
self.cm.add_connectors(['wrong'])
|
||||
|
||||
def test_wrong_connectors_duplicate(self):
|
||||
with self.assertRaises(NameError,
|
||||
msg="Trying to add (connector pmod 0 1=>1 2=>2), but "
|
||||
"(connector pmod 0 1=>B0 2=>B1 3=>B2 4=>B3) has the same name and number"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
(r"^Trying to add \(connector pmod 0 1=>1 2=>2\), but "
|
||||
r"\(connector pmod 0 1=>B0 2=>B1 3=>B2 4=>B3\) has the same name and number$")):
|
||||
self.cm.add_connectors([Connector("pmod", 0, "1 2")])
|
||||
|
||||
def test_wrong_lookup(self):
|
||||
with self.assertRaises(ResourceError,
|
||||
msg="Resource user_led#1 does not exist"):
|
||||
with self.assertRaisesRegex(ResourceError,
|
||||
r"^Resource user_led#1 does not exist$"):
|
||||
r = self.cm.lookup("user_led", 1)
|
||||
|
||||
def test_wrong_clock_signal(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Object None is not a Signal"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Object None is not a Signal$"):
|
||||
self.cm.add_clock_constraint(None, 10e6)
|
||||
|
||||
def test_wrong_clock_frequency(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Frequency must be a number, not None"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Frequency must be a number, not None$"):
|
||||
self.cm.add_clock_constraint(Signal(), None)
|
||||
|
||||
def test_wrong_request_duplicate(self):
|
||||
with self.assertRaises(ResourceError,
|
||||
msg="Resource user_led#0 has already been requested"):
|
||||
with self.assertRaisesRegex(ResourceError,
|
||||
r"^Resource user_led#0 has already been requested$"):
|
||||
self.cm.request("user_led", 0)
|
||||
self.cm.request("user_led", 0)
|
||||
|
||||
|
@ -253,46 +253,46 @@ class ResourceManagerTestCase(FHDLTestCase):
|
|||
Resource("clk20", 0, Pins("H1", dir="i")),
|
||||
])
|
||||
self.cm.request("clk100", 0)
|
||||
with self.assertRaises(ResourceError,
|
||||
msg="Resource component clk20_0 uses physical pin H1, but it is already "
|
||||
"used by resource component clk100_0 that was requested earlier"):
|
||||
with self.assertRaisesRegex(ResourceError,
|
||||
(r"^Resource component clk20_0 uses physical pin H1, but it is already "
|
||||
r"used by resource component clk100_0 that was requested earlier$")):
|
||||
self.cm.request("clk20", 0)
|
||||
|
||||
def test_wrong_request_with_dir(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Direction must be one of \"i\", \"o\", \"oe\", \"io\", or \"-\", "
|
||||
"not 'wrong'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Direction must be one of \"i\", \"o\", \"oe\", \"io\", or \"-\", "
|
||||
r"not 'wrong'$")):
|
||||
user_led = self.cm.request("user_led", 0, dir="wrong")
|
||||
|
||||
def test_wrong_request_with_dir_io(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Direction of (pins o A0) cannot be changed from \"o\" to \"i\"; direction "
|
||||
"can be changed from \"io\" to \"i\", \"o\", or \"oe\", or from anything "
|
||||
"to \"-\""):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
(r"^Direction of \(pins o A0\) cannot be changed from \"o\" to \"i\"; direction "
|
||||
r"can be changed from \"io\" to \"i\", \"o\", or \"oe\", or from anything "
|
||||
r"to \"-\"$")):
|
||||
user_led = self.cm.request("user_led", 0, dir="i")
|
||||
|
||||
def test_wrong_request_with_dir_dict(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Directions must be a dict, not 'i', because (resource i2c 0 (subsignal scl "
|
||||
"(pins o N10)) (subsignal sda (pins io N11))) "
|
||||
"has subsignals"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Directions must be a dict, not 'i', because \(resource i2c 0 \(subsignal scl "
|
||||
r"\(pins o N10\)\) \(subsignal sda \(pins io N11\)\)\) "
|
||||
r"has subsignals$")):
|
||||
i2c = self.cm.request("i2c", 0, dir="i")
|
||||
|
||||
def test_wrong_request_with_wrong_xdr(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Data rate of (pins o A0) must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Data rate of \(pins o A0\) must be a non-negative integer, not -1$"):
|
||||
user_led = self.cm.request("user_led", 0, xdr=-1)
|
||||
|
||||
def test_wrong_request_with_xdr_dict(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Data rate must be a dict, not 2, because (resource i2c 0 (subsignal scl "
|
||||
"(pins o N10)) (subsignal sda (pins io N11))) "
|
||||
"has subsignals"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Data rate must be a dict, not 2, because \(resource i2c 0 \(subsignal scl "
|
||||
r"\(pins o N10\)\) \(subsignal sda \(pins io N11\)\)\) "
|
||||
r"has subsignals$"):
|
||||
i2c = self.cm.request("i2c", 0, xdr=2)
|
||||
|
||||
def test_wrong_clock_constraint_twice(self):
|
||||
clk100 = self.cm.request("clk100")
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Cannot add clock constraint on (sig clk100_0__i), which is already "
|
||||
"constrained to 100000000.0 Hz"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
(r"^Cannot add clock constraint on \(sig clk100_0__i\), which is already "
|
||||
r"constrained to 100000000\.0 Hz$")):
|
||||
self.cm.add_clock_constraint(clk100.i, 1e6)
|
||||
|
|
|
@ -35,18 +35,18 @@ class ShapeTestCase(FHDLTestCase):
|
|||
self.assertEqual(s3.signed, True)
|
||||
|
||||
def test_make_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Width must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Width must be a non-negative integer, not -1$"):
|
||||
Shape(-1)
|
||||
|
||||
def test_compare_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shapes may be compared with other Shapes and (int, bool) tuples, not 'hi'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shapes may be compared with other Shapes and \(int, bool\) tuples, not 'hi'$"):
|
||||
Shape(1, True) == 'hi'
|
||||
|
||||
def test_compare_tuple_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shapes may be compared with other Shapes and (int, bool) tuples, not (2, 3)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shapes may be compared with other Shapes and \(int, bool\) tuples, not \(2, 3\)$"):
|
||||
Shape(1, True) == (2, 3)
|
||||
|
||||
def test_repr(self):
|
||||
|
@ -84,8 +84,8 @@ class ShapeTestCase(FHDLTestCase):
|
|||
self.assertEqual(s1.signed, False)
|
||||
|
||||
def test_cast_int_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Width must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Width must be a non-negative integer, not -1$"):
|
||||
Shape.cast(-1)
|
||||
|
||||
def test_cast_tuple(self):
|
||||
|
@ -98,8 +98,8 @@ class ShapeTestCase(FHDLTestCase):
|
|||
def test_cast_tuple_wrong(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Width must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Width must be a non-negative integer, not -1$"):
|
||||
Shape.cast((-1, True))
|
||||
|
||||
def test_cast_range(self):
|
||||
|
@ -134,13 +134,13 @@ class ShapeTestCase(FHDLTestCase):
|
|||
self.assertEqual(s2.signed, True)
|
||||
|
||||
def test_cast_enum_bad(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Only enumerations with integer values can be used as value shapes"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Only enumerations with integer values can be used as value shapes$"):
|
||||
Shape.cast(StringEnum)
|
||||
|
||||
def test_cast_bad(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Object 'foo' cannot be used as value shape"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Object 'foo' cannot be used as value shape$"):
|
||||
Shape.cast("foo")
|
||||
|
||||
|
||||
|
@ -150,8 +150,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
self.assertIsInstance(Value.cast(True), Const)
|
||||
c = Const(0)
|
||||
self.assertIs(Value.cast(c), c)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Object 'str' cannot be converted to an nMigen value"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Object 'str' cannot be converted to an nMigen value$"):
|
||||
Value.cast("str")
|
||||
|
||||
def test_cast_enum(self):
|
||||
|
@ -163,13 +163,13 @@ class ValueTestCase(FHDLTestCase):
|
|||
self.assertEqual(e2.shape(), signed(2))
|
||||
|
||||
def test_cast_enum_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Only enumerations with integer values can be used as value shapes"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Only enumerations with integer values can be used as value shapes$"):
|
||||
Value.cast(StringEnum.FOO)
|
||||
|
||||
def test_bool(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Attempted to convert nMigen value to Python boolean"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Attempted to convert nMigen value to Python boolean$"):
|
||||
if Const(0):
|
||||
pass
|
||||
|
||||
|
@ -185,8 +185,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
self.assertIsInstance(s2, Slice)
|
||||
self.assertEqual(s2.start, 3)
|
||||
self.assertEqual(s2.stop, 4)
|
||||
with self.assertRaises(IndexError,
|
||||
msg="Cannot index 5 bits into 4-bit value"):
|
||||
with self.assertRaisesRegex(IndexError,
|
||||
r"^Cannot index 5 bits into 4-bit value$"):
|
||||
Const(10)[5]
|
||||
|
||||
def test_getitem_slice(self):
|
||||
|
@ -211,8 +211,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
self.assertEqual(s3.parts[2].stop, 5)
|
||||
|
||||
def test_getitem_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Cannot index value with 'str'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Cannot index value with 'str'$"):
|
||||
Const(31)["str"]
|
||||
|
||||
def test_shift_left(self):
|
||||
|
@ -240,8 +240,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
"(s (slice (const 9'sd-256) 9:9))")
|
||||
|
||||
def test_shift_left_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shift amount must be an integer, not 'str'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shift amount must be an integer, not 'str'$"):
|
||||
Const(31).shift_left("str")
|
||||
|
||||
def test_shift_right(self):
|
||||
|
@ -269,8 +269,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
"(s (slice (const 9'sd-256) 9:9))")
|
||||
|
||||
def test_shift_right_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shift amount must be an integer, not 'str'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shift amount must be an integer, not 'str'$"):
|
||||
Const(31).shift_left("str")
|
||||
|
||||
def test_rotate_left(self):
|
||||
|
@ -284,8 +284,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
"(cat (slice (const 9'd256) 7:9) (slice (const 9'd256) 0:7))")
|
||||
|
||||
def test_rotate_left_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Rotate amount must be an integer, not 'str'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Rotate amount must be an integer, not 'str'$"):
|
||||
Const(31).rotate_left("str")
|
||||
|
||||
def test_rotate_right(self):
|
||||
|
@ -299,8 +299,8 @@ class ValueTestCase(FHDLTestCase):
|
|||
"(cat (slice (const 9'd256) 2:9) (slice (const 9'd256) 0:2))")
|
||||
|
||||
def test_rotate_right_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Rotate amount must be an integer, not 'str'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Rotate amount must be an integer, not 'str'$"):
|
||||
Const(31).rotate_right("str")
|
||||
|
||||
|
||||
|
@ -318,8 +318,8 @@ class ConstTestCase(FHDLTestCase):
|
|||
self.assertEqual(Const(0, unsigned(0)).shape(), unsigned(0))
|
||||
|
||||
def test_shape_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Width must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Width must be a non-negative integer, not -1$"):
|
||||
Const(1, -1)
|
||||
|
||||
def test_normalization(self):
|
||||
|
@ -413,8 +413,8 @@ class OperatorTestCase(FHDLTestCase):
|
|||
self.assertEqual(v5.shape(), unsigned(4))
|
||||
|
||||
def test_mod_wrong(self):
|
||||
with self.assertRaises(NotImplementedError,
|
||||
msg="Division by a signed value is not supported"):
|
||||
with self.assertRaisesRegex(NotImplementedError,
|
||||
r"^Division by a signed value is not supported$"):
|
||||
Const(0, signed(4)) % Const(0, signed(6))
|
||||
|
||||
def test_floordiv(self):
|
||||
|
@ -427,8 +427,8 @@ class OperatorTestCase(FHDLTestCase):
|
|||
self.assertEqual(v5.shape(), unsigned(4))
|
||||
|
||||
def test_floordiv_wrong(self):
|
||||
with self.assertRaises(NotImplementedError,
|
||||
msg="Division by a signed value is not supported"):
|
||||
with self.assertRaisesRegex(NotImplementedError,
|
||||
r"^Division by a signed value is not supported$"):
|
||||
Const(0, signed(4)) // Const(0, signed(6))
|
||||
|
||||
def test_and(self):
|
||||
|
@ -476,11 +476,11 @@ class OperatorTestCase(FHDLTestCase):
|
|||
self.assertEqual(v1.shape(), unsigned(11))
|
||||
|
||||
def test_shl_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shift amount must be unsigned"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shift amount must be unsigned$"):
|
||||
1 << Const(0, signed(6))
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shift amount must be unsigned"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shift amount must be unsigned$"):
|
||||
Const(1, unsigned(4)) << -1
|
||||
|
||||
def test_shr(self):
|
||||
|
@ -489,11 +489,11 @@ class OperatorTestCase(FHDLTestCase):
|
|||
self.assertEqual(v1.shape(), unsigned(4))
|
||||
|
||||
def test_shr_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shift amount must be unsigned"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shift amount must be unsigned$"):
|
||||
1 << Const(0, signed(6))
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Shift amount must be unsigned"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Shift amount must be unsigned$"):
|
||||
Const(1, unsigned(4)) << -1
|
||||
|
||||
def test_lt(self):
|
||||
|
@ -588,25 +588,25 @@ class OperatorTestCase(FHDLTestCase):
|
|||
|
||||
def test_matches_width_wrong(self):
|
||||
s = Signal(4)
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Match pattern '--' must have the same width as match value (which is 4)"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Match pattern '--' must have the same width as match value \(which is 4\)$"):
|
||||
s.matches("--")
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Match pattern '10110' is wider than match value (which has width 4); "
|
||||
"comparison will never be true"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
(r"^Match pattern '10110' is wider than match value \(which has width 4\); "
|
||||
r"comparison will never be true$")):
|
||||
s.matches(0b10110)
|
||||
|
||||
def test_matches_bits_wrong(self):
|
||||
s = Signal(4)
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Match pattern 'abc' must consist of 0, 1, and - (don't care) bits, "
|
||||
"and may include whitespace"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
(r"^Match pattern 'abc' must consist of 0, 1, and - \(don't care\) bits, "
|
||||
r"and may include whitespace$")):
|
||||
s.matches("abc")
|
||||
|
||||
def test_matches_pattern_wrong(self):
|
||||
s = Signal(4)
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Match pattern must be an integer, a string, or an enumeration, not 1.0"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Match pattern must be an integer, a string, or an enumeration, not 1\.0$"):
|
||||
s.matches(1.0)
|
||||
|
||||
def test_hash(self):
|
||||
|
@ -630,23 +630,23 @@ class SliceTestCase(FHDLTestCase):
|
|||
self.assertEqual((s1.start, s1.stop), (4, 7))
|
||||
|
||||
def test_start_end_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Slice start must be an integer, not 'x'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Slice start must be an integer, not 'x'$"):
|
||||
Slice(0, "x", 1)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Slice stop must be an integer, not 'x'"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Slice stop must be an integer, not 'x'$"):
|
||||
Slice(0, 1, "x")
|
||||
|
||||
def test_start_end_out_of_range(self):
|
||||
c = Const(0, 8)
|
||||
with self.assertRaises(IndexError,
|
||||
msg="Cannot start slice 10 bits into 8-bit value"):
|
||||
with self.assertRaisesRegex(IndexError,
|
||||
r"^Cannot start slice 10 bits into 8-bit value$"):
|
||||
Slice(c, 10, 12)
|
||||
with self.assertRaises(IndexError,
|
||||
msg="Cannot stop slice 12 bits into 8-bit value"):
|
||||
with self.assertRaisesRegex(IndexError,
|
||||
r"^Cannot stop slice 12 bits into 8-bit value$"):
|
||||
Slice(c, 0, 12)
|
||||
with self.assertRaises(IndexError,
|
||||
msg="Slice start 4 must be less than slice stop 2"):
|
||||
with self.assertRaisesRegex(IndexError,
|
||||
r"^Slice start 4 must be less than slice stop 2$"):
|
||||
Slice(c, 4, 2)
|
||||
|
||||
def test_repr(self):
|
||||
|
@ -842,8 +842,8 @@ class SignalTestCase(FHDLTestCase):
|
|||
self.assertEqual(s11.shape(), unsigned(1))
|
||||
|
||||
def test_shape_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Width must be a non-negative integer, not -10"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Width must be a non-negative integer, not -10$"):
|
||||
Signal(-10)
|
||||
|
||||
def test_name(self):
|
||||
|
@ -860,20 +860,20 @@ class SignalTestCase(FHDLTestCase):
|
|||
def test_reset_enum(self):
|
||||
s1 = Signal(2, reset=UnsignedEnum.BAR)
|
||||
self.assertEqual(s1.reset, 2)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Reset value has to be an int or an integral Enum"
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Reset value has to be an int or an integral Enum$"
|
||||
):
|
||||
Signal(1, reset=StringEnum.FOO)
|
||||
|
||||
def test_reset_narrow(self):
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Reset value 8 requires 4 bits to represent, but the signal only has 3 bits"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
r"^Reset value 8 requires 4 bits to represent, but the signal only has 3 bits$"):
|
||||
Signal(3, reset=8)
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Reset value 4 requires 4 bits to represent, but the signal only has 3 bits"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
r"^Reset value 4 requires 4 bits to represent, but the signal only has 3 bits$"):
|
||||
Signal(signed(3), reset=4)
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Reset value -5 requires 4 bits to represent, but the signal only has 3 bits"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
r"^Reset value -5 requires 4 bits to represent, but the signal only has 3 bits$"):
|
||||
Signal(signed(3), reset=-5)
|
||||
|
||||
def test_attrs(self):
|
||||
|
@ -928,8 +928,8 @@ class ClockSignalTestCase(FHDLTestCase):
|
|||
s2 = ClockSignal("pix")
|
||||
self.assertEqual(s2.domain, "pix")
|
||||
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Clock domain name must be a string, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Clock domain name must be a string, not 1$"):
|
||||
ClockSignal(1)
|
||||
|
||||
def test_shape(self):
|
||||
|
@ -942,8 +942,8 @@ class ClockSignalTestCase(FHDLTestCase):
|
|||
self.assertEqual(repr(s1), "(clk sync)")
|
||||
|
||||
def test_wrong_name_comb(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'comb' does not have a clock"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'comb' does not have a clock$"):
|
||||
ClockSignal("comb")
|
||||
|
||||
|
||||
|
@ -954,8 +954,8 @@ class ResetSignalTestCase(FHDLTestCase):
|
|||
s2 = ResetSignal("pix")
|
||||
self.assertEqual(s2.domain, "pix")
|
||||
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Clock domain name must be a string, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Clock domain name must be a string, not 1$"):
|
||||
ResetSignal(1)
|
||||
|
||||
def test_shape(self):
|
||||
|
@ -968,8 +968,8 @@ class ResetSignalTestCase(FHDLTestCase):
|
|||
self.assertEqual(repr(s1), "(rst sync)")
|
||||
|
||||
def test_wrong_name_comb(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'comb' does not have a reset"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'comb' does not have a reset$"):
|
||||
ResetSignal("comb")
|
||||
|
||||
|
||||
|
@ -1014,19 +1014,19 @@ class SampleTestCase(FHDLTestCase):
|
|||
s3 = Sample(ResetSignal(), 1, "sync")
|
||||
|
||||
def test_wrong_value_operator(self):
|
||||
with self.assertRaises(TypeError,
|
||||
"Sampled value must be a signal or a constant, not "
|
||||
"(+ (sig $signal) (const 1'd1))"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Sampled value must be a signal or a constant, not "
|
||||
r"\(\+ \(sig \$signal\) \(const 1'd1\)\)$")):
|
||||
Sample(Signal() + 1, 1, "sync")
|
||||
|
||||
def test_wrong_clocks_neg(self):
|
||||
with self.assertRaises(ValueError,
|
||||
"Cannot sample a value 1 cycles in the future"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Cannot sample a value 1 cycles in the future$"):
|
||||
Sample(Signal(), -1, "sync")
|
||||
|
||||
def test_wrong_domain(self):
|
||||
with self.assertRaises(TypeError,
|
||||
"Domain name must be a string or None, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Domain name must be a string or None, not 0$"):
|
||||
Sample(Signal(), 1, 0)
|
||||
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ class ClockDomainTestCase(FHDLTestCase):
|
|||
self.assertEqual(pix.name, "pix")
|
||||
dom = [ClockDomain("foo")][0]
|
||||
self.assertEqual(dom.name, "foo")
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Clock domain name must be specified explicitly"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Clock domain name must be specified explicitly$"):
|
||||
ClockDomain()
|
||||
cd_reset = ClockDomain(local=True)
|
||||
self.assertEqual(cd_reset.local, True)
|
||||
|
@ -32,8 +32,8 @@ class ClockDomainTestCase(FHDLTestCase):
|
|||
self.assertEqual(sync.clk_edge, "neg")
|
||||
|
||||
def test_edge_wrong(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain clock edge must be one of 'pos' or 'neg', not 'xxx'"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain clock edge must be one of 'pos' or 'neg', not 'xxx'$"):
|
||||
ClockDomain("sync", clk_edge="xxx")
|
||||
|
||||
def test_with_reset(self):
|
||||
|
@ -73,6 +73,6 @@ class ClockDomainTestCase(FHDLTestCase):
|
|||
self.assertEqual(sync.clk.name, "pix_clk")
|
||||
|
||||
def test_wrong_name_comb(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'comb' may not be clocked"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'comb' may not be clocked$"):
|
||||
comb = ClockDomain()
|
||||
|
|
|
@ -20,9 +20,9 @@ class DSLTestCase(FHDLTestCase):
|
|||
self.w1 = Signal(4)
|
||||
|
||||
def test_cant_inherit(self):
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Instead of inheriting from `Module`, inherit from `Elaboratable` and "
|
||||
"return a `Module` from the `elaborate(self, platform)` method"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
(r"^Instead of inheriting from `Module`, inherit from `Elaboratable` and "
|
||||
r"return a `Module` from the `elaborate\(self, platform\)` method$")):
|
||||
class ORGate(Module):
|
||||
pass
|
||||
|
||||
|
@ -69,47 +69,47 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_d_conflict(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Driver-driver conflict: trying to drive (sig c1) from d.sync, but it "
|
||||
"is already driven from d.comb"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
(r"^Driver-driver conflict: trying to drive \(sig c1\) from d\.sync, but it "
|
||||
r"is already driven from d\.comb$")):
|
||||
m.d.comb += self.c1.eq(1)
|
||||
m.d.sync += self.c1.eq(1)
|
||||
|
||||
def test_d_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Cannot assign 'd.pix' attribute; did you mean 'd.pix +='?"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Cannot assign 'd\.pix' attribute; did you mean 'd.pix \+='\?$"):
|
||||
m.d.pix = None
|
||||
|
||||
def test_d_asgn_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Only assignments and property checks may be appended to d.sync"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Only assignments and property checks may be appended to d\.sync$"):
|
||||
m.d.sync += Switch(self.s1, {})
|
||||
|
||||
def test_comb_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="'Module' object has no attribute 'comb'; did you mean 'd.comb'?"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^'Module' object has no attribute 'comb'; did you mean 'd\.comb'\?$"):
|
||||
m.comb += self.c1.eq(1)
|
||||
|
||||
def test_sync_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="'Module' object has no attribute 'sync'; did you mean 'd.sync'?"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^'Module' object has no attribute 'sync'; did you mean 'd\.sync'\?$"):
|
||||
m.sync += self.c1.eq(1)
|
||||
|
||||
def test_attr_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="'Module' object has no attribute 'nonexistentattr'"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^'Module' object has no attribute 'nonexistentattr'$"):
|
||||
m.nonexistentattr
|
||||
|
||||
def test_d_suspicious(self):
|
||||
m = Module()
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Using '<module>.d.submodules' would add statements to clock domain "
|
||||
"'submodules'; did you mean <module>.submodules instead?"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
(r"^Using '<module>\.d\.submodules' would add statements to clock domain "
|
||||
r"'submodules'; did you mean <module>\.submodules instead\?$")):
|
||||
m.d.submodules += []
|
||||
|
||||
def test_clock_signal(self):
|
||||
|
@ -260,15 +260,15 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_Elif_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Elif without preceding If"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Elif without preceding If$"):
|
||||
with m.Elif(self.s2):
|
||||
pass
|
||||
|
||||
def test_Else_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Else without preceding If/Elif"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Else without preceding If\/Elif$"):
|
||||
with m.Else():
|
||||
pass
|
||||
|
||||
|
@ -287,11 +287,11 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_If_signed_suspicious(self):
|
||||
m = Module()
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Signed values in If/Elif conditions usually result from inverting Python "
|
||||
"booleans with ~, which leads to unexpected results. Replace `~flag` with "
|
||||
"`not flag`. (If this is a false positive, silence this warning with "
|
||||
"`m.If(x)` → `m.If(x.bool())`.)"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
(r"^Signed values in If\/Elif conditions usually result from inverting Python "
|
||||
r"booleans with ~, which leads to unexpected results\. Replace `~flag` with "
|
||||
r"`not flag`\. \(If this is a false positive, silence this warning with "
|
||||
r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$")):
|
||||
with m.If(~True):
|
||||
pass
|
||||
|
||||
|
@ -299,28 +299,28 @@ class DSLTestCase(FHDLTestCase):
|
|||
m = Module()
|
||||
with m.If(0):
|
||||
pass
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Signed values in If/Elif conditions usually result from inverting Python "
|
||||
"booleans with ~, which leads to unexpected results. Replace `~flag` with "
|
||||
"`not flag`. (If this is a false positive, silence this warning with "
|
||||
"`m.If(x)` → `m.If(x.bool())`.)"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
(r"^Signed values in If\/Elif conditions usually result from inverting Python "
|
||||
r"booleans with ~, which leads to unexpected results\. Replace `~flag` with "
|
||||
r"`not flag`\. \(If this is a false positive, silence this warning with "
|
||||
r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$")):
|
||||
with m.Elif(~True):
|
||||
pass
|
||||
|
||||
def test_if_If_Elif_Else(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="`if m.If(...):` does not work; use `with m.If(...)`"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^`if m\.If\(\.\.\.\):` does not work; use `with m\.If\(\.\.\.\)`$"):
|
||||
if m.If(0):
|
||||
pass
|
||||
with m.If(0):
|
||||
pass
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="`if m.Elif(...):` does not work; use `with m.Elif(...)`"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^`if m\.Elif\(\.\.\.\):` does not work; use `with m\.Elif\(\.\.\.\)`$"):
|
||||
if m.Elif(0):
|
||||
pass
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="`if m.Else(...):` does not work; use `with m.Else(...)`"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^`if m\.Else\(\.\.\.\):` does not work; use `with m\.Else\(\.\.\.\)`$"):
|
||||
if m.Else():
|
||||
pass
|
||||
|
||||
|
@ -414,18 +414,18 @@ class DSLTestCase(FHDLTestCase):
|
|||
RED = 0b10101010
|
||||
m = Module()
|
||||
with m.Switch(self.w1):
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Case pattern '--' must have the same width as switch value (which is 4)"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Case pattern '--' must have the same width as switch value \(which is 4\)$"):
|
||||
with m.Case("--"):
|
||||
pass
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Case pattern '10110' is wider than switch value (which has width 4); "
|
||||
"comparison will never be true"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
(r"^Case pattern '10110' is wider than switch value \(which has width 4\); "
|
||||
r"comparison will never be true$")):
|
||||
with m.Case(0b10110):
|
||||
pass
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Case pattern '10101010' (Color.RED) is wider than switch value "
|
||||
"(which has width 4); comparison will never be true"):
|
||||
with self.assertWarnsRegex(SyntaxWarning,
|
||||
(r"^Case pattern '10101010' \(Color\.RED\) is wider than switch value "
|
||||
r"\(which has width 4\); comparison will never be true$")):
|
||||
with m.Case(Color.RED):
|
||||
pass
|
||||
self.assertRepr(m._statements, """
|
||||
|
@ -437,33 +437,33 @@ class DSLTestCase(FHDLTestCase):
|
|||
def test_Case_bits_wrong(self):
|
||||
m = Module()
|
||||
with m.Switch(self.w1):
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Case pattern 'abc' must consist of 0, 1, and - (don't care) bits, "
|
||||
"and may include whitespace"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
(r"^Case pattern 'abc' must consist of 0, 1, and - \(don't care\) bits, "
|
||||
r"and may include whitespace$")):
|
||||
with m.Case("abc"):
|
||||
pass
|
||||
|
||||
def test_Case_pattern_wrong(self):
|
||||
m = Module()
|
||||
with m.Switch(self.w1):
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Case pattern must be an integer, a string, or an enumeration, not 1.0"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Case pattern must be an integer, a string, or an enumeration, not 1\.0$"):
|
||||
with m.Case(1.0):
|
||||
pass
|
||||
|
||||
def test_Case_outside_Switch_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Case is not permitted outside of Switch"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Case is not permitted outside of Switch$"):
|
||||
with m.Case():
|
||||
pass
|
||||
|
||||
def test_If_inside_Switch_wrong(self):
|
||||
m = Module()
|
||||
with m.Switch(self.s1):
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="If is not permitted directly inside of Switch; "
|
||||
"it is permitted inside of Switch Case"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
(r"^If is not permitted directly inside of Switch; "
|
||||
r"it is permitted inside of Switch Case$")):
|
||||
with m.If(self.s2):
|
||||
pass
|
||||
|
||||
|
@ -577,15 +577,15 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_FSM_wrong_domain(self):
|
||||
m = Module()
|
||||
with self.assertRaises(ValueError,
|
||||
msg="FSM may not be driven by the 'comb' domain"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^FSM may not be driven by the 'comb' domain$"):
|
||||
with m.FSM(domain="comb"):
|
||||
pass
|
||||
|
||||
def test_FSM_wrong_undefined(self):
|
||||
m = Module()
|
||||
with self.assertRaises(NameError,
|
||||
msg="FSM state 'FOO' is referenced but not defined"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^FSM state 'FOO' is referenced but not defined$"):
|
||||
with m.FSM() as fsm:
|
||||
fsm.ongoing("FOO")
|
||||
|
||||
|
@ -594,21 +594,21 @@ class DSLTestCase(FHDLTestCase):
|
|||
with m.FSM():
|
||||
with m.State("FOO"):
|
||||
pass
|
||||
with self.assertRaises(NameError,
|
||||
msg="FSM state 'FOO' is already defined"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^FSM state 'FOO' is already defined$"):
|
||||
with m.State("FOO"):
|
||||
pass
|
||||
|
||||
def test_FSM_wrong_next(self):
|
||||
m = Module()
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="Only assignment to `m.next` is permitted"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^Only assignment to `m\.next` is permitted$"):
|
||||
m.next
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="`m.next = <...>` is only permitted inside an FSM state"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^`m\.next = <\.\.\.>` is only permitted inside an FSM state$"):
|
||||
m.next = "FOO"
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="`m.next = <...>` is only permitted inside an FSM state"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r"^`m\.next = <\.\.\.>` is only permitted inside an FSM state$"):
|
||||
with m.FSM():
|
||||
m.next = "FOO"
|
||||
|
||||
|
@ -617,9 +617,9 @@ class DSLTestCase(FHDLTestCase):
|
|||
with m.FSM():
|
||||
with m.State("FOO"):
|
||||
pass
|
||||
with self.assertRaises(SyntaxError,
|
||||
msg="If is not permitted directly inside of FSM; "
|
||||
"it is permitted inside of FSM State"):
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
(r"^If is not permitted directly inside of FSM; "
|
||||
r"it is permitted inside of FSM State$")):
|
||||
with m.If(self.s2):
|
||||
pass
|
||||
|
||||
|
@ -668,18 +668,18 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_submodule_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Trying to add 1, which does not implement .elaborate(), as a submodule"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Trying to add 1, which does not implement \.elaborate\(\), as a submodule$"):
|
||||
m.submodules.foo = 1
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Trying to add 1, which does not implement .elaborate(), as a submodule"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Trying to add 1, which does not implement \.elaborate\(\), as a submodule$"):
|
||||
m.submodules += 1
|
||||
|
||||
def test_submodule_named_conflict(self):
|
||||
m1 = Module()
|
||||
m2 = Module()
|
||||
m1.submodules.foo = m2
|
||||
with self.assertRaises(NameError, msg="Submodule named 'foo' already exists"):
|
||||
with self.assertRaisesRegex(NameError, r"^Submodule named 'foo' already exists$"):
|
||||
m1.submodules.foo = m2
|
||||
|
||||
def test_submodule_get(self):
|
||||
|
@ -698,9 +698,9 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_submodule_get_unset(self):
|
||||
m1 = Module()
|
||||
with self.assertRaises(AttributeError, msg="No submodule named 'foo' exists"):
|
||||
with self.assertRaisesRegex(AttributeError, r"^No submodule named 'foo' exists$"):
|
||||
m2 = m1.submodules.foo
|
||||
with self.assertRaises(AttributeError, msg="No submodule named 'foo' exists"):
|
||||
with self.assertRaisesRegex(AttributeError, r"^No submodule named 'foo' exists$"):
|
||||
m2 = m1.submodules["foo"]
|
||||
|
||||
def test_domain_named_implicit(self):
|
||||
|
@ -716,24 +716,24 @@ class DSLTestCase(FHDLTestCase):
|
|||
|
||||
def test_domain_add_wrong(self):
|
||||
m = Module()
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Only clock domains may be added to `m.domains`, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Only clock domains may be added to `m\.domains`, not 1$"):
|
||||
m.domains.foo = 1
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Only clock domains may be added to `m.domains`, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Only clock domains may be added to `m\.domains`, not 1$"):
|
||||
m.domains += 1
|
||||
|
||||
def test_domain_add_wrong_name(self):
|
||||
m = Module()
|
||||
with self.assertRaises(NameError,
|
||||
msg="Clock domain name 'bar' must match name in `m.domains.foo += ...` syntax"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^Clock domain name 'bar' must match name in `m\.domains\.foo \+= \.\.\.` syntax$"):
|
||||
m.domains.foo = ClockDomain("bar")
|
||||
|
||||
def test_domain_add_wrong_duplicate(self):
|
||||
m = Module()
|
||||
m.domains += ClockDomain("foo")
|
||||
with self.assertRaises(NameError,
|
||||
msg="Clock domain named 'foo' already exists"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^Clock domain named 'foo' already exists$"):
|
||||
m.domains += ClockDomain("foo")
|
||||
|
||||
def test_lower(self):
|
||||
|
|
|
@ -16,14 +16,14 @@ class BadElaboratable(Elaboratable):
|
|||
|
||||
class FragmentGetTestCase(FHDLTestCase):
|
||||
def test_get_wrong(self):
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Object None cannot be elaborated"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Object None cannot be elaborated$"):
|
||||
Fragment.get(None, platform=None)
|
||||
|
||||
with self.assertWarns(UserWarning,
|
||||
msg=".elaborate() returned None; missing return statement?"):
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Object None cannot be elaborated"):
|
||||
with self.assertWarnsRegex(UserWarning,
|
||||
r"^\.elaborate\(\) returned None; missing return statement\?$"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Object None cannot be elaborated$"):
|
||||
Fragment.get(BadElaboratable(), platform=None)
|
||||
|
||||
|
||||
|
@ -41,11 +41,11 @@ class FragmentGeneratedTestCase(FHDLTestCase):
|
|||
f2 = Fragment()
|
||||
f1.add_subfragment(f2, "f2")
|
||||
|
||||
with self.assertRaises(NameError,
|
||||
msg="No subfragment at index #1"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^No subfragment at index #1$"):
|
||||
f1.find_subfragment(1)
|
||||
with self.assertRaises(NameError,
|
||||
msg="No subfragment with name 'fx'"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^No subfragment with name 'fx'$"):
|
||||
f1.find_subfragment("fx")
|
||||
|
||||
def test_find_generated(self):
|
||||
|
@ -300,18 +300,18 @@ class FragmentPortsTestCase(FHDLTestCase):
|
|||
|
||||
def test_port_wrong(self):
|
||||
f = Fragment()
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Only signals may be added as ports, not (const 1'd1)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Only signals may be added as ports, not \(const 1'd1\)$"):
|
||||
f.prepare(ports=(Const(1),))
|
||||
|
||||
def test_port_not_iterable(self):
|
||||
f = Fragment()
|
||||
with self.assertRaises(TypeError,
|
||||
msg="`ports` must be either a list or a tuple, not 1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^`ports` must be either a list or a tuple, not 1$"):
|
||||
f.prepare(ports=1)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="`ports` must be either a list or a tuple, not (const 1'd1)" +
|
||||
" (did you mean `ports=(<signal>,)`, rather than `ports=<signal>`?)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^`ports` must be either a list or a tuple, not \(const 1'd1\)"
|
||||
r" \(did you mean `ports=\(<signal>,\)`, rather than `ports=<signal>`\?\)$")):
|
||||
f.prepare(ports=Const(1))
|
||||
|
||||
class FragmentDomainsTestCase(FHDLTestCase):
|
||||
|
@ -380,10 +380,10 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
|||
f.add_subfragment(fa, "a")
|
||||
f.add_subfragment(fb)
|
||||
|
||||
with self.assertRaises(DomainError,
|
||||
msg="Domain 'sync' is defined by subfragments 'a', <unnamed #1> of fragment "
|
||||
"'top'; it is necessary to either rename subfragment domains explicitly, "
|
||||
"or give names to subfragments"):
|
||||
with self.assertRaisesRegex(DomainError,
|
||||
(r"^Domain 'sync' is defined by subfragments 'a', <unnamed #1> of fragment "
|
||||
r"'top'; it is necessary to either rename subfragment domains explicitly, "
|
||||
r"or give names to subfragments$")):
|
||||
f._propagate_domains_up()
|
||||
|
||||
def test_domain_conflict_name(self):
|
||||
|
@ -398,10 +398,10 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
|||
f.add_subfragment(fa, "x")
|
||||
f.add_subfragment(fb, "x")
|
||||
|
||||
with self.assertRaises(DomainError,
|
||||
msg="Domain 'sync' is defined by subfragments #0, #1 of fragment 'top', some "
|
||||
"of which have identical names; it is necessary to either rename subfragment "
|
||||
"domains explicitly, or give distinct names to subfragments"):
|
||||
with self.assertRaisesRegex(DomainError,
|
||||
(r"^Domain 'sync' is defined by subfragments #0, #1 of fragment 'top', some "
|
||||
r"of which have identical names; it is necessary to either rename subfragment "
|
||||
r"domains explicitly, or give distinct names to subfragments$")):
|
||||
f._propagate_domains_up()
|
||||
|
||||
def test_domain_conflict_rename_drivers(self):
|
||||
|
@ -481,8 +481,8 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
|||
f1 = Fragment()
|
||||
f1.add_driver(s1, "sync")
|
||||
|
||||
with self.assertRaises(DomainError,
|
||||
msg="Domain 'sync' is used but not defined"):
|
||||
with self.assertRaisesRegex(DomainError,
|
||||
r"^Domain 'sync' is used but not defined$"):
|
||||
f1._propagate_domains(missing_domain=lambda name: None)
|
||||
|
||||
def test_propagate_create_missing(self):
|
||||
|
@ -542,9 +542,9 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
|||
f2 = Fragment()
|
||||
f2.add_domains(ClockDomain("foo"))
|
||||
|
||||
with self.assertRaises(DomainError,
|
||||
msg="Fragment returned by missing domain callback does not define requested "
|
||||
"domain 'sync' (defines 'foo')."):
|
||||
with self.assertRaisesRegex(DomainError,
|
||||
(r"^Fragment returned by missing domain callback does not define requested "
|
||||
r"domain 'sync' \(defines 'foo'\)\.$")):
|
||||
f1._propagate_domains(missing_domain=lambda name: f2)
|
||||
|
||||
|
||||
|
@ -597,16 +597,16 @@ class FragmentHierarchyConflictTestCase(FHDLTestCase):
|
|||
def test_conflict_self_sub_error(self):
|
||||
self.setUp_self_sub()
|
||||
|
||||
with self.assertRaises(DriverConflict,
|
||||
msg="Signal '(sig s1)' is driven from multiple fragments: top, top.<unnamed #1>"):
|
||||
with self.assertRaisesRegex(DriverConflict,
|
||||
r"^Signal '\(sig s1\)' is driven from multiple fragments: top, top.<unnamed #1>$"):
|
||||
self.f1._resolve_hierarchy_conflicts(mode="error")
|
||||
|
||||
def test_conflict_self_sub_warning(self):
|
||||
self.setUp_self_sub()
|
||||
|
||||
with self.assertWarns(DriverConflict,
|
||||
msg="Signal '(sig s1)' is driven from multiple fragments: top, top.<unnamed #1>; "
|
||||
"hierarchy will be flattened"):
|
||||
with self.assertWarnsRegex(DriverConflict,
|
||||
(r"^Signal '\(sig s1\)' is driven from multiple fragments: top, top.<unnamed #1>; "
|
||||
r"hierarchy will be flattened$")):
|
||||
self.f1._resolve_hierarchy_conflicts(mode="warn")
|
||||
|
||||
def setUp_sub_sub(self):
|
||||
|
@ -691,17 +691,17 @@ class FragmentHierarchyConflictTestCase(FHDLTestCase):
|
|||
def test_conflict_memory_error(self):
|
||||
self.setUp_memory()
|
||||
|
||||
with self.assertRaises(DriverConflict,
|
||||
msg="Memory 'm' is accessed from multiple fragments: top.<unnamed #0>, "
|
||||
"top.<unnamed #1>"):
|
||||
with self.assertRaisesRegex(DriverConflict,
|
||||
r"^Memory 'm' is accessed from multiple fragments: top\.<unnamed #0>, "
|
||||
r"top\.<unnamed #1>$"):
|
||||
self.f1._resolve_hierarchy_conflicts(mode="error")
|
||||
|
||||
def test_conflict_memory_warning(self):
|
||||
self.setUp_memory()
|
||||
|
||||
with self.assertWarns(DriverConflict,
|
||||
msg="Memory 'm' is accessed from multiple fragments: top.<unnamed #0>, "
|
||||
"top.<unnamed #1>; hierarchy will be flattened"):
|
||||
with self.assertWarnsRegex(DriverConflict,
|
||||
(r"^Memory 'm' is accessed from multiple fragments: top.<unnamed #0>, "
|
||||
r"top.<unnamed #1>; hierarchy will be flattened$")):
|
||||
self.f1._resolve_hierarchy_conflicts(mode="warn")
|
||||
|
||||
def test_explicit_flatten(self):
|
||||
|
@ -783,16 +783,16 @@ class InstanceTestCase(FHDLTestCase):
|
|||
|
||||
def test_wrong_construct_arg(self):
|
||||
s = Signal()
|
||||
with self.assertRaises(NameError,
|
||||
msg="Instance argument ('', 's1', (sig s)) should be a tuple "
|
||||
"(kind, name, value) where kind is one of \"p\", \"i\", \"o\", or \"io\""):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
(r"^Instance argument \('', 's1', \(sig s\)\) should be a tuple "
|
||||
r"\(kind, name, value\) where kind is one of \"p\", \"i\", \"o\", or \"io\"$")):
|
||||
Instance("foo", ("", "s1", s))
|
||||
|
||||
def test_wrong_construct_kwarg(self):
|
||||
s = Signal()
|
||||
with self.assertRaises(NameError,
|
||||
msg="Instance keyword argument x_s1=(sig s) does not start with one of "
|
||||
"\"p_\", \"i_\", \"o_\", or \"io_\""):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
(r"^Instance keyword argument x_s1=\(sig s\) does not start with one of "
|
||||
r"\"p_\", \"i_\", \"o_\", or \"io_\"$")):
|
||||
Instance("foo", x_s1=s)
|
||||
|
||||
def setUp_cpu(self):
|
||||
|
|
|
@ -20,11 +20,11 @@ class MemoryTestCase(FHDLTestCase):
|
|||
self.assertEqual(m.depth, 4)
|
||||
|
||||
def test_geometry_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Memory width must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Memory width must be a non-negative integer, not -1$"):
|
||||
m = Memory(width=-1, depth=4)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Memory depth must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Memory depth must be a non-negative integer, not -1$"):
|
||||
m = Memory(width=8, depth=-1)
|
||||
|
||||
def test_init(self):
|
||||
|
@ -32,14 +32,14 @@ class MemoryTestCase(FHDLTestCase):
|
|||
self.assertEqual(m.init, [0, 1, 2, 3])
|
||||
|
||||
def test_init_wrong_count(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Memory initialization value count exceed memory depth (8 > 4)"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Memory initialization value count exceed memory depth \(8 > 4\)$"):
|
||||
m = Memory(width=8, depth=4, init=range(8))
|
||||
|
||||
def test_init_wrong_type(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Memory initialization value at address 1: "
|
||||
"'str' object cannot be interpreted as an integer"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Memory initialization value at address 1: "
|
||||
r"'str' object cannot be interpreted as an integer$")):
|
||||
m = Memory(width=8, depth=4, init=[1, "0"])
|
||||
|
||||
def test_attrs(self):
|
||||
|
@ -82,8 +82,8 @@ class MemoryTestCase(FHDLTestCase):
|
|||
|
||||
def test_read_port_wrong(self):
|
||||
mem = Memory(width=8, depth=4)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Read port cannot be simultaneously asynchronous and non-transparent"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Read port cannot be simultaneously asynchronous and non-transparent$"):
|
||||
mem.read_port(domain="comb", transparent=False)
|
||||
|
||||
def test_write_port(self):
|
||||
|
@ -108,14 +108,14 @@ class MemoryTestCase(FHDLTestCase):
|
|||
|
||||
def test_write_port_granularity_wrong(self):
|
||||
mem = Memory(width=8, depth=4)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Write port granularity must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Write port granularity must be a non-negative integer, not -1$"):
|
||||
mem.write_port(granularity=-1)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Write port granularity must not be greater than memory width (10 > 8)"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Write port granularity must not be greater than memory width \(10 > 8\)$"):
|
||||
mem.write_port(granularity=10)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Write port granularity must divide memory width evenly"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Write port granularity must divide memory width evenly$"):
|
||||
mem.write_port(granularity=3)
|
||||
|
||||
|
||||
|
|
|
@ -72,31 +72,31 @@ class LayoutTestCase(FHDLTestCase):
|
|||
"('b', Layout([('c', signed(3))]))])")
|
||||
|
||||
def test_wrong_field(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Field (1,) has invalid layout: should be either (name, shape) or "
|
||||
"(name, shape, direction)"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Field \(1,\) has invalid layout: should be either \(name, shape\) or "
|
||||
r"\(name, shape, direction\)$")):
|
||||
Layout.cast([(1,)])
|
||||
|
||||
def test_wrong_name(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Field (1, 1) has invalid name: should be a string"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Field \(1, 1\) has invalid name: should be a string$"):
|
||||
Layout.cast([(1, 1)])
|
||||
|
||||
def test_wrong_name_duplicate(self):
|
||||
with self.assertRaises(NameError,
|
||||
msg="Field ('a', 2) has a name that is already present in the layout"):
|
||||
with self.assertRaisesRegex(NameError,
|
||||
r"^Field \('a', 2\) has a name that is already present in the layout$"):
|
||||
Layout.cast([("a", 1), ("a", 2)])
|
||||
|
||||
def test_wrong_direction(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Field ('a', 1, 0) has invalid direction: should be a Direction "
|
||||
"instance like DIR_FANIN"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Field \('a', 1, 0\) has invalid direction: should be a Direction "
|
||||
r"instance like DIR_FANIN$")):
|
||||
Layout.cast([("a", 1, 0)])
|
||||
|
||||
def test_wrong_shape(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Field ('a', 'x') has invalid shape: should be castable to Shape or "
|
||||
"a list of fields of a nested record"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Field \('a', 'x'\) has invalid shape: should be castable to Shape or "
|
||||
r"a list of fields of a nested record$")):
|
||||
Layout.cast([("a", "x")])
|
||||
|
||||
|
||||
|
@ -142,11 +142,11 @@ class RecordTestCase(FHDLTestCase):
|
|||
("stb", 1),
|
||||
("ack", 1),
|
||||
])
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Record 'r' does not have a field 'en'. Did you mean one of: stb, ack?"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Record 'r' does not have a field 'en'\. Did you mean one of: stb, ack\?$"):
|
||||
r["en"]
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Record 'r' does not have a field 'en'. Did you mean one of: stb, ack?"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Record 'r' does not have a field 'en'\. Did you mean one of: stb, ack\?$"):
|
||||
r.en
|
||||
|
||||
def test_wrong_field_unnamed(self):
|
||||
|
@ -154,8 +154,8 @@ class RecordTestCase(FHDLTestCase):
|
|||
("stb", 1),
|
||||
("ack", 1),
|
||||
])][0]
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Unnamed record does not have a field 'en'. Did you mean one of: stb, ack?"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Unnamed record does not have a field 'en'\. Did you mean one of: stb, ack\?$"):
|
||||
r.en
|
||||
|
||||
def test_construct_with_fields(self):
|
||||
|
@ -303,27 +303,27 @@ class ConnectTestCase(FHDLTestCase):
|
|||
core = Record(self.core_layout)
|
||||
periph = Record(self.periph_layout)
|
||||
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Cannot include field 'foo' because it is not present in record 'core'"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Cannot include field 'foo' because it is not present in record 'core'$"):
|
||||
core.connect(periph, include={"foo": True})
|
||||
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Cannot exclude field 'foo' because it is not present in record 'core'"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
r"^Cannot exclude field 'foo' because it is not present in record 'core'$"):
|
||||
core.connect(periph, exclude={"foo": True})
|
||||
|
||||
def test_wrong_direction(self):
|
||||
recs = [Record([("x", 1)]) for _ in range(2)]
|
||||
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Cannot connect field 'x' of unnamed record because it does not have "
|
||||
"a direction"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
(r"^Cannot connect field 'x' of unnamed record because it does not have "
|
||||
r"a direction$")):
|
||||
recs[0].connect(recs[1])
|
||||
|
||||
def test_wrong_missing_field(self):
|
||||
core = Record([("addr", 32, DIR_FANOUT)])
|
||||
periph = Record([])
|
||||
|
||||
with self.assertRaises(AttributeError,
|
||||
msg="Cannot connect field 'addr' of record 'core' to subordinate record 'periph' "
|
||||
"because the subordinate record does not have this field"):
|
||||
with self.assertRaisesRegex(AttributeError,
|
||||
(r"^Cannot connect field 'addr' of record 'core' to subordinate record 'periph' "
|
||||
r"because the subordinate record does not have this field$")):
|
||||
core.connect(periph)
|
||||
|
|
|
@ -110,13 +110,13 @@ class DomainRenamerTestCase(FHDLTestCase):
|
|||
})
|
||||
|
||||
def test_rename_wrong_to_comb(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'sync' may not be renamed to 'comb'"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'sync' may not be renamed to 'comb'$"):
|
||||
DomainRenamer("comb")
|
||||
|
||||
def test_rename_wrong_from_comb(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'comb' may not be renamed"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'comb' may not be renamed$"):
|
||||
DomainRenamer({"comb": "sync"})
|
||||
|
||||
|
||||
|
@ -189,8 +189,8 @@ class DomainLowererTestCase(FHDLTestCase):
|
|||
self.s.eq(ClockSignal("xxx"))
|
||||
)
|
||||
|
||||
with self.assertRaises(DomainError,
|
||||
msg="Signal (clk xxx) refers to nonexistent domain 'xxx'"):
|
||||
with self.assertRaisesRegex(DomainError,
|
||||
r"^Signal \(clk xxx\) refers to nonexistent domain 'xxx'$"):
|
||||
DomainLowerer()(f)
|
||||
|
||||
def test_lower_wrong_reset_less_domain(self):
|
||||
|
@ -201,8 +201,8 @@ class DomainLowererTestCase(FHDLTestCase):
|
|||
self.s.eq(ResetSignal("sync"))
|
||||
)
|
||||
|
||||
with self.assertRaises(DomainError,
|
||||
msg="Signal (rst sync) refers to reset of reset-less domain 'sync'"):
|
||||
with self.assertRaisesRegex(DomainError,
|
||||
r"^Signal \(rst sync\) refers to reset of reset-less domain 'sync'$"):
|
||||
DomainLowerer()(f)
|
||||
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ from ..lib.cdc import *
|
|||
|
||||
class FFSynchronizerTestCase(FHDLTestCase):
|
||||
def test_stages_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||
FFSynchronizer(Signal(), Signal(), stages=0)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Synchronization stage count may not safely be less than 2"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Synchronization stage count may not safely be less than 2$"):
|
||||
FFSynchronizer(Signal(), Signal(), stages=1)
|
||||
|
||||
def test_basic(self):
|
||||
|
@ -56,16 +56,16 @@ class FFSynchronizerTestCase(FHDLTestCase):
|
|||
|
||||
class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
||||
def test_stages_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||
ResetSynchronizer(Signal(), stages=0)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Synchronization stage count may not safely be less than 2"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Synchronization stage count may not safely be less than 2$"):
|
||||
ResetSynchronizer(Signal(), stages=1)
|
||||
|
||||
def test_edge_wrong(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="AsyncFFSynchronizer async edge must be one of 'pos' or 'neg', not 'xxx'"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^AsyncFFSynchronizer async edge must be one of 'pos' or 'neg', not 'xxx'$"):
|
||||
AsyncFFSynchronizer(Signal(), Signal(), domain="sync", async_edge="xxx")
|
||||
|
||||
def test_pos_edge(self):
|
||||
|
@ -147,11 +147,11 @@ class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
|||
|
||||
class ResetSynchronizerTestCase(FHDLTestCase):
|
||||
def test_stages_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||
ResetSynchronizer(Signal(), stages=0)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Synchronization stage count may not safely be less than 2"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Synchronization stage count may not safely be less than 2$"):
|
||||
ResetSynchronizer(Signal(), stages=1)
|
||||
|
||||
def test_basic(self):
|
||||
|
@ -196,11 +196,11 @@ class ResetSynchronizerTestCase(FHDLTestCase):
|
|||
# TODO: test with distinct clocks
|
||||
class PulseSynchronizerTestCase(FHDLTestCase):
|
||||
def test_stages_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||
PulseSynchronizer("w", "r", stages=0)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Synchronization stage count may not safely be less than 2"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Synchronization stage count may not safely be less than 2$"):
|
||||
PulseSynchronizer("w", "r", stages=1)
|
||||
|
||||
def test_smoke(self):
|
||||
|
|
|
@ -9,11 +9,11 @@ from ..lib.fifo import *
|
|||
|
||||
class FIFOTestCase(FHDLTestCase):
|
||||
def test_depth_wrong(self):
|
||||
with self.assertRaises(TypeError,
|
||||
msg="FIFO width must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^FIFO width must be a non-negative integer, not -1$"):
|
||||
FIFOInterface(width=-1, depth=8, fwft=True)
|
||||
with self.assertRaises(TypeError,
|
||||
msg="FIFO depth must be a non-negative integer, not -1"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^FIFO depth must be a non-negative integer, not -1$"):
|
||||
FIFOInterface(width=8, depth=-1, fwft=True)
|
||||
|
||||
def test_sync_depth(self):
|
||||
|
@ -37,9 +37,9 @@ class FIFOTestCase(FHDLTestCase):
|
|||
self.assertEqual(AsyncFIFO(width=8, depth=17).depth, 32)
|
||||
|
||||
def test_async_depth_wrong(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="AsyncFIFO only supports depths that are powers of 2; "
|
||||
"requested exact depth 15 is not"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
(r"^AsyncFIFO only supports depths that are powers of 2; "
|
||||
r"requested exact depth 15 is not$")):
|
||||
AsyncFIFO(width=8, depth=15, exact_depth=True)
|
||||
|
||||
def test_async_buffered_depth(self):
|
||||
|
@ -54,9 +54,9 @@ class FIFOTestCase(FHDLTestCase):
|
|||
self.assertEqual(AsyncFIFOBuffered(width=8, depth=18).depth, 33)
|
||||
|
||||
def test_async_buffered_depth_wrong(self):
|
||||
with self.assertRaises(ValueError,
|
||||
msg="AsyncFIFOBuffered only supports depths that are one higher than powers of 2; "
|
||||
"requested exact depth 16 is not"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
(r"^AsyncFIFOBuffered only supports depths that are one higher than powers of 2; "
|
||||
r"requested exact depth 16 is not$")):
|
||||
AsyncFIFOBuffered(width=8, depth=16, exact_depth=True)
|
||||
|
||||
class FIFOModel(Elaboratable, FIFOInterface):
|
||||
|
|
|
@ -541,8 +541,8 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
|||
|
||||
def test_add_process_wrong(self):
|
||||
with self.assertSimulation(Module()) as sim:
|
||||
with self.assertRaises(TypeError,
|
||||
msg="Cannot add a process 1 because it is not a generator function"):
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
r"^Cannot add a process 1 because it is not a generator function$"):
|
||||
sim.add_process(1)
|
||||
|
||||
def test_add_process_wrong_generator(self):
|
||||
|
@ -559,15 +559,15 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
|||
m.d.sync += s.eq(0)
|
||||
with self.assertSimulation(m) as sim:
|
||||
sim.add_clock(1)
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'sync' already has a clock driving it"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'sync' already has a clock driving it$"):
|
||||
sim.add_clock(1)
|
||||
|
||||
def test_add_clock_wrong_missing(self):
|
||||
m = Module()
|
||||
with self.assertSimulation(m) as sim:
|
||||
with self.assertRaises(ValueError,
|
||||
msg="Domain 'sync' is not present in simulation"):
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
r"^Domain 'sync' is not present in simulation$"):
|
||||
sim.add_clock(1)
|
||||
|
||||
def test_add_clock_if_exists(self):
|
||||
|
|
|
@ -28,23 +28,6 @@ class FHDLTestCase(unittest.TestCase):
|
|||
return repr_str.strip()
|
||||
self.assertEqual(prepare_repr(repr(obj)), prepare_repr(repr_str))
|
||||
|
||||
@contextmanager
|
||||
def assertRaises(self, exception, msg=None):
|
||||
with super().assertRaises(exception) as cm:
|
||||
yield
|
||||
if msg is not None:
|
||||
# WTF? unittest.assertRaises is completely broken.
|
||||
self.assertEqual(str(cm.exception), msg)
|
||||
|
||||
@contextmanager
|
||||
def assertWarns(self, category, msg=None):
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
yield
|
||||
self.assertEqual(len(warns), 1)
|
||||
self.assertEqual(warns[0].category, category)
|
||||
if msg is not None:
|
||||
self.assertEqual(str(warns[0].message), msg)
|
||||
|
||||
def assertFormal(self, spec, mode="bmc", depth=1):
|
||||
caller, *_ = traceback.extract_stack(limit=2)
|
||||
spec_root, _ = os.path.splitext(caller.filename)
|
||||
|
|
Loading…
Reference in a new issue