def test_UInt_type(self): self.assertEqual(UInt(Size(8)).as_numpy_type(), np.uint8) self.assertEqual(UInt(Size(16)).as_numpy_type(), np.uint16) self.assertEqual(UInt(Size(32)).as_numpy_type(), np.uint32) self.assertEqual(UInt(Size(64)).as_numpy_type(), np.uint64) with self.assertRaises(NotImplementedError): UInt(Size(128)).as_numpy_type()
def test_Complex(self): """Only 64 and 128 bits are supported.""" for bits in (64, 128): for _ in range(1000): self.check_complex( random.uniform(-1, 1) + random.uniform(-1, 1) * 1j, Complex(Size(bits))) self.assertTrue(DeltaGraph.check_wire(Raw(complex), Raw(complex))) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Raw(Complex(Size(64))), Raw(Complex(Size(128))))
def test_Int(self): """Only 8, 16, 32 and 64 bits are supported.""" for bits in (8, 16, 32, 64): self.check(-2**(bits - 1), Int(Size(bits))) self.check(2**(bits - 1) - 1, Int(Size(bits))) for _ in range(1000): self.check(random.randint(-2**(bits - 1), 2**(bits - 1) - 1), Int(Size(bits))) self.assertTrue(DeltaGraph.check_wire(Raw(int), Raw(int))) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Raw(Int(Size(32))), Raw(Int(Size(64))))
def test_Float(self): """Only 32 and 64 bits are supported.""" precision_dict = {32: -23, 64: -52} for bits, precision in precision_dict.items(): for _ in range(1000): self.check_float(random.uniform(-1, 1), Float(Size(bits))) self.check(1 + 2**precision, Float(Size(bits))) self.assertTrue(DeltaGraph.check_wire(Raw(float), Raw(float))) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Raw(Float(Size(32))), Raw(Float(Size(64))))
def test_Str(self): self.check('hello world', Str()) self.check('A' * 1024, Str()) self.check('check digits 14213', Str()) self.check('check spaces in the end ', Str()) with self.assertRaises(DeltaTypeError): self.check('123456', Str(Size(4))) self.check((-5, 'text'), Tuple([int, Str()])) self.check(['hello', 'world!'], Array(Str(), Size(2))) self.check_numpy('hello world', Str())
def check_float(self, val, t: Float): """Test pack-unpack for floats.""" if not isinstance(t, Float): raise DeltaTypeError # TODO this check can be done on binary, then the number of places # will be more reasonably explained if t.size == Size(32): places = 6 elif t.size == Size(64): places = 15 else: raise NotImplementedError('Unsupported format') val_new = self.to_np_and_back(val, t) self.assertAlmostEqual(val, val_new, places=places)
def test_Union(self): # primitive self.check(5, Union([int, bool])) self.check(True, Union([int, bool])) # compound self.check(5, Union([int, Tuple([int, float])])) self.check((4, 5), Union([int, Tuple([int, int])])) self.check((4, 5), Union([Array(int, Size(2)), Tuple([int, int])])) self.check([4, 5], Union([Array(int, Size(2)), Tuple([int, int])])) self.assertTrue( DeltaGraph.check_wire(Raw(Union([Str(), int])), Raw(Union([Str(), int])))) with self.assertRaises(DeltaTypeError): self.check("Can't pack me", Union([int, float]))
def check_complex(self, val, t: Complex): """Test pack-unpack for complex numbers.""" if not isinstance(t, Complex): raise DeltaTypeError # Using the same idea as check_float, but for real and imaginary parts if t.size == Size(64): places = 6 elif t.size == Size(128): places = 15 else: raise NotImplementedError('Unsupported format') val_new = self.to_np_and_back(val, t) self.assertAlmostEqual(val.real, val_new.real, places=places) self.assertAlmostEqual(val.imag, val_new.imag, places=places)
def test_Tuple(self): # primitive elements are poperly handled self.check((-5, True, 3.25), Tuple([int, bool, float])) # incapsulation self.check((-5, (1, 2)), Tuple([int, Tuple([int, int])])) # mixed types self.check(([1, 2, 3], [4.0, 5.0]), Tuple([Array(int, Size(3)), Array(float, Size(2))])) self.check(("hello", "world"), Tuple([Str(), Str(Size(6))])) self.assertTrue( DeltaGraph.check_wire(Raw(Tuple([Str(), int])), Raw(Tuple([Str(), int]))))
def test_Str(self): self.check('hello world', Str()) self.check('A' * 1024, Str()) self.check('check digits 14213', Str()) self.check('check spaces in the end ', Str()) self.check((-5, 'text'), Tuple([int, Str()])) self.check(['hello', 'world!'], Array(Str(), Size(2))) self.assertTrue(DeltaGraph.check_wire(Raw(Str()), Raw(Str())))
def test_UInt(self): """Only 8, 16, 32, and 64 bits are supported.""" for bits in (8, 16, 32, 64): self.check(0, UInt(Size(bits))) self.check(2**bits - 1, UInt(Size(bits))) for _ in range(1000): self.check(random.randint(0, 2**bits - 1), UInt(Size(bits))) # Booleans can be packed self.check(True, UInt(Size(bits))) self.check(False, UInt(Size(bits))) # Floats, strings and negative or complex numbers are not packable self.assertFalse(UInt(Size(bits)).is_packable(3.5)) self.assertFalse(UInt(Size(bits)).is_packable(3.0)) self.assertFalse(UInt(Size(bits)).is_packable("abc")) self.assertFalse(UInt(Size(bits)).is_packable(-2)) self.assertFalse(UInt(Size(bits)).is_packable(3 + 5j))
def test_compound_objects(self): t = Array(Tuple([bool, int]), Size(3)) val = [(True, 1), (False, 2), (True, 3), (False, 4), (True, 5)] self.check(val, t) t = Tuple([int, Tuple([bool, int])]) val = (12, (True, 8)) self.check(val, t) t = Tuple([int, Array(int, Size(2))]) val = (12, [14, 18]) self.check(val, t) t = Tuple([int, Str()]) val = (12, "hello") self.check(val, t) t = Tuple([int, Record(RecBI)]) val = (12, RecBI(True, 8)) self.check(val, t) t = Tuple([int, Union([bool, int])]) val = (12, True) np_val = t.as_numpy_object(val) self.assertEqual(Int().from_numpy_object(np_val[0][0]), 12) self.assertEqual(Bool().from_numpy_object(np_val[0][1][1]), True) t = Record(RecATI) val = RecATI([1, 2], (3.0, 4), 5) self.check(val, t) t = Union([Array(int, Size(2)), int]) val = [1, 2] np_val = t.as_numpy_object(val) new_val = Array(int, Size(2)).from_numpy_object(np_val[0][1]) self.assertEqual(val, new_val) t = Union([str, int]) val = "abcde" np_val = t.as_numpy_object(val) new_val = Str().from_numpy_object(np_val[0][1]) self.assertEqual(val, new_val)
def test_Int(self): """Only 8, 16, 32, and 64 bits are supported.""" for bits in (8, 16, 32, 64): self.check(-2**(bits - 1), Int(Size(bits))) self.check(2**(bits - 1) - 1, Int(Size(bits))) for _ in range(1000): self.check(random.randint(-2**(bits - 1), 2**(bits - 1) - 1), Int(Size(bits))) # Booleans can be packed self.check(True, Int(Size(bits))) self.check(False, Int(Size(bits))) # Floats, strings and overflowing or # complex numbers are not packable self.assertFalse(Int(Size(bits)).is_packable(3.5)) self.assertFalse(Int(Size(bits)).is_packable(3.0)) self.assertFalse(Int(Size(bits)).is_packable("abc")) self.assertFalse(Int(Size(bits)).is_packable(2**bits - 1)) self.assertFalse(Int(Size(bits)).is_packable(3 + 5j))
def test_as_python_type(self): """Test conversion of Deltaflow data types to python.""" # special self.assertEqual(Top().as_python_type(), typing.Any) # primitive self.assertEqual(Int(Size(32)).as_python_type(), int) self.assertEqual(Int(Size(64)).as_python_type(), int) self.assertEqual(UInt(Size(32)).as_python_type(), int) self.assertEqual(UInt(Size(64)).as_python_type(), int) self.assertEqual(Bool().as_python_type(), bool) with self.assertRaises(NotImplementedError): Char().as_python_type() self.assertEqual(Float(Size(32)).as_python_type(), float) self.assertEqual(Float(Size(64)).as_python_type(), float) self.assertEqual(Complex(Size(64)).as_python_type(), complex) self.assertEqual(Complex(Size(128)).as_python_type(), complex) # compound self.assertEqual( Tuple([int, bool]).as_python_type(), typing.Tuple[int, bool]) self.assertEqual( Tuple([int, Tuple([int, bool])]).as_python_type(), typing.Tuple[int, typing.Tuple[int, bool]]) self.assertEqual( Array(int, Size(3)).as_python_type(), typing.List[int]) self.assertEqual(Str().as_python_type(), str) self.assertEqual(Str(Size(10)).as_python_type(), str) self.assertEqual(Record(RecBI).as_python_type(), RecBI) self.assertEqual(Record(RecBDi).as_python_type(), RecBDi) self.assertNotEqual(Record(RecBI).as_python_type(), RecBI_copy) # compound: Union self.assertEqual( Union([bool, int]).as_python_type(), typing.Union[bool, int]) self.assertEqual( Union([bool, Tuple([int, bool])]).as_python_type(), typing.Union[bool, typing.Tuple[int, bool]])
def test_Union(self): # primitive self.check(5, Union([int, bool]), Union([int, bool])) self.check(True, Union([int, bool]), Union([bool, int])) # compound self.check(5, Union([int, Tuple([int, float])])) self.check((4, 5), Union([int, Tuple([int, int])])) self.check((4, 5), Union([Array(int, Size(2)), Tuple([int, int])])) self.check([4, 5], Union([Array(int, Size(2)), Tuple([int, int])])) # buffer's size is always the same self.assertEqual(len(Union([int, bool]).pack(5)), Union([int, bool]).size.val) self.assertEqual(len(Union([int, bool]).pack(True)), Union([int, bool]).size.val) # numpy (throws error) with self.assertRaises( DeltaTypeError, msg="NumPy unions cannot be converted to Python types."): self.check_numpy(5, Union([bool, float, int]))
def test_default_name_func_block(self): saver = StateSaver(int) with DeltaGraph() as graph: r = return_5_default_name().output s = saver.save_and_exit(r) self.assertTrue(graph.check()) self.assertEqual(len(r.out_ports), 1) port_under_test = r.out_ports[0] self.assertEqual(port_under_test.destination.node, s) self.assertEqual(port_under_test.port_type, Int(Size(32))) self.assertEqual(port_under_test.index, 'output')
def test_Tuple(self): # primitive elements are properly handled self.check((-5, True, 3.25), Tuple([int, bool, float])) with self.assertRaises(DeltaTypeError): self.check((-5, True, 3.25), Tuple([int, bool, int])) # incapsulation self.check((-5, (1, 2)), Tuple([int, Tuple([int, int])])) with self.assertRaises(AssertionError): self.check((-5, (1, 2)), Tuple([int, Tuple([int, int])]), Tuple([int, int, int])) # mixed types self.check(([1, 2, 3], [4.0, 5.0]), Tuple([Array(int, Size(3)), Array(float, Size(2))])) self.check(("hello", "world"), Tuple([Str(), Str(Size(6))])) # numpy self.check_numpy((1, 2.0, True), Tuple([int, float, bool]))
def test_custom_name_interactive(self): saver = StateSaver(int) with DeltaGraph() as graph: r = send_5.call().out s = saver.save_and_exit(r) self.assertTrue(graph.check()) self.assertEqual(len(r.out_ports), 1) port_under_test = r.out_ports[0] self.assertEqual(port_under_test.destination.node, s) self.assertEqual(port_under_test.port_type, Int(Size(32))) self.assertEqual(port_under_test.index, 'out')
def test_Top(self): """Everything can be accepted as Top().""" self.assertTrue(DeltaGraph.check_wire(Int(), Top())) self.assertTrue(DeltaGraph.check_wire(UInt(), Top())) self.assertTrue(DeltaGraph.check_wire(Bool(), Top())) self.assertTrue(DeltaGraph.check_wire(Tuple([int, bool]), Top())) self.assertTrue(DeltaGraph.check_wire(Union([int, bool]), Top())) self.assertTrue(DeltaGraph.check_wire(Array(int, Size(8)), Top())) self.assertTrue(DeltaGraph.check_wire(Str(), Top())) self.assertTrue(DeltaGraph.check_wire(Record(RecBI), Top())) # however this isn't true if allow_top is set to False with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Int(), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(UInt(), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Bool(), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Tuple([int, bool]), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Union([int, bool]), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Array(int, Size(8)), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Str(), Top(), allow_top=False) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Record(RecBI), Top(), allow_top=False) # the sending port cannot have type Top() with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Top(), Top()) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Top(), Int()) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Union([Int(), Top()]), Int())
def test_custom_name_method_block(self): saver = StateSaver(int) m = MethodReturner() with DeltaGraph() as graph: r = m.return_5_m().out s = saver.save_and_exit(r) self.assertTrue(graph.check()) self.assertEqual(len(r.out_ports), 1) port_under_test = r.out_ports[0] self.assertEqual(port_under_test.destination.node, s) self.assertEqual(port_under_test.port_type, Int(Size(32))) self.assertEqual(port_under_test.index, 'out')
def test_Array(self): """Only strict typing.""" self.assertTrue( DeltaGraph.check_wire(Array(int, Size(8)), Array(int, Size(8)))) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Array(int, Size(10)), Array(int, Size(8))) with self.assertRaises(DeltaTypeError): DeltaGraph.check_wire(Array(int, Size(8)), Array(int, Size(10)))
def test_Record(self): # primitive self.check(RecBI(True, 5), Record(RecBI)) self.check(-4, Int()) self.check(RecBII(True, 5, -4), Record(RecBII)) # mixed self.check(RecIT(-4.0, (1, 2)), Record(RecIT)) self.check(RecATI([1, 2], (3.0, 4), 5), Record(RecATI)) self.check((RecIT(-4.0, (1, 2)), 1), Tuple([Record(RecIT), int])) self.check([RecIT(-4.0, (1, 2)), RecIT(5.0, (-3, -4))], Array(Record(RecIT), Size(2))) self.assertTrue( DeltaGraph.check_wire(Raw(Record(RecIT)), Raw(Record(RecIT))))
def test_top_not_allowed(self): """Compound types should not accept Top as a sub-type.""" with self.assertRaises(DeltaTypeError): Array(object, Size(5)) with self.assertRaises(DeltaTypeError): Tuple([object, int]) with self.assertRaises(DeltaTypeError): Record(RecBT) with self.assertRaises(DeltaTypeError): Raw(object) with self.assertRaises(DeltaTypeError): Union([int, bool, object])
def test_types_comparison(self): """Various tests of types comparison.""" # primitive self.assertEqual(Int(Size(32)), Int()) self.assertNotEqual(Int(), UInt()) self.assertNotEqual(Int(), Int(Size(64))) # compound self.assertEqual(Tuple([int, bool]), Tuple([int, bool])) self.assertNotEqual(Tuple([int, bool]), Tuple([bool, int])) self.assertEqual(Array(int, Size(4)), Array(int, Size(4))) self.assertEqual(Array(int, Size(4)), Array(Int(), Size(4))) self.assertNotEqual(Array(int, Size(4)), Array(int, Size(5))) self.assertNotEqual(Str(), Str(Size(100))) self.assertEqual(Record(RecBI), Record(RecBI)) # compound: Union self.assertEqual(Union([int, bool]), Union([bool, int])) self.assertEqual(Union([int, Union([int, bool])]), Union([int, bool])) self.assertEqual(Union([int, Union([int, Union([int, bool])])]), Union([int, bool])) self.assertEqual(Union([int, int]), Union([int])) self.assertNotEqual(Union([Int()]), Int())
def test_Float(self): """Only 32 and 64 bits are supported.""" precision_dict = {32: -23, 64: -52} for bits, precision in precision_dict.items(): for _ in range(1000): self.check_float(random.uniform(-1, 1), Float(Size(bits))) self.check(1 + 2**precision, Float(Size(bits))) # Booleans and ints can be packed self.check(True, Float(Size(bits))) self.check(False, Float(Size(bits))) self.check(3, Float(Size(bits))) # Strings and complex numbers are not packable self.assertFalse(Float(Size(bits)).is_packable("abc")) self.assertFalse(Float(Size(bits)).is_packable(3 + 5j))
def test_Record(self): # primitive self.check(RecBI(True, 5), Record(RecBI)) self.check(-4, Int()) self.check(RecBII(True, 5, -4), Record(RecBII)) with self.assertRaises(DeltaTypeError): self.check(RecBI(True, 5), Record(RecIB)) # mixed self.check(RecIT(-4.0, (1, 2)), Record(RecIT)) self.check(RecATI([1, 2], (3.0, 4), 5), Record(RecATI)) self.check((RecIT(-4.0, (1, 2)), 1), Tuple([Record(RecIT), int])) self.check([RecIT(-4.0, (1, 2)), RecIT(5.0, (-3, -4))], Array(Record(RecIT), Size(2))) # numpy self.check_numpy(RecBI(False, 2), Record(RecBI))
def test_str(self): """Test string representation of data types.""" # primitive self.assertEqual(str(Int()), "Int32") self.assertEqual(str(Int(Size(64))), "Int64") self.assertEqual(str(UInt()), "UInt32") self.assertEqual(str(UInt(Size(64))), "UInt64") self.assertEqual(str(Bool()), "Bool") self.assertEqual(str(Char()), "Char8") self.assertEqual(str(Float()), "Float32") self.assertEqual(str(Float(Size(64))), "Float64") # compound self.assertEqual(str(Array(int, Size(8))), "[Int32 x 8]") self.assertEqual(str(Str()), "Str8192") self.assertEqual(str(Str(Size(100))), "Str800") self.assertEqual(str(Tuple([int, bool])), "(Int32, Bool)") self.assertEqual(str(Record(RecBIS)), "{x: Bool, y: Int32, z: Str8192}") self.assertEqual(str(Union([int, bool])), "<Bool | Int32>") # compound: Union self.assertEqual(str(Union([int])), "<Int32>") self.assertEqual(str(Union([int, Union([int, bool])])), "<Bool | Int32>") self.assertEqual(str(Union([int, Union([int, Union([int, bool])])])), "<Bool | Int32>") # encapsulation of various types self.assertEqual(str(Union([int, Tuple([int, bool])])), "<(Int32, Bool) | Int32>") self.assertEqual(str(Array(Tuple([int, bool]), Size(8))), "[(Int32, Bool) x 8]") # special self.assertEqual(str(Top()), "T") self.assertEqual(str(Size(5)), "5") self.assertEqual(str(Size(NamespacedName("a", "b"))), "(a.b)")
def test_Complex(self): """Only 64 and 128 bits are supported.""" for bits in (64, 128): for _ in range(1000): self.check_complex( random.uniform(-1, 1) + random.uniform(-1, 1) * 1j, Complex(Size(bits))) # Booleans, ints and floats can be packed self.check(True, Complex(Size(bits))) self.check(False, Complex(Size(bits))) self.check(3, Complex(Size(bits))) self.check(3.5, Complex(Size(bits))) # Strings are not packable self.assertFalse(Complex(Size(bits)).is_packable("abc"))
def test_Str_object(self): self.check("abcde", Str(Size(32)))
def test_Str_type(self): str_type = Str(Size(32)).as_numpy_type() self.assertEqual(str_type, (np.string_, 32))