def test_anonymous_struct_member(self): # Member with anonymous struct type. anonymous_struct = self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ) self.assertPrettyPrint( self.prog.struct_type( "line_segment", 16, ( TypeMember(anonymous_struct, "a", 0), TypeMember(anonymous_struct, "b", 64), ), ), """\ struct line_segment { struct { int x; int y; } a; struct { int x; int y; } b; }""", )
def test_init(self): m = TypeMember(self.prog.void_type()) self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) self.assertIsNone(m.name) self.assertEqual(m.bit_offset, 0) self.assertEqual(m.offset, 0) self.assertIsNone(m.bit_field_size) m = TypeMember(Object(self.prog, self.prog.void_type()), "foo") self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 0) self.assertEqual(m.offset, 0) self.assertIsNone(m.bit_field_size) m = TypeMember(self.prog.void_type(), "foo", 8) self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 8) self.assertEqual(m.offset, 1) self.assertIsNone(m.bit_field_size) self.assertRaises(TypeError, TypeMember, None) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), 1) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), "foo", None)
def test_struct_unnamed_member(self): self.assertPrettyPrint( self.prog.struct_type( "point3", 0, ( TypeMember( self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "x"), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ) ), TypeMember(self.prog.int_type("int", 4, True), "z", 64), ), ), """\ struct point3 { struct { int x; int y; }; int z; }""", )
def test_typedef(self): self.assertPrettyPrint(typedef_type("INT", int_type("int", 4, True)), "typedef int INT") self.assertPrettyPrint( typedef_type("CINT", int_type("int", 4, True, Qualifiers.CONST)), "typedef const int CINT", ) self.assertPrettyPrint( typedef_type("INT", int_type("int", 4, True), Qualifiers.CONST), "const typedef int INT", ) self.assertPrettyPrint( typedef_type("string", pointer_type(8, int_type("char", 1, True))), "typedef char *string", ) t = typedef_type( "Point", struct_type( None, 8, ( TypeMember(int_type("int", 4, True), "x", 0), TypeMember(int_type("int", 4, True), "y", 4), ), ), ) self.assertPrettyPrint( t, """\ typedef struct { int x; int y; } Point""", )
def test_init(self): m = TypeMember(self.prog.void_type()) self.assertIdentical(m.type, self.prog.void_type()) self.assertIsNone(m.name) self.assertEqual(m.bit_offset, 0) self.assertEqual(m.offset, 0) self.assertEqual(m.bit_field_size, 0) m = TypeMember(self.prog.void_type(), "foo") self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 0) self.assertEqual(m.offset, 0) self.assertEqual(m.bit_field_size, 0) m = TypeMember(self.prog.void_type(), "foo", 8) self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 8) self.assertEqual(m.offset, 1) self.assertEqual(m.bit_field_size, 0) m = TypeMember(self.prog.void_type(), "foo", 9, 7) self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 9) self.assertRaises(ValueError, getattr, m, "offset") self.assertEqual(m.bit_field_size, 7) self.assertRaises(TypeError, TypeMember, None) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), 1) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), "foo", None) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), "foo", 0, None)
def test_offsetof(self): self.assertEqual(offsetof(self.line_segment_type, "b"), 8) self.assertEqual(offsetof(self.line_segment_type, "a.y"), 4) self.assertRaisesRegex( LookupError, "'struct line_segment' has no member 'c'", offsetof, self.line_segment_type, "c.x", ) small_point_type = self.prog.struct_type( "small_point", 1, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0, 4), TypeMember(self.prog.int_type("int", 4, True), "y", 4, 4), ), ) self.assertEqual(offsetof(small_point_type, "x"), 0) self.assertRaisesRegex( ValueError, "member is not byte-aligned", offsetof, small_point_type, "y", )
def test_class_type(self): struct_class = self.prog.struct_type( "class", 8, (TypeMember(self.prog.pointer_type(self.prog.void_type()), "ptr"),), ) class_point = self.prog.class_type( "Point", 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ) self.types.append(struct_class) self.types.append(class_point) self.prog.language = Language.C self.assertIdentical(self.prog.type("struct class"), struct_class) self.prog.language = Language.CPP self.assertRaisesRegex( SyntaxError, "expected identifier after 'struct'", self.prog.type, "struct class", ) self.assertIdentical(self.prog.type("class Point"), class_point)
def test_union(self): t = union_type( "foo", 4, ( TypeMember(int_type("int", 4, True), "i"), TypeMember(array_type(4, int_type("unsigned char", 1, False)), "a"), ), ) self.assertPrettyPrint( t, """\ union foo { int i; unsigned char a[4]; }""", ) t = union_type( "foo", 4, ( TypeMember(int_type("int", 4, True), "i"), TypeMember(array_type(4, int_type("unsigned char", 1, False)), "a"), ), Qualifiers.CONST, ) self.assertPrettyPrint( t, """\ const union foo { int i; unsigned char a[4]; }""", )
def test_callable(self): m = TypeMember(self.prog.void_type) self.assertIdentical(m.type, self.prog.void_type()) m = TypeMember(lambda: self.prog.int_type("int", 4, True)) self.assertIdentical(m.type, self.prog.int_type("int", 4, True)) m = TypeMember(lambda: None) self.assertRaises(TypeError, getattr, m, "type")
def test_callable(self): m = TypeMember(void_type) self.assertEqual(m.type, void_type()) m = TypeMember(lambda: int_type("int", 4, True)) self.assertEqual(m.type, int_type("int", 4, True)) m = TypeMember(lambda: None) self.assertRaises(TypeError, getattr, m, "type")
def test_bad_thunk(self): t1 = self.prog.struct_type( "foo", 16, (TypeMember(lambda: exec('raise Exception("test")'), "bar"), )) with self.assertRaisesRegex(Exception, "test"): t1.members[0].type t1 = self.prog.struct_type("foo", 16, (TypeMember(lambda: 0, "bar"), )) with self.assertRaisesRegex(TypeError, "type callable must return Type"): t1.members[0].type
def test_repr(self): m = TypeMember(self.prog.void_type, name="foo") self.assertEqual( repr(m), "TypeMember(prog.type('void'), name='foo', bit_offset=0)") m = TypeMember(self.prog.void_type) self.assertEqual(repr(m), "TypeMember(prog.type('void'), bit_offset=0)") m = TypeMember(lambda: None) self.assertRaises(TypeError, repr, m)
def test_repr(self): m = TypeMember(type=void_type, name="foo") self.assertEqual( repr(m), "TypeMember(type=void_type(), name='foo', bit_offset=0)") m = TypeMember(type=void_type, bit_field_size=4) self.assertEqual( repr(m), "TypeMember(type=void_type(), name=None, bit_offset=0, bit_field_size=4)", ) m = TypeMember(lambda: None) self.assertRaises(TypeError, repr, m)
def test_bit_field(self): self.assertPrettyPrint( self.prog.struct_type( "point", 4, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0, 4), TypeMember(self.prog.int_type("int", 4, True), "y", 4, 8), ), ), """\ struct point { int x : 4; int y : 8; }""", )
def test_different_programs_compound_callback(self): with self.assertRaisesRegex(ValueError, "objects are from different program"): self.prog.struct_type( None, 4, (TypeMember(lambda: mock_program().int_type("int", 4, True)), )).members[0].type
def test_anonymous_struct(self): self.assertPrettyPrint( self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ), """\ struct { int x; int y; }""", )
def test_compound_offset(self): value = {"n": 23, "x": 100, "y": -5} obj = Object( self.prog, self.prog.struct_type( None, 12, ( TypeMember(self.prog.int_type("int", 4, True), "n"), TypeMember(self.point_type, None, 32), ), ), value, ) self.assertEqual(obj.value_(), value) self.assertIdentical(obj.x, Object(self.prog, "int", value=100)) self.assertIdentical(obj.y, Object(self.prog, "int", value=-5))
def test_infinite(self): f = lambda: struct_type("foo", 0, (TypeMember(f, "next"), )) self.assertEqual( repr(f()), "struct_type(tag='foo', size=0, members=(TypeMember(type=struct_type(tag='foo', ...), name='next', bit_offset=0),))", ) with self.assertRaisesRegex(RecursionError, "maximum.*depth"): f() == f()
def test_different_programs_compound(self): self.assertRaisesRegex( ValueError, "object is from different program", self.prog.struct_type, None, 4, (TypeMember(mock_program().int_type("int", 4, True)), ), )
def test_typedef_struct(self): self.assertPrettyPrint( self.prog.typedef_type( "Point", self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ), ), """\ typedef struct { int x; int y; } Point""", )
def test_cycle(self): t1 = struct_type("foo", 8, (TypeMember(lambda: pointer_type(8, t1), "next"), )) t2 = struct_type("foo", 8, (TypeMember(lambda: pointer_type(8, t2), "next"), )) t3, t4 = ( struct_type("foo", 8, (TypeMember(lambda: pointer_type(8, t4), "next"), )), struct_type("foo", 8, (TypeMember(lambda: pointer_type(8, t3), "next"), )), ) self.assertEqual(t1, t2) self.assertEqual(t2, t3) self.assertEqual(t3, t4) self.assertEqual( repr(t1), "struct_type(tag='foo', size=8, members=(TypeMember(type=pointer_type(size=8, type=struct_type(tag='foo', ...)), name='next', bit_offset=0),))", )
def test_repr(self): m = TypeMember(self.prog.void_type, name="foo") self.assertEqual( repr(m), "TypeMember(prog.type('void'), name='foo', bit_offset=0)") m = TypeMember(self.prog.void_type) self.assertEqual(repr(m), "TypeMember(prog.type('void'), bit_offset=0)") m = TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=1)) self.assertEqual( repr(m), "TypeMember(Object(prog, 'int', bit_field_size=1), bit_offset=0)") m = TypeMember(lambda: None) self.assertRaises(TypeError, repr, m)
def setUp(self): super().setUp() self.types = [] self.objects = [] self.prog = mock_program(types=self.types, objects=self.objects) self.coord_type = self.prog.class_type( "coord", 12, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), TypeMember(self.prog.int_type("int", 4, True), "z", 64), ), ) self.point_type = self.prog.struct_type( "point", 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ) self.line_segment_type = self.prog.struct_type( "line_segment", 16, (TypeMember(self.point_type, "a"), TypeMember(self.point_type, "b", 64)), ) self.option_type = self.prog.union_type( "option", 4, ( TypeMember(self.prog.int_type("int", 4, True), "i"), TypeMember(self.prog.float_type("float", 4), "f"), ), ) self.color_type = self.prog.enum_type( "color", self.prog.int_type("unsigned int", 4, False), ( TypeEnumerator("RED", 0), TypeEnumerator("GREEN", 1), TypeEnumerator("BLUE", 2), ), ) self.pid_type = self.prog.typedef_type( "pid_t", self.prog.int_type("int", 4, True))
def test_function_no_name(self): self.assertRaisesRegex( ValueError, "function must have name", str, struct_type( "foo", 8, (TypeMember(function_type(int_type("int", 4, True), (), False), None),), ), )
def test_non_scalar_bit_offset(self): obj = Object( self.prog, self.prog.struct_type( "weird", 9, (TypeMember(self.point_type, "point", bit_offset=1),) ), value={}, ) self.assertRaisesRegex( ValueError, "non-scalar must be byte-aligned", obj.member_, "point" )
def test_union(self): self.assertPrettyPrint( self.prog.union_type( "foo", 4, ( TypeMember(self.prog.int_type("int", 4, True), "i"), TypeMember( self.prog.array_type( self.prog.int_type("unsigned char", 1, False), 4 ), "a", ), ), ), """\ union foo { int i; unsigned char a[4]; }""", )
def test_member(self): t = self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember( self.prog.struct_type( None, 4, (TypeMember(self.prog.int_type("int", 4, True), "y", 0), ), ), None, 32, ), ), ) self.assertIdentical( t.member("x"), TypeMember(self.prog.int_type("int", 4, True), "x", 0)) self.assertIdentical( t.member("y"), TypeMember(self.prog.int_type("int", 4, True), "y", 32)) self.assertRaises(LookupError, t.member, "z") self.assertIdentical( t.members[1].type.member("y"), TypeMember(self.prog.int_type("int", 4, True), "y", 0), ) self.assertRaises(TypeError, self.prog.int_type("int", 4, True).member, "foo")
def test_struct(self): self.add_memory_segment( ( (99).to_bytes(4, "little") + (-1).to_bytes(4, "little", signed=True) + (12345).to_bytes(4, "little") + (0).to_bytes(4, "little") ), virt_addr=0xFFFF0000, ) self.types.append(self.point_type) obj = Object(self.prog, "struct point", address=0xFFFF0000) self.assertEqual(obj.value_(), {"x": 99, "y": -1}) self.assertEqual(sizeof(obj), 8) type_ = self.prog.struct_type( "foo", 16, ( TypeMember(self.point_type, "point"), TypeMember( self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "bar"), TypeMember(self.prog.int_type("int", 4, True), "baz", 32), ), ), None, 64, ), ), ) obj = Object(self.prog, type_, address=0xFFFF0000) self.assertEqual( obj.value_(), {"point": {"x": 99, "y": -1}, "bar": 12345, "baz": 0} )
def test_cycle2(self): t1 = self.prog.struct_type( "list_head", 16, ( TypeMember(lambda: self.prog.pointer_type(t1), "next"), TypeMember(lambda: self.prog.pointer_type(t1), "prev", 8), ), ) t2 = self.prog.struct_type( "list_head", 16, ( TypeMember(lambda: self.prog.pointer_type(t2), "next"), TypeMember(lambda: self.prog.pointer_type(t2), "prev", 8), ), ) self.assertIdentical(t1, t2) self.assertEqual( repr(t1), "prog.struct_type(tag='list_head', size=16, members=(TypeMember(prog.type('struct list_head *'), name='next', bit_offset=0), TypeMember(prog.type('struct list_head *'), name='prev', bit_offset=8)))", )
def test_cycle(self): t1 = self.prog.struct_type( "foo", 8, (TypeMember(lambda: self.prog.pointer_type(t1), "next"), )) t2 = self.prog.struct_type( "foo", 8, (TypeMember(lambda: self.prog.pointer_type(t2), "next"), )) t3, t4 = ( self.prog.struct_type( "foo", 8, (TypeMember(lambda: self.prog.pointer_type(t4), "next"), )), self.prog.struct_type( "foo", 8, (TypeMember(lambda: self.prog.pointer_type(t3), "next"), )), ) self.assertIdentical(t1, t2) self.assertIdentical(t2, t3) self.assertIdentical(t3, t4) self.assertEqual( repr(t1), "prog.struct_type(tag='foo', size=8, members=(TypeMember(prog.type('struct foo *'), name='next', bit_offset=0),))", )