tests: fix remove unnecessary workaround for some unittest assertions.
authorJacob Graves <jacob@greatscottgadgets.com>
Tue, 28 Jul 2020 19:35:25 +0000 (13:35 -0600)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 31 Dec 2021 14:54:53 +0000 (14:54 +0000)
14 files changed:
nmigen/test/test_build_dsl.py
nmigen/test/test_build_plat.py
nmigen/test/test_build_res.py
nmigen/test/test_hdl_ast.py
nmigen/test/test_hdl_cd.py
nmigen/test/test_hdl_dsl.py
nmigen/test/test_hdl_ir.py
nmigen/test/test_hdl_mem.py
nmigen/test/test_hdl_rec.py
nmigen/test/test_hdl_xfrm.py
nmigen/test/test_lib_cdc.py
nmigen/test/test_lib_fifo.py
nmigen/test/test_sim.py
nmigen/test/utils.py

index bf901bfc0d87844f38ad40f246b428defdc36079..87f082aa403815ae7cda8228038a55b3f05dde5a 100644 (file)
@@ -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})
index 2b2ec62ee72cbfba95332686eb39041e45ffa5c0..1342501d2f80669c281a1f7f991c809eff6437ea 100644 (file)
@@ -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")
index 3b3a9d5e9af3b88b7534a74d7a0b121ef8d305dd..db105a69196322d11e55d430e7ee83080fafa5b0 100644 (file)
@@ -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)
index 691408a0363e9a4d3bdea0f659b0888863420cec..af874156bfca27c3553251fe38f4abf56ec97ff5 100644 (file)
@@ -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)
 
 
index 85bcfc85f927a6a0077f252a38a4b1a69b395706..8927e08252db2c67d184486f5c3fd8b039e330bd 100644 (file)
@@ -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()
index c3a5b270537e0e0bada70190f91aad45beeeb37d..454415dadf28235a98ff74d87a2b306c9b7ff110 100644 (file)
@@ -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):
index b93537d9d2a73bc70d3e4ba8cd47101d03d93df4..ab8bdd846153a11efc59166227c0d61d8b0fb01d 100644 (file)
@@ -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):
index 131c6398d458d145bf34a7ba6573bf6445b47849..ed87aec62ab44fa03d06954503bbec7056f72e33 100644 (file)
@@ -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)
 
 
index 4f99800b9f2c455335e8628e017f61119fedc2a5..dfcadf787463913e71591cf62572bf972679969d 100644 (file)
@@ -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)
index 394d3497bb2d7f0b3345932063742541c6278a6c..9ec6e1b0f4a48c22c482718a69ed59d9b8d365c4 100644 (file)
@@ -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)
 
 
index 8b081220b66b9d9e4d3a86baa22372bb4294c5b0..5a169ac430db4c87362d251735cd8223f4b87b3e 100644 (file)
@@ -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):
index 29a28d8dcde8851e65bc9294658df5a0fe903a0e..36698dec7757003ef5aa69f5d97e037a265f3aa1 100644 (file)
@@ -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):
index bff305129e54e47daba83ee3a80c6d259ed47226..8626e71eab9832090d5081ff330707bc6ff92cf7 100644 (file)
@@ -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):
index d8a168cb2f5de2b45e203f170f39f06d7b2ffa9a..3c884032f262e0c281806c098f29b84530db4c92 100644 (file)
@@ -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)