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