1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import sys
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import traceback
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport module as mojom
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Support for writing mojom test cases.
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# RunTest(fn) will execute fn, catching any exceptions. fn should return
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# the number of errors that are encountered.
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# EXPECT_EQ(a, b) and EXPECT_TRUE(b) will print error information if the
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# expectations are not true and return a non zero value. This allows test cases
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# to be written like this
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# def Foo():
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#   errors = 0
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#   errors += EXPECT_EQ('test', test())
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#   ...
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#   return errors
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# RunTest(foo)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def FieldsAreEqual(field1, field2):
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if field1 == field2:
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return field1.name == field2.name and \
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      KindsAreEqual(field1.kind, field2.kind) and \
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      field1.ordinal == field2.ordinal and \
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      field1.default == field2.default
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def KindsAreEqual(kind1, kind2):
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if kind1 == kind2:
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if kind1.__class__ != kind2.__class__ or kind1.spec != kind2.spec:
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return False
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if kind1.__class__ == mojom.Kind:
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return kind1.spec == kind2.spec
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if kind1.__class__ == mojom.Struct:
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if kind1.name != kind2.name or \
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        kind1.spec != kind2.spec or \
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        len(kind1.fields) != len(kind2.fields):
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return False
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for i in range(len(kind1.fields)):
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if not FieldsAreEqual(kind1.fields[i], kind2.fields[i]):
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return False
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if kind1.__class__ == mojom.Array:
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return KindsAreEqual(kind1.kind, kind2.kind)
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  print 'Unknown Kind class: ', kind1.__class__.__name__
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return False
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def ParametersAreEqual(parameter1, parameter2):
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if parameter1 == parameter2:
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return parameter1.name == parameter2.name and \
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)     parameter1.ordinal == parameter2.ordinal and \
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)     parameter1.default == parameter2.default and \
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)     KindsAreEqual(parameter1.kind, parameter2.kind)
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def MethodsAreEqual(method1, method2):
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if method1 == method2:
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if method1.name != method2.name or \
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      method1.ordinal != method2.ordinal or \
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      len(method1.parameters) != len(method2.parameters):
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return False
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for i in range(len(method1.parameters)):
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if not ParametersAreEqual(method1.parameters[i], method2.parameters[i]):
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return False
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return True
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def InterfacesAreEqual(interface1, interface2):
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if interface1 == interface2:
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if interface1.name != interface2.name or \
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      len(interface1.methods) != len(interface2.methods):
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return False
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for i in range(len(interface1.methods)):
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if not MethodsAreEqual(interface1.methods[i], interface2.methods[i]):
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return False
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return True
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def ModulesAreEqual(module1, module2):
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if module1 == module2:
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return True
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if module1.name != module2.name or \
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      module1.namespace != module2.namespace or \
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      len(module1.structs) != len(module2.structs) or \
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      len(module1.interfaces) != len(module2.interfaces):
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return False
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for i in range(len(module1.structs)):
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if not KindsAreEqual(module1.structs[i], module2.structs[i]):
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return False
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for i in range(len(module1.interfaces)):
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if not InterfacesAreEqual(module1.interfaces[i], module2.interfaces[i]):
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return False
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return True
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Builds and returns a Module suitable for testing/
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def BuildTestModule():
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  module = mojom.Module('test', 'testspace')
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  struct = module.AddStruct('teststruct')
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  struct.AddField('testfield1', mojom.INT32)
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  struct.AddField('testfield2', mojom.Array(mojom.INT32), 42)
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  interface = module.AddInterface('Server')
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  method = interface.AddMethod('Foo', 42)
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  method.AddParameter('foo', mojom.INT32)
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  method.AddParameter('bar', mojom.Array(struct))
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return module
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Tests if |module| is as built by BuildTestModule(). Returns the number of
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# errors
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def TestTestModule(module):
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors = 0
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('test', module.name)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('testspace', module.namespace)
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(1, len(module.structs))
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('teststruct', module.structs[0].name)
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(2, len(module.structs[0].fields))
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('testfield1', module.structs[0].fields[0].name)
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(mojom.INT32, module.structs[0].fields[0].kind)
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('testfield2', module.structs[0].fields[1].name)
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(mojom.Array, module.structs[0].fields[1].kind.__class__)
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(mojom.INT32, module.structs[0].fields[1].kind.kind)
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(1, len(module.interfaces))
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('Server', module.interfaces[0].name)
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(1, len(module.interfaces[0].methods))
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('Foo', module.interfaces[0].methods[0].name)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(2, len(module.interfaces[0].methods[0].parameters))
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('foo', module.interfaces[0].methods[0].parameters[0].name)
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(mojom.INT32,
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      module.interfaces[0].methods[0].parameters[0].kind)
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ('bar', module.interfaces[0].methods[0].parameters[1].name)
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mojom.Array,
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    module.interfaces[0].methods[0].parameters[1].kind.__class__)
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  errors += EXPECT_EQ(
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    module.structs[0],
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    module.interfaces[0].methods[0].parameters[1].kind.kind)
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return errors
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def PrintFailure(string):
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  stack = traceback.extract_stack()
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  frame = stack[len(stack)-3]
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sys.stderr.write("ERROR at %s:%d, %s\n" % (frame[0], frame[1], string))
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  print "Traceback:"
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for line in traceback.format_list(stack[:len(stack)-2]):
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    sys.stderr.write(line)
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def EXPECT_EQ(a, b):
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if a != b:
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    PrintFailure("%s != %s" % (a, b))
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return 1
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def EXPECT_TRUE(a):
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if not a:
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    PrintFailure('Expecting True')
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return 1
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def RunTest(fn):
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sys.stdout.write('Running %s...' % fn.__name__)
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  try:
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errors = fn()
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  except:
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    traceback.print_exc(sys.stderr)
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errors = 1
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if errors == 0:
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    sys.stdout.write('OK\n')
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  elif errors == 1:
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    sys.stdout.write('1 ERROR\n')
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else:
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    sys.stdout.write('%d ERRORS\n' % errors)
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return errors
194