xref: /aosp_15_r20/kernel/tests/net/test/cstruct_test.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2016 The Android Open Source Project
4*2f2c4c7aSAndroid Build Coastguard Worker#
5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*2f2c4c7aSAndroid Build Coastguard Worker#
9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0
10*2f2c4c7aSAndroid Build Coastguard Worker#
11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License.
16*2f2c4c7aSAndroid Build Coastguard Worker
17*2f2c4c7aSAndroid Build Coastguard Workerimport binascii
18*2f2c4c7aSAndroid Build Coastguard Workerimport unittest
19*2f2c4c7aSAndroid Build Coastguard Worker
20*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct
21*2f2c4c7aSAndroid Build Coastguard Worker
22*2f2c4c7aSAndroid Build Coastguard Worker
23*2f2c4c7aSAndroid Build Coastguard Worker# These aren't constants, they're classes. So, pylint: disable=invalid-name
24*2f2c4c7aSAndroid Build Coastguard WorkerTestStructA = cstruct.Struct("TestStructA", "=BI", "byte1 int2")
25*2f2c4c7aSAndroid Build Coastguard WorkerTestStructB = cstruct.Struct("TestStructB", "=BI", "byte1 int2")
26*2f2c4c7aSAndroid Build Coastguard Worker
27*2f2c4c7aSAndroid Build Coastguard Worker
28*2f2c4c7aSAndroid Build Coastguard Workerclass CstructTest(unittest.TestCase):
29*2f2c4c7aSAndroid Build Coastguard Worker
30*2f2c4c7aSAndroid Build Coastguard Worker  def CheckEquals(self, a, b):
31*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(a, b)
32*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b, a)
33*2f2c4c7aSAndroid Build Coastguard Worker    assert a == b
34*2f2c4c7aSAndroid Build Coastguard Worker    assert b == a
35*2f2c4c7aSAndroid Build Coastguard Worker    assert not (a != b)  # pylint: disable=g-comparison-negation,superfluous-parens
36*2f2c4c7aSAndroid Build Coastguard Worker    assert not (b != a)  # pylint: disable=g-comparison-negation,superfluous-parens
37*2f2c4c7aSAndroid Build Coastguard Worker
38*2f2c4c7aSAndroid Build Coastguard Worker  def CheckNotEquals(self, a, b):
39*2f2c4c7aSAndroid Build Coastguard Worker    self.assertNotEqual(a, b)
40*2f2c4c7aSAndroid Build Coastguard Worker    self.assertNotEqual(b, a)
41*2f2c4c7aSAndroid Build Coastguard Worker    assert a != b
42*2f2c4c7aSAndroid Build Coastguard Worker    assert b != a
43*2f2c4c7aSAndroid Build Coastguard Worker    assert not (a == b)  # pylint: disable=g-comparison-negation,superfluous-parens
44*2f2c4c7aSAndroid Build Coastguard Worker    assert not (b == a)  # pylint: disable=g-comparison-negation,superfluous-parens
45*2f2c4c7aSAndroid Build Coastguard Worker
46*2f2c4c7aSAndroid Build Coastguard Worker  def testEqAndNe(self):
47*2f2c4c7aSAndroid Build Coastguard Worker    a1 = TestStructA((1, 2))
48*2f2c4c7aSAndroid Build Coastguard Worker    a2 = TestStructA((2, 3))
49*2f2c4c7aSAndroid Build Coastguard Worker    a3 = TestStructA((1, 2))
50*2f2c4c7aSAndroid Build Coastguard Worker    b = TestStructB((1, 2))
51*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckNotEquals(a1, b)
52*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckNotEquals(a2, b)
53*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckNotEquals(a1, a2)
54*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckNotEquals(a2, a3)
55*2f2c4c7aSAndroid Build Coastguard Worker    for i in [a1, a2, a3, b]:
56*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckEquals(i, i)
57*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckEquals(a1, a3)
58*2f2c4c7aSAndroid Build Coastguard Worker
59*2f2c4c7aSAndroid Build Coastguard Worker  def testNestedStructs(self):
60*2f2c4c7aSAndroid Build Coastguard Worker    Nested = cstruct.Struct("Nested", "!HSSi",
61*2f2c4c7aSAndroid Build Coastguard Worker                            "word1 nest2 nest3 int4",
62*2f2c4c7aSAndroid Build Coastguard Worker                            [TestStructA, TestStructB])
63*2f2c4c7aSAndroid Build Coastguard Worker    DoubleNested = cstruct.Struct("DoubleNested", "SSB",
64*2f2c4c7aSAndroid Build Coastguard Worker                                  "nest1 nest2 byte3",
65*2f2c4c7aSAndroid Build Coastguard Worker                                  [TestStructA, Nested])
66*2f2c4c7aSAndroid Build Coastguard Worker    d = DoubleNested((TestStructA((1, 2)),
67*2f2c4c7aSAndroid Build Coastguard Worker                      Nested((5, TestStructA((3, 4)), TestStructB((7, 8)), 9)),
68*2f2c4c7aSAndroid Build Coastguard Worker                      6))
69*2f2c4c7aSAndroid Build Coastguard Worker
70*2f2c4c7aSAndroid Build Coastguard Worker    expectedlen = (len(TestStructA) +
71*2f2c4c7aSAndroid Build Coastguard Worker                   2 + len(TestStructA) + len(TestStructB) + 4 +
72*2f2c4c7aSAndroid Build Coastguard Worker                   1)
73*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expectedlen, len(DoubleNested))
74*2f2c4c7aSAndroid Build Coastguard Worker
75*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(7, d.nest2.nest3.byte1)
76*2f2c4c7aSAndroid Build Coastguard Worker
77*2f2c4c7aSAndroid Build Coastguard Worker    d.byte3 = 252
78*2f2c4c7aSAndroid Build Coastguard Worker    d.nest2.word1 = 33214
79*2f2c4c7aSAndroid Build Coastguard Worker    n = d.nest2
80*2f2c4c7aSAndroid Build Coastguard Worker    n.int4 = -55
81*2f2c4c7aSAndroid Build Coastguard Worker    t = n.nest3
82*2f2c4c7aSAndroid Build Coastguard Worker    t.int2 = 33627591
83*2f2c4c7aSAndroid Build Coastguard Worker
84*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(33627591, d.nest2.nest3.int2)
85*2f2c4c7aSAndroid Build Coastguard Worker
86*2f2c4c7aSAndroid Build Coastguard Worker    expected = (
87*2f2c4c7aSAndroid Build Coastguard Worker        "DoubleNested(nest1=TestStructA(byte1=1, int2=2),"
88*2f2c4c7aSAndroid Build Coastguard Worker        " nest2=Nested(word1=33214, nest2=TestStructA(byte1=3, int2=4),"
89*2f2c4c7aSAndroid Build Coastguard Worker        " nest3=TestStructB(byte1=7, int2=33627591), int4=-55), byte3=252)")
90*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, str(d))
91*2f2c4c7aSAndroid Build Coastguard Worker    expected = binascii.unhexlify("01" "02000000"
92*2f2c4c7aSAndroid Build Coastguard Worker                                  "81be" "03" "04000000"
93*2f2c4c7aSAndroid Build Coastguard Worker                                  "07" "c71d0102" "ffffffc9" "fc")
94*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, d.Pack())
95*2f2c4c7aSAndroid Build Coastguard Worker    unpacked = DoubleNested(expected)
96*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckEquals(unpacked, d)
97*2f2c4c7aSAndroid Build Coastguard Worker
98*2f2c4c7aSAndroid Build Coastguard Worker  def testNullTerminatedStrings(self):
99*2f2c4c7aSAndroid Build Coastguard Worker    TestStruct = cstruct.Struct("TestStruct", "B16si16AH",
100*2f2c4c7aSAndroid Build Coastguard Worker                                "byte1 string2 int3 ascii4 word5")
101*2f2c4c7aSAndroid Build Coastguard Worker    nullstr = b"hello" + (16 - len("hello")) * b"\x00"
102*2f2c4c7aSAndroid Build Coastguard Worker
103*2f2c4c7aSAndroid Build Coastguard Worker    t = TestStruct((2, nullstr, 12345, nullstr, 33210))
104*2f2c4c7aSAndroid Build Coastguard Worker    expected = ("TestStruct(byte1=2, string2=68656c6c6f0000000000000000000000,"
105*2f2c4c7aSAndroid Build Coastguard Worker                " int3=12345, ascii4=hello, word5=33210)")
106*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, str(t))
107*2f2c4c7aSAndroid Build Coastguard Worker
108*2f2c4c7aSAndroid Build Coastguard Worker    embeddednull = b"hello\x00visible123"
109*2f2c4c7aSAndroid Build Coastguard Worker    t = TestStruct((2, embeddednull, 12345, embeddednull, 33210))
110*2f2c4c7aSAndroid Build Coastguard Worker    expected = ("TestStruct(byte1=2, string2=68656c6c6f0076697369626c65313233,"
111*2f2c4c7aSAndroid Build Coastguard Worker                " int3=12345, ascii4=hello\x00visible123, word5=33210)")
112*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, str(t))
113*2f2c4c7aSAndroid Build Coastguard Worker
114*2f2c4c7aSAndroid Build Coastguard Worker    embedded_non_ascii = b"hello\xc0visible123"
115*2f2c4c7aSAndroid Build Coastguard Worker    t = TestStruct((2, embedded_non_ascii, 12345, embeddednull, 33210))
116*2f2c4c7aSAndroid Build Coastguard Worker    expected = ("TestStruct(byte1=2, string2=68656c6c6fc076697369626c65313233,"
117*2f2c4c7aSAndroid Build Coastguard Worker                " int3=12345, ascii4=hello\x00visible123, word5=33210)")
118*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, str(t))
119*2f2c4c7aSAndroid Build Coastguard Worker
120*2f2c4c7aSAndroid Build Coastguard Worker  def testZeroInitialization(self):
121*2f2c4c7aSAndroid Build Coastguard Worker    TestStruct = cstruct.Struct("TestStruct", "B16si16AH",
122*2f2c4c7aSAndroid Build Coastguard Worker                                "byte1 string2 int3 ascii4 word5")
123*2f2c4c7aSAndroid Build Coastguard Worker    t = TestStruct()
124*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, t.byte1)
125*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"\x00" * 16, t.string2)
126*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, t.int3)
127*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"\x00" * 16, t.ascii4)
128*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, t.word5)
129*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"\x00" * len(TestStruct), t.Pack())
130*2f2c4c7aSAndroid Build Coastguard Worker
131*2f2c4c7aSAndroid Build Coastguard Worker  def testKeywordInitialization(self):
132*2f2c4c7aSAndroid Build Coastguard Worker    TestStruct = cstruct.Struct("TestStruct", "=B16sIH",
133*2f2c4c7aSAndroid Build Coastguard Worker                                "byte1 string2 int3 word4")
134*2f2c4c7aSAndroid Build Coastguard Worker    bytes = b"hello world! ^_^"
135*2f2c4c7aSAndroid Build Coastguard Worker    hex_bytes = binascii.hexlify(bytes)
136*2f2c4c7aSAndroid Build Coastguard Worker
137*2f2c4c7aSAndroid Build Coastguard Worker    # Populate all fields
138*2f2c4c7aSAndroid Build Coastguard Worker    t1 = TestStruct(byte1=1, string2=bytes, int3=0xFEDCBA98, word4=0x1234)
139*2f2c4c7aSAndroid Build Coastguard Worker    expected = binascii.unhexlify(b"01" + hex_bytes + b"98BADCFE" b"3412")
140*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, t1.Pack())
141*2f2c4c7aSAndroid Build Coastguard Worker
142*2f2c4c7aSAndroid Build Coastguard Worker    # Partially populated
143*2f2c4c7aSAndroid Build Coastguard Worker    t1 = TestStruct(string2=bytes, word4=0x1234)
144*2f2c4c7aSAndroid Build Coastguard Worker    expected = binascii.unhexlify(b"00" + hex_bytes + b"00000000" b"3412")
145*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, t1.Pack())
146*2f2c4c7aSAndroid Build Coastguard Worker
147*2f2c4c7aSAndroid Build Coastguard Worker  def testCstructOffset(self):
148*2f2c4c7aSAndroid Build Coastguard Worker    TestStruct = cstruct.Struct("TestStruct", "B16si16AH",
149*2f2c4c7aSAndroid Build Coastguard Worker                                "byte1 string2 int3 ascii4 word5")
150*2f2c4c7aSAndroid Build Coastguard Worker    nullstr = b"hello" + (16 - len("hello")) * b"\x00"
151*2f2c4c7aSAndroid Build Coastguard Worker    t = TestStruct((2, nullstr, 12345, nullstr, 33210))
152*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, t.offset("byte1"))
153*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, t.offset("string2"))  # sizeof(byte)
154*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(17, t.offset("int3"))    # sizeof(byte) + 16*sizeof(char)
155*2f2c4c7aSAndroid Build Coastguard Worker    # The integer is automatically padded by the struct module
156*2f2c4c7aSAndroid Build Coastguard Worker    # to match native alignment.
157*2f2c4c7aSAndroid Build Coastguard Worker    # offset = sizeof(byte) + 16*sizeof(char) + padding + sizeof(int)
158*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(24, t.offset("ascii4"))
159*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(40, t.offset("word5"))
160*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaises(KeyError, t.offset, "random")
161*2f2c4c7aSAndroid Build Coastguard Worker
162*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: Add support for nested struct offset
163*2f2c4c7aSAndroid Build Coastguard Worker    Nested = cstruct.Struct("Nested", "!HSSi", "word1 nest2 nest3 int4",
164*2f2c4c7aSAndroid Build Coastguard Worker                            [TestStructA, TestStructB])
165*2f2c4c7aSAndroid Build Coastguard Worker    DoubleNested = cstruct.Struct("DoubleNested", "SSB", "nest1 nest2 byte3",
166*2f2c4c7aSAndroid Build Coastguard Worker                                  [TestStructA, Nested])
167*2f2c4c7aSAndroid Build Coastguard Worker    d = DoubleNested((TestStructA((1, 2)), Nested((5, TestStructA((3, 4)),
168*2f2c4c7aSAndroid Build Coastguard Worker                                                   TestStructB((7, 8)), 9)), 6))
169*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, d.offset("nest1"))
170*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(len(TestStructA), d.offset("nest2"))
171*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(len(TestStructA) + len(Nested), d.offset("byte3"))
172*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaises(KeyError, t.offset, "word1")
173*2f2c4c7aSAndroid Build Coastguard Worker
174*2f2c4c7aSAndroid Build Coastguard Worker  def testDefinitionFieldMismatch(self):
175*2f2c4c7aSAndroid Build Coastguard Worker    cstruct.Struct("TestA", "=BI", "byte1 int2")
176*2f2c4c7aSAndroid Build Coastguard Worker    cstruct.Struct("TestA", "=BxxxxxIx", "byte1 int2")
177*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaises(ValueError):
178*2f2c4c7aSAndroid Build Coastguard Worker      cstruct.Struct("TestA", "=B", "byte1 int2")
179*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaises(ValueError):
180*2f2c4c7aSAndroid Build Coastguard Worker      cstruct.Struct("TestA", "=BI", "byte1")
181*2f2c4c7aSAndroid Build Coastguard Worker
182*2f2c4c7aSAndroid Build Coastguard Worker    Nested = cstruct.Struct("Nested", "!II", "int1 int2")
183*2f2c4c7aSAndroid Build Coastguard Worker    cstruct.Struct("TestB", "=BSI", "byte1 nest2 int3", [Nested])
184*2f2c4c7aSAndroid Build Coastguard Worker    cstruct.Struct("TestB", "=BxSxIx", "byte1 nest2 int3", [Nested])
185*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaises(ValueError):
186*2f2c4c7aSAndroid Build Coastguard Worker      cstruct.Struct("TestB", "=BSI", "byte1 int3", [Nested])
187*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaises(ValueError):
188*2f2c4c7aSAndroid Build Coastguard Worker      cstruct.Struct("TestB", "=BSI", "byte1 nest2", [Nested])
189*2f2c4c7aSAndroid Build Coastguard Worker
190*2f2c4c7aSAndroid Build Coastguard Worker    cstruct.Struct("TestC", "=BSSI", "byte1 nest2 nest3 int4", [Nested, Nested])
191*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaises(ValueError):
192*2f2c4c7aSAndroid Build Coastguard Worker      cstruct.Struct("TestC", "=BSSI", "byte1 nest2 int4", [Nested, Nested])
193*2f2c4c7aSAndroid Build Coastguard Worker
194*2f2c4c7aSAndroid Build Coastguard Worker
195*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__":
196*2f2c4c7aSAndroid Build Coastguard Worker  unittest.main()
197