hdl.ast: implement ValueCastable.
[nmigen.git] / tests / test_hdl_ast.py
index e6dfc49e081f0cdf5d79fc932d1d6e3ff0174116..b0d40d5c6beee395256ce2459766f9fc9e0a2d50 100644 (file)
@@ -1025,6 +1025,52 @@ class UserValueTestCase(FHDLTestCase):
         self.assertEqual(uv.lower_count, 1)
 
 
+class MockValueCastableChanges(ValueCastable):
+    def __init__(self, width=0):
+        self.width = width
+
+    @ValueCastable.lowermethod
+    def as_value(self):
+        return Signal(self.width)
+
+
+class MockValueCastableNotDecorated(ValueCastable):
+    def __init__(self):
+        pass
+
+    def as_value(self):
+        return Signal()
+
+
+class MockValueCastableNoOverride(ValueCastable):
+    def __init__(self):
+        pass
+
+
+class ValueCastableTestCase(FHDLTestCase):
+    def test_not_decorated(self):
+        with self.assertRaisesRegex(TypeError,
+                r"^Class 'MockValueCastableNotDecorated' deriving from `ValueCastable` must decorate the `as_value` "
+                r"method with the `ValueCastable.lowermethod` decorator$"):
+            vc = MockValueCastableNotDecorated()
+
+    def test_no_override(self):
+        with self.assertRaisesRegex(TypeError,
+                r"^Class 'MockValueCastableNoOverride' deriving from `ValueCastable` must override the `as_value` "
+                r"method$"):
+            vc = MockValueCastableNoOverride()
+
+    def test_memoized(self):
+        vc = MockValueCastableChanges(1)
+        sig1 = vc.as_value()
+        vc.width = 2
+        sig2 = vc.as_value()
+        self.assertIs(sig1, sig2)
+        vc.width = 3
+        sig3 = Value.cast(vc)
+        self.assertIs(sig1, sig3)
+
+
 class SampleTestCase(FHDLTestCase):
     def test_const(self):
         s = Sample(1, 1, "sync")