1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import sys
6
7import module as mojom
8import pack
9import test_support
10
11
12EXPECT_EQ = test_support.EXPECT_EQ
13EXPECT_TRUE = test_support.EXPECT_TRUE
14RunTest = test_support.RunTest
15
16
17def TestOrdinalOrder():
18  errors = 0
19  struct = mojom.Struct('test')
20  struct.AddField('testfield1', mojom.INT32, 2)
21  struct.AddField('testfield2', mojom.INT32, 1)
22  ps = pack.PackedStruct(struct)
23
24  errors += EXPECT_EQ(2, len(ps.packed_fields))
25  errors += EXPECT_EQ('testfield2', ps.packed_fields[0].field.name)
26  errors += EXPECT_EQ('testfield1', ps.packed_fields[1].field.name)
27
28  return errors
29
30def TestZeroFields():
31  errors = 0
32  struct = mojom.Struct('test')
33  ps = pack.PackedStruct(struct)
34  errors += EXPECT_EQ(0, len(ps.packed_fields))
35  return errors
36
37
38def TestOneField():
39  errors = 0
40  struct = mojom.Struct('test')
41  struct.AddField('testfield1', mojom.INT8)
42  ps = pack.PackedStruct(struct)
43  errors += EXPECT_EQ(1, len(ps.packed_fields))
44  return errors
45
46# Pass three tuples.
47# |kinds| is a sequence of mojom.Kinds that specify the fields that are to
48# be created.
49# |fields| is the expected order of the resulting fields, with the integer
50# "1" first.
51# |offsets| is the expected order of offsets, with the integer "0" first.
52def TestSequence(kinds, fields, offsets):
53  errors = 0
54  struct = mojom.Struct('test')
55  index = 1
56  for kind in kinds:
57    struct.AddField("%d" % index, kind)
58    index += 1
59  ps = pack.PackedStruct(struct)
60  num_fields = len(ps.packed_fields)
61  errors += EXPECT_EQ(len(kinds), num_fields)
62  for i in xrange(num_fields):
63    EXPECT_EQ("%d" % fields[i], ps.packed_fields[i].field.name)
64    EXPECT_EQ(offsets[i], ps.packed_fields[i].offset)
65
66  return errors
67
68
69def TestPaddingPackedInOrder():
70  return TestSequence(
71      (mojom.INT8, mojom.UINT8, mojom.INT32),
72      (1, 2, 3),
73      (0, 1, 4))
74
75
76def TestPaddingPackedOutOfOrder():
77  return TestSequence(
78      (mojom.INT8, mojom.INT32, mojom.UINT8),
79      (1, 3, 2),
80      (0, 1, 4))
81
82
83def TestPaddingPackedOverflow():
84  kinds = (mojom.INT8, mojom.INT32, mojom.INT16, mojom.INT8, mojom.INT8)
85  # 2 bytes should be packed together first, followed by short, then by int.
86  fields = (1, 4, 3, 2, 5)
87  offsets = (0, 1, 2, 4, 8)
88  return TestSequence(kinds, fields, offsets)
89
90
91def TestNullableTypes():
92  kinds = (mojom.STRING.MakeNullableKind(),
93           mojom.HANDLE.MakeNullableKind(),
94           mojom.Struct('test_struct').MakeNullableKind(),
95           mojom.DCPIPE.MakeNullableKind(),
96           mojom.Array().MakeNullableKind(),
97           mojom.DPPIPE.MakeNullableKind(),
98           mojom.Array(length=5).MakeNullableKind(),
99           mojom.MSGPIPE.MakeNullableKind(),
100           mojom.Interface('test_inteface').MakeNullableKind(),
101           mojom.SHAREDBUFFER.MakeNullableKind(),
102           mojom.InterfaceRequest().MakeNullableKind())
103  fields = (1, 2, 4, 3, 5, 6, 8, 7, 9, 10, 11)
104  offsets = (0, 8, 12, 16, 24, 32, 36, 40, 48, 52, 56)
105  return TestSequence(kinds, fields, offsets)
106
107
108def TestAllTypes():
109  return TestSequence(
110      (mojom.BOOL, mojom.INT8, mojom.STRING, mojom.UINT8,
111       mojom.INT16, mojom.DOUBLE, mojom.UINT16,
112       mojom.INT32, mojom.UINT32, mojom.INT64,
113       mojom.FLOAT, mojom.STRING, mojom.HANDLE,
114       mojom.UINT64, mojom.Struct('test'), mojom.Array(),
115       mojom.STRING.MakeNullableKind()),
116      (1, 2, 4, 5, 7, 3, 6,  8,  9,  10, 11, 13, 12, 14, 15, 16, 17, 18),
117      (0, 1, 2, 4, 6, 8, 16, 24, 28, 32, 40, 44, 48, 56, 64, 72, 80, 88))
118
119
120def TestPaddingPackedOutOfOrderByOrdinal():
121  errors = 0
122  struct = mojom.Struct('test')
123  struct.AddField('testfield1', mojom.INT8)
124  struct.AddField('testfield3', mojom.UINT8, 3)
125  struct.AddField('testfield2', mojom.INT32, 2)
126  ps = pack.PackedStruct(struct)
127  errors += EXPECT_EQ(3, len(ps.packed_fields))
128
129  # Second byte should be packed in behind first, altering order.
130  errors += EXPECT_EQ('testfield1', ps.packed_fields[0].field.name)
131  errors += EXPECT_EQ('testfield3', ps.packed_fields[1].field.name)
132  errors += EXPECT_EQ('testfield2', ps.packed_fields[2].field.name)
133
134  # Second byte should be packed with first.
135  errors += EXPECT_EQ(0, ps.packed_fields[0].offset)
136  errors += EXPECT_EQ(1, ps.packed_fields[1].offset)
137  errors += EXPECT_EQ(4, ps.packed_fields[2].offset)
138
139  return errors
140
141
142def TestBools():
143  errors = 0
144  struct = mojom.Struct('test')
145  struct.AddField('bit0', mojom.BOOL)
146  struct.AddField('bit1', mojom.BOOL)
147  struct.AddField('int', mojom.INT32)
148  struct.AddField('bit2', mojom.BOOL)
149  struct.AddField('bit3', mojom.BOOL)
150  struct.AddField('bit4', mojom.BOOL)
151  struct.AddField('bit5', mojom.BOOL)
152  struct.AddField('bit6', mojom.BOOL)
153  struct.AddField('bit7', mojom.BOOL)
154  struct.AddField('bit8', mojom.BOOL)
155  ps = pack.PackedStruct(struct)
156  errors += EXPECT_EQ(10, len(ps.packed_fields))
157
158  # First 8 bits packed together.
159  for i in xrange(8):
160    pf = ps.packed_fields[i]
161    errors += EXPECT_EQ(0, pf.offset)
162    errors += EXPECT_EQ("bit%d" % i, pf.field.name)
163    errors += EXPECT_EQ(i, pf.bit)
164
165  # Ninth bit goes into second byte.
166  errors += EXPECT_EQ("bit8", ps.packed_fields[8].field.name)
167  errors += EXPECT_EQ(1, ps.packed_fields[8].offset)
168  errors += EXPECT_EQ(0, ps.packed_fields[8].bit)
169
170  # int comes last.
171  errors += EXPECT_EQ("int", ps.packed_fields[9].field.name)
172  errors += EXPECT_EQ(4, ps.packed_fields[9].offset)
173
174  return errors
175
176
177def Main(args):
178  errors = 0
179  errors += RunTest(TestZeroFields)
180  errors += RunTest(TestOneField)
181  errors += RunTest(TestPaddingPackedInOrder)
182  errors += RunTest(TestPaddingPackedOutOfOrder)
183  errors += RunTest(TestPaddingPackedOverflow)
184  errors += RunTest(TestNullableTypes)
185  errors += RunTest(TestAllTypes)
186  errors += RunTest(TestPaddingPackedOutOfOrderByOrdinal)
187  errors += RunTest(TestBools)
188
189  return errors
190
191
192if __name__ == '__main__':
193  sys.exit(Main(sys.argv[1:]))
194