Commit 0c7a8ec9 authored by dglazkov's avatar dglazkov Committed by Commit bot

Add first bindings unit test and enable testing.

Also:
* Quick refactor of jinja2 context creation into a builder.
* Switched Attribute/Method to dicts.
* Added a bit more meat more to header template.
* Added nicer parameter handling to run-bindings-tests
* Added stub helper for unit tests.

BUG=654129
R=bashi,yukishiino,haraken

Review-Url: https://codereview.chromium.org/2568693002
Cr-Commit-Position: refs/heads/master@{#437989}
parent b46a672f
......@@ -38,46 +38,62 @@ def includes_for_type(idl_type):
def interface_context(idl_interface):
attributes = []
methods = []
includes = set()
builder = InterfaceContextBuilder(MODULE_PYNAME)
builder.set_class_name(idl_interface.name)
for idl_attribute in idl_interface.attributes:
attributes.append(Attribute.create(idl_attribute))
includes.update(includes_for_type(idl_attribute.idl_type))
builder.add_attribute(idl_attribute)
for idl_operation in idl_interface.operations:
if idl_operation.name:
methods.append(Method.create(idl_operation))
return {
'code_generator': MODULE_PYNAME,
'class_name': idl_interface.name,
'cpp_includes': includes,
'attributes': attributes,
'methods': methods,
}
class Attribute(object):
def __init__(self, name, return_type):
self.name = name
self.return_type = return_type
@staticmethod
def create(idl_attribute):
name = idl_attribute.name
return_type = idl_attribute.idl_type.preprocessed_type.base_type
return Attribute(name, return_type)
builder.add_operation(idl_operation)
return builder.build()
class InterfaceContextBuilder(object):
def __init__(self, code_generator):
self.result = {'code_generator': code_generator}
def set_class_name(self, class_name):
self.result['class_name'] = class_name
class Method(object):
def __init__(self, name, return_type):
self.name = name
self.return_type = return_type
def _ensure_set(self, name):
return self.result.setdefault(name, set())
@staticmethod
def create(idl_operation):
def _ensure_list(self, name):
return self.result.setdefault(name, [])
def add_attribute(self, idl_attribute):
self._ensure_list('attributes').append(
self.create_attribute(idl_attribute))
self._ensure_set('cpp_includes').update(
includes_for_type(idl_attribute.idl_type))
def add_operation(self, idl_operation):
if idl_operation.name:
self._ensure_list('methods').append(
self.create_method(idl_operation))
self._ensure_set('cpp_includes').update(
includes_for_type(idl_operation.idl_type))
def create_method(self, idl_operation):
name = idl_operation.name
return_type = idl_operation.idl_type.preprocessed_type.base_type
return Method(name, return_type)
return {
'name': name,
'return_type': return_type
}
def create_attribute(self, idl_attribute):
name = idl_attribute.name
return_type = idl_attribute.idl_type.preprocessed_type.base_type
return {
'name': name,
'return_type': return_type
}
def build(self):
return self.result
class CodeGeneratorWebModule(CodeGeneratorBase):
......@@ -102,7 +118,7 @@ class CodeGeneratorWebModule(CodeGeneratorBase):
# TODO(dglazkov): Implement callback interfaces.
# TODO(dglazkov): Make sure partial interfaces are handled.
if interface.is_callback or interface.is_partial:
raise ValueError("Partial or callback interfaces are not supported")
raise ValueError('Partial or callback interfaces are not supported')
template_context = interface_context(interface)
......
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# pylint: disable=import-error,print-statement,relative-import
"""Unit tests for code_generator_web_module.py."""
import unittest
from code_generator_web_module import InterfaceContextBuilder
class IdlTestingHelper(object):
"""A collection of stub makers and helper utils to make testing code
generation easy."""
def make_stub_object(self):
return type('', (), {})()
def add_idl_type_to_stub(self, stub, return_type):
stub.idl_type = self.make_stub_object()
stub.idl_type.preprocessed_type = self.make_stub_object()
stub.idl_type.preprocessed_type.base_type = return_type
def make_stub_idl_attribute(self, name, return_type):
idl_attribute_stub = self.make_stub_object()
idl_attribute_stub.name = name
self.add_idl_type_to_stub(idl_attribute_stub, return_type)
return idl_attribute_stub
def make_stub_idl_operation(self, name, return_type):
idl_operation_stub = self.make_stub_object()
idl_operation_stub.name = name
self.add_idl_type_to_stub(idl_operation_stub, return_type)
return idl_operation_stub
class InterfaceContextBuilderTest(unittest.TestCase):
def test_empty(self):
builder = InterfaceContextBuilder('test')
self.assertEqual({'code_generator': 'test'}, builder.build())
def test_set_name(self):
builder = InterfaceContextBuilder('test')
builder.set_class_name('foo')
self.assertEqual({
'code_generator': 'test',
'class_name': 'foo',
}, builder.build())
def test_add_attribute(self):
helper = IdlTestingHelper()
builder = InterfaceContextBuilder('test')
attribute = helper.make_stub_idl_attribute('foo', 'bar')
builder.add_attribute(attribute)
self.assertEqual({
'code_generator': 'test',
'cpp_includes': set(['bar']),
'attributes': [{'name': 'foo', 'return_type': 'bar'}],
}, builder.build())
def test_add_method(self):
helper = IdlTestingHelper()
builder = InterfaceContextBuilder('test')
operation = helper.make_stub_idl_operation('foo', 'bar')
builder.add_operation(operation)
self.assertEqual({
'code_generator': 'test',
'cpp_includes': set(['bar']),
'methods': [{'name': 'foo', 'return_type': 'bar'}],
}, builder.build())
......@@ -2,6 +2,24 @@
{% include 'copyright_block.txt' %}
// TODO(dglazkov): Implement generating the header file.
// TODO(dglazkov): Use chromium-style path.
#ifndef {{class_name}}_h
#define {{class_name}}_h
{% endfilter %}
\ No newline at end of file
{% for include_file in header_includes %}
#include "{{include_file}}"
{% endfor %}
namespace blink {
namespace api {
class {{class_name}} {
};
} // namespace api
} // namespace blink
#endif // {{class_name}}_h
{% endfilter %}
......@@ -10,6 +10,8 @@
#include "WebTestInterface3.h"
// TODO(dglazkov): Implement generating includes.
#include "Webvoid.h"
#include "WebIterator.h"
#include "WebDOMString.h"
namespace blink {
......
......@@ -7,4 +7,17 @@
// clang-format off
// TODO(dglazkov): Implement generating the header file.
// TODO(dglazkov): Use chromium-style path.
#ifndef TestInterface3_h
#define TestInterface3_h
namespace blink {
namespace api {
class TestInterface3 {
};
} // namespace api
} // namespace blink
#endif // TestInterface3_h
......@@ -26,7 +26,10 @@
import sys
from webkitpy.bindings.bindings_tests import run_bindings_tests
from webkitpy.common import webkit_finder
webkit_finder.add_typ_dir_to_sys_path()
import typ
def main(argv):
"""Runs Blink bindings IDL compiler on test IDL files and compares the
......@@ -36,15 +39,38 @@ def main(argv):
(this is automatically done as a presubmit script),
and submit changes to the test results in the same patch.
This makes it easier to track and review changes in generated code.
Options:
--reset-results: Overwrites reference files with the generated results.
--verbose: Show output on success and logging messages (not just failure)
"""
reset_results = '--reset-results' in argv
verbose = '--verbose' in argv
argument_parser = typ.ArgumentParser()
argument_parser.add_argument('--reset-results',
default=False,
action='store_true',
help='Overwrites reference files with the generated results.')
argument_parser.add_argument('--skip-unit-tests',
default=False,
action='store_true',
help='Skip running unit tests (only run reference tests).')
argument_parser.add_argument('--skip-reference-tests',
default=False,
action='store_true',
help='Skip running reference tests (only run unit tests).')
# First, run bindings unit tests.
runner = typ.Runner()
runner.parse_args(argument_parser, argv[1:])
args = runner.args
if argument_parser.exit_status is not None:
return argument_parser.exit_status
runner.args.top_level_dir = webkit_finder.get_bindings_scripts_dir()
if not args.skip_unit_tests:
return_code, _, _ = runner.run()
if return_code != 0:
return return_code
if args.skip_reference_tests:
return 0
return run_bindings_tests(reset_results, verbose)
# Now run the bindings end-to-end tests.
return run_bindings_tests(args.reset_results, args.verbose)
if __name__ == '__main__':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment