1#!/usr/bin/python2
2
3# Copyright 2015 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Unit tests for the libtpm2 structure_generator."""
8
9from __future__ import print_function
10
11import StringIO
12import os
13import unittest
14
15import extract_structures
16import structure_generator
17
18
19class TestGenerators(unittest.TestCase):
20  """Test structure_generator classes."""
21
22  def testTypedefMarshal(self):
23    """Test generation of marshaling code for typedefs."""
24    marshalled_types = set(['int'])
25    typedef = structure_generator.Typedef('int', 'INT')
26    typedef2 = structure_generator.Typedef('INT', 'INT2')
27    typemap = {'INT': typedef}
28    out_file = StringIO.StringIO()
29    typedef2.OutputMarshalImpl(out_file, marshalled_types, typemap)
30    self.assertIn('INT', marshalled_types)
31    self.assertIn('INT2', marshalled_types)
32    out_file.close()
33
34  def testConstantTypeMarshal(self):
35    """Test generation of marshaling code for constant types."""
36    marshalled_types = set(['int'])
37    typedef = structure_generator.Typedef('int', 'UINT16')
38    constant = structure_generator.ConstantType('UINT16', 'TPM_TYPE')
39    constant.valid_values.append('VALUE0')
40    constant.valid_values.append('VALUE1')
41    typemap = {'UINT16': typedef}
42    out_file = StringIO.StringIO()
43    constant.OutputMarshalImpl(out_file, marshalled_types, typemap)
44    self.assertIn('UINT16', marshalled_types)
45    self.assertIn('TPM_TYPE', marshalled_types)
46    out_file.close()
47
48  def testAttributeStructureMarshal(self):
49    """Test generation of marshaling code for attribute structures."""
50    marshalled_types = set(['int'])
51    typedef = structure_generator.Typedef('int', 'UINT16')
52    attributeStruct = structure_generator.AttributeStructure(
53        'UINT16', 'TPM_TYPE')
54    attributeStruct.reserved.append('4_7')
55    attributeStruct.reserved.append('1')
56    typemap = {'UINT16': typedef}
57    out_file = StringIO.StringIO()
58    attributeStruct.OutputMarshalImpl(out_file, marshalled_types, typemap)
59    self.assertIn('UINT16', marshalled_types)
60    self.assertIn('TPM_TYPE', marshalled_types)
61    out_file.close()
62
63  def testInterfacemarshal(self):
64    """test generation of marshaling code for interfaces."""
65    marshalled_types = set(['int'])
66    typedef = structure_generator.Typedef('int', 'UINT16')
67    interface = structure_generator.Interface('UINT16', 'TPM_TYPE')
68    interface.conditional = 'TPM_VALUE_NULL'
69    interface.bounds.append(('TPM_MIN', 'TPM_MAX'))
70    interface.valid_values.append('VALUE0')
71    interface.valid_values.append('VALUE1')
72    typemap = {'UINT16': typedef}
73    out_file = StringIO.StringIO()
74    interface.OutputMarshalImpl(out_file, marshalled_types, typemap)
75    self.assertIn('UINT16', marshalled_types)
76    self.assertIn('TPM_TYPE', marshalled_types)
77    out_file.close()
78
79  def testStructMarshal(self):
80    """Test generation of marshaling code for structures."""
81    marshalled_types = set(['int'])
82    struct = structure_generator.Structure('TEST_STRUCT')
83    struct.AddField(structure_generator.Field('UINT16', 'type', None, False))
84    struct.AddField(structure_generator.Field('TPMI_TYPE', 'interfaceField0',
85                                              'TRUE', False))
86    struct.AddField(structure_generator.Field('TPMI_TYPE', 'interfaceField1',
87                                              'FALSE', False))
88    struct.AddField(structure_generator.Field('TPMU_SYM_MODE', 'unionField',
89                                              'type', False))
90    struct.AddField(structure_generator.Field('UINT16', 'arrayField',
91                                              'MAX_VALUE', True))
92    typedef = structure_generator.Typedef('int', 'UINT16')
93    interface = structure_generator.Interface('UINT16', 'TPMI_TYPE')
94    # Choose TPMU_SYM_MODE because it exists in selectors definition and it
95    # has few fields.
96    union = structure_generator.Union('TPMU_SYM_MODE')
97    union.AddField(structure_generator.Field('UINT16', 'aes', None))
98    union.AddField(structure_generator.Field('UINT16', 'SM4', None))
99    typemap = {
100        'UINT16': typedef,
101        'TPMI_TYPE': interface,
102        'TPMU_SYM_MODE': union
103    }
104    out_file = StringIO.StringIO()
105    struct.OutputMarshalImpl(out_file, marshalled_types, typemap)
106    self.assertIn('UINT16', marshalled_types)
107    self.assertIn('TPMI_TYPE', marshalled_types)
108    self.assertIn('TPMU_SYM_MODE', marshalled_types)
109    self.assertIn('TEST_STRUCT', marshalled_types)
110    out_file.close()
111
112  def testUnionMarshal(self):
113    """Test generation of marshaling code for unions."""
114    marshalled_types = set(['int'])
115    union = structure_generator.Union('TPMU_SYM_MODE')
116    union.AddField(structure_generator.Field('UINT16', 'aes', None))
117    union.AddField(structure_generator.Field('UINT16', 'SM4', None))
118    typedef = structure_generator.Typedef('int', 'UINT16')
119    typemap = {'UINT16': typedef}
120    out_file = StringIO.StringIO()
121    union.OutputMarshalImpl(out_file, marshalled_types, typemap)
122    self.assertIn('UINT16', marshalled_types)
123    self.assertIn('TPMU_SYM_MODE', marshalled_types)
124    out_file.close()
125
126  def _MakeArg(self, arg_type, arg_name):
127    return {'type': arg_type,
128            'name': arg_name,
129            'command_code': None,
130            'description': None}
131
132
133class TestParser(unittest.TestCase):
134  """Test structure parser."""
135
136  def testStructureParser(self):
137    """Test the structure parser with valid data.
138
139       One of each typedef, constant type, attribute structure, interface,
140       structure, and union. Should appear in types array in that order.
141    """
142    html_parser = extract_structures.SpecParser()
143    html_file_name = os.path.join(os.path.dirname(__file__),
144                                  'test_structure_generator.html')
145    html_parser.feed(open(html_file_name).read())
146    html_parser.close()
147    types = html_parser.GetTable().GetTypeMap()
148    self.assertEqual(len(types), 6)
149    tpm_obj = types['UINT16']
150    self.assertEqual(tpm_obj.old_type, 'uint16_t')
151    self.assertEqual(tpm_obj.new_type, 'UINT16')
152    tpm_obj = types['TPMA_LOCALITY']
153    self.assertEqual(tpm_obj.old_type, 'base_type')
154    self.assertEqual(tpm_obj.new_type, 'TPMA_LOCALITY')
155    self.assertEqual(tpm_obj.reserved[0], '4_7')
156    self.assertEqual(tpm_obj.reserved[1], '9')
157    tpm_obj = types['const_type']
158    self.assertEqual(tpm_obj.old_type, 'base_type')
159    self.assertEqual(tpm_obj.new_type, 'const_type')
160    self.assertEqual(tpm_obj.valid_values[0], 'const_name')
161    self.assertEqual(tpm_obj.error_code, 'return_name')
162    tpm_obj = types['TPMI_DH_OBJECT']
163    self.assertEqual(tpm_obj.old_type, 'base_type')
164    self.assertEqual(tpm_obj.new_type, 'TPMI_DH_OBJECT')
165    self.assertEqual(tpm_obj.bounds[0][0], 'min_name')
166    self.assertEqual(tpm_obj.bounds[0][1], 'max_name')
167    self.assertEqual(tpm_obj.valid_values[0], 'const_name')
168    self.assertEqual(tpm_obj.conditional_value, 'null_name')
169    self.assertEqual(tpm_obj.error_code, 'return_name')
170    tpm_obj = types['struct_type']
171    self.assertEqual(tpm_obj.name, 'struct_type')
172    self.assertEqual(tpm_obj.fields[0].field_type, 'UINT16')
173    self.assertEqual(tpm_obj.fields[0].field_name, 'field1')
174    self.assertEqual(tpm_obj.fields[1].field_type, 'UINT16')
175    self.assertEqual(tpm_obj.fields[1].field_name, 'field2')
176    self.assertEqual(tpm_obj.fields[2].field_type, 'UINT16')
177    self.assertEqual(tpm_obj.fields[2].field_name, 'field3')
178    self.assertEqual(tpm_obj.fields[2].run_time_size, 'field1')
179    self.assertEqual(tpm_obj.fields[3].field_type, 'UINT16')
180    self.assertEqual(tpm_obj.fields[3].field_name, 'field4')
181    self.assertEqual(tpm_obj.fields[3].selector_value, 'field2')
182    self.assertEqual(tpm_obj.fields[4].field_type, 'interface_type')
183    self.assertEqual(tpm_obj.fields[4].field_name, 'field5')
184    self.assertEqual(tpm_obj.upper_bounds['field1'], 'max')
185    self.assertEqual(tpm_obj.lower_bounds['field1'], 'min')
186    tpm_obj = types['union_type']
187    self.assertEqual(tpm_obj.name, 'union_type')
188    self.assertEqual(tpm_obj.fields[0].field_type, 'field1_type')
189    self.assertEqual(tpm_obj.fields[0].field_name, 'field1')
190    self.assertEqual(tpm_obj.fields[1].field_type, 'field2_type')
191    self.assertEqual(tpm_obj.fields[1].field_name, 'field2')
192
193if __name__ == '__main__':
194  unittest.main()
195