Home | History | Annotate | Download | only in generators
      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