1- from ctypes import Structure , c_char , c_uint32 , c_ubyte , alignment
1+ from ctypes import Structure , c_char , c_uint32 , c_ubyte , alignment , sizeof , Union
22import inspect
33import unittest
44
@@ -22,11 +22,11 @@ class Main(Structure):
2222 ('string' , Aligned ),
2323 ]
2424
25- d = Main .from_buffer (data )
26- self .assertEqual (d .first , 7 )
27- self .assertEqual (d .string .value , b'hello world!' )
25+ main = Main .from_buffer (data )
26+ self .assertEqual (main .first , 7 )
27+ self .assertEqual (main .string .value , b'hello world!' )
2828 self .assertEqual (
29- bytes (d .string .__buffer__ (inspect .BufferFlags .SIMPLE )),
29+ bytes (main .string .__buffer__ (inspect .BufferFlags .SIMPLE )),
3030 b'\x68 \x65 \x6c \x6c \x6f \x20 \x77 \x6f \x72 \x6c \x64 \x21 \x00 \x00 \x00 \x00 '
3131 )
3232
@@ -60,12 +60,12 @@ class MainTooBig(Structure):
6060 ("x" , SomeBoolsTooBig ),
6161 ("y" , c_uint32 ),
6262 ]
63- d = Main .from_buffer (data )
64- self .assertEqual (d .y , 7 )
63+ main = Main .from_buffer (data )
64+ self .assertEqual (main .y , 7 )
6565 self .assertEqual (alignment (SomeBools ), 4 )
66- self .assertEqual (d .x .bool1 , True )
67- self .assertEqual (d .x .bool2 , False )
68- self .assertEqual (d .x .bool3 , True )
66+ self .assertEqual (main .x .bool1 , True )
67+ self .assertEqual (main .x .bool2 , False )
68+ self .assertEqual (main .x .bool3 , True )
6969
7070 with self .assertRaises (ValueError ) as ctx :
7171 MainTooBig .from_buffer (data )
@@ -74,5 +74,92 @@ class MainTooBig(Structure):
7474 'Buffer size too small (4 instead of at least 8 bytes)'
7575 )
7676
77+ def test_aligned_subclasses (self ):
78+ data = bytearray (
79+ b"\x01 \x00 \x00 \x00 \x02 \x00 \x00 \x00 \x03 \x00 \x00 \x00 \x04 \x00 \x00 \x00 "
80+ )
81+
82+ class UnalignedSub (Structure ):
83+ x : c_uint32
84+ _fields_ = [
85+ ("x" , c_uint32 ),
86+ ]
87+
88+ class AlignedStruct (UnalignedSub ):
89+ _align_ = 8
90+ y : c_uint32
91+ _fields_ = [
92+ ("y" , c_uint32 ),
93+ ]
94+
95+ class Main (Structure ):
96+ _fields_ = [
97+ ("a" , c_uint32 ),
98+ ("b" , AlignedStruct )
99+ ]
100+
101+ main = Main .from_buffer (data )
102+ self .assertEqual (alignment (main .b ), 8 )
103+ self .assertEqual (alignment (main ), 8 )
104+ self .assertEqual (sizeof (main .b ), 8 )
105+ self .assertEqual (sizeof (main ), 16 )
106+ self .assertEqual (main .a , 1 )
107+ self .assertEqual (main .b .x , 3 )
108+ self .assertEqual (main .b .y , 4 )
109+
110+ def test_aligned_union (self ):
111+ data = bytearray (
112+ b"\x01 \x00 \x00 \x00 \x02 \x00 \x00 \x00 \x03 \x00 \x00 \x00 \x04 \x00 \x00 \x00 "
113+ )
114+
115+ class AlignedUnion (Union ):
116+ _align_ = 8
117+ _fields_ = [
118+ ("a" , c_uint32 ),
119+ ("b" , c_ubyte * 8 ),
120+ ]
121+
122+ class Main (Structure ):
123+ _fields_ = [
124+ ("first" , c_uint32 ),
125+ ("union" , AlignedUnion ),
126+ ]
127+
128+ main = Main .from_buffer (data )
129+ self .assertEqual (main .first , 1 )
130+ self .assertEqual (main .union .a , 3 )
131+ self .assertEqual (bytes (main .union .b ), b"\x03 \x00 \x00 \x00 \x04 \x00 \x00 \x00 " )
132+
133+ def test_aligned_struct_in_union (self ):
134+ data = bytearray (
135+ b"\x01 \x00 \x00 \x00 \x02 \x00 \x00 \x00 \x03 \x00 \x00 \x00 \x04 \x00 \x00 \x00 "
136+ )
137+
138+ class Sub (Structure ):
139+ _align_ = 8
140+ _fields_ = [
141+ ("x" , c_uint32 ),
142+ ("y" , c_uint32 ),
143+ ]
144+
145+ class MainUnion (Union ):
146+ _fields_ = [
147+ ("a" , c_uint32 ),
148+ ("b" , Sub ),
149+ ]
150+
151+ class Main (Structure ):
152+ _fields_ = [
153+ ("first" , c_uint32 ),
154+ ("union" , MainUnion ),
155+ ]
156+
157+ main = Main .from_buffer (data )
158+ self .assertEqual (main .first , 1 )
159+ self .assertEqual (main .union .a , 3 )
160+ self .assertEqual (main .union .b .x , 3 )
161+ self .assertEqual (main .union .b .y , 4 )
162+
163+
77164if __name__ == '__main__' :
78165 unittest .main ()
0 commit comments