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 5 import mojom 6 import sys 7 import traceback 8 9 # Support for writing mojom test cases. 10 # RunTest(fn) will execute fn, catching any exceptions. fn should return 11 # the number of errors that are encountered. 12 # 13 # EXPECT_EQ(a, b) and EXPECT_TRUE(b) will print error information if the 14 # expectations are not true and return a non zero value. This allows test cases 15 # to be written like this 16 # 17 # def Foo(): 18 # errors = 0 19 # errors += EXPECT_EQ('test', test()) 20 # ... 21 # return errors 22 # 23 # RunTest(foo) 24 25 def FieldsAreEqual(field1, field2): 26 if field1 == field2: 27 return True 28 return field1.name == field2.name and \ 29 KindsAreEqual(field1.kind, field2.kind) and \ 30 field1.ordinal == field2.ordinal and \ 31 field1.default == field2.default 32 33 34 def KindsAreEqual(kind1, kind2): 35 if kind1 == kind2: 36 return True 37 if kind1.__class__ != kind2.__class__ or kind1.spec != kind2.spec: 38 return False 39 if kind1.__class__ == mojom.Kind: 40 return kind1.spec == kind2.spec 41 if kind1.__class__ == mojom.Struct: 42 if kind1.name != kind2.name or \ 43 kind1.spec != kind2.spec or \ 44 len(kind1.fields) != len(kind2.fields): 45 return False 46 for i in range(len(kind1.fields)): 47 if not FieldsAreEqual(kind1.fields[i], kind2.fields[i]): 48 return False 49 return True 50 if kind1.__class__ == mojom.Array: 51 return KindsAreEqual(kind1.kind, kind2.kind) 52 print 'Unknown Kind class: ', kind1.__class__.__name__ 53 return False 54 55 56 def ParametersAreEqual(parameter1, parameter2): 57 if parameter1 == parameter2: 58 return True 59 return parameter1.name == parameter2.name and \ 60 parameter1.ordinal == parameter2.ordinal and \ 61 parameter1.default == parameter2.default and \ 62 KindsAreEqual(parameter1.kind, parameter2.kind) 63 64 65 def MethodsAreEqual(method1, method2): 66 if method1 == method2: 67 return True 68 if method1.name != method2.name or \ 69 method1.ordinal != method2.ordinal or \ 70 len(method1.parameters) != len(method2.parameters): 71 return False 72 for i in range(len(method1.parameters)): 73 if not ParametersAreEqual(method1.parameters[i], method2.parameters[i]): 74 return False 75 return True 76 77 78 def InterfacesAreEqual(interface1, interface2): 79 if interface1 == interface2: 80 return True 81 if interface1.name != interface2.name or \ 82 len(interface1.methods) != len(interface2.methods): 83 return False 84 for i in range(len(interface1.methods)): 85 if not MethodsAreEqual(interface1.methods[i], interface2.methods[i]): 86 return False 87 return True 88 89 90 def ModulesAreEqual(module1, module2): 91 if module1 == module2: 92 return True 93 if module1.name != module2.name or \ 94 module1.namespace != module2.namespace or \ 95 len(module1.structs) != len(module2.structs) or \ 96 len(module1.interfaces) != len(module2.interfaces): 97 return False 98 for i in range(len(module1.structs)): 99 if not KindsAreEqual(module1.structs[i], module2.structs[i]): 100 return False 101 for i in range(len(module1.interfaces)): 102 if not InterfacesAreEqual(module1.interfaces[i], module2.interfaces[i]): 103 return False 104 return True 105 106 107 # Builds and returns a Module suitable for testing/ 108 def BuildTestModule(): 109 module = mojom.Module('test', 'testspace') 110 struct = module.AddStruct('teststruct') 111 struct.AddField('testfield1', mojom.INT32) 112 struct.AddField('testfield2', mojom.Array(mojom.INT32), 42) 113 114 interface = module.AddInterface('Server') 115 method = interface.AddMethod('Foo', 42) 116 method.AddParameter('foo', mojom.INT32) 117 method.AddParameter('bar', mojom.Array(struct)) 118 119 return module 120 121 122 # Tests if |module| is as built by BuildTestModule(). Returns the number of 123 # errors 124 def TestTestModule(module): 125 errors = 0 126 127 errors += EXPECT_EQ('test', module.name) 128 errors += EXPECT_EQ('testspace', module.namespace) 129 errors += EXPECT_EQ(1, len(module.structs)) 130 errors += EXPECT_EQ('teststruct', module.structs[0].name) 131 errors += EXPECT_EQ(2, len(module.structs[0].fields)) 132 errors += EXPECT_EQ('testfield1', module.structs[0].fields[0].name) 133 errors += EXPECT_EQ(mojom.INT32, module.structs[0].fields[0].kind) 134 errors += EXPECT_EQ('testfield2', module.structs[0].fields[1].name) 135 errors += EXPECT_EQ(mojom.Array, module.structs[0].fields[1].kind.__class__) 136 errors += EXPECT_EQ(mojom.INT32, module.structs[0].fields[1].kind.kind) 137 138 errors += EXPECT_EQ(1, len(module.interfaces)) 139 errors += EXPECT_EQ('Server', module.interfaces[0].name) 140 errors += EXPECT_EQ(1, len(module.interfaces[0].methods)) 141 errors += EXPECT_EQ('Foo', module.interfaces[0].methods[0].name) 142 errors += EXPECT_EQ(2, len(module.interfaces[0].methods[0].parameters)) 143 errors += EXPECT_EQ('foo', module.interfaces[0].methods[0].parameters[0].name) 144 errors += EXPECT_EQ(mojom.INT32, 145 module.interfaces[0].methods[0].parameters[0].kind) 146 errors += EXPECT_EQ('bar', module.interfaces[0].methods[0].parameters[1].name) 147 errors += EXPECT_EQ( 148 mojom.Array, 149 module.interfaces[0].methods[0].parameters[1].kind.__class__) 150 errors += EXPECT_EQ( 151 module.structs[0], 152 module.interfaces[0].methods[0].parameters[1].kind.kind) 153 return errors 154 155 156 def PrintFailure(string): 157 stack = traceback.extract_stack() 158 frame = stack[len(stack)-3] 159 sys.stderr.write("ERROR at %s:%d, %s\n" % (frame[0], frame[1], string)) 160 print "Traceback:" 161 for line in traceback.format_list(stack[:len(stack)-2]): 162 sys.stderr.write(line) 163 164 165 def EXPECT_EQ(a, b): 166 if a != b: 167 PrintFailure("%s != %s" % (a, b)) 168 return 1 169 return 0 170 171 172 def EXPECT_TRUE(a): 173 if not a: 174 PrintFailure('Expecting True') 175 return 1 176 return 0 177 178 179 def RunTest(fn): 180 sys.stdout.write('Running %s...' % fn.__name__) 181 success = True; 182 try: 183 errors = fn() 184 except: 185 traceback.print_exc(sys.stderr) 186 errors = 1 187 if errors == 0: 188 sys.stdout.write('OK\n') 189 elif errors == 1: 190 sys.stdout.write('1 ERROR\n') 191 else: 192 sys.stdout.write('%d ERRORS\n' % errors) 193 return errors 194