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