mirror of https://github.com/mongodb/mongo
444 lines
12 KiB
Python
444 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (C) 2018-present MongoDB, Inc.
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the Server Side Public License, version 1,
|
|
# as published by MongoDB, Inc.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# Server Side Public License for more details.
|
|
#
|
|
# You should have received a copy of the Server Side Public License
|
|
# along with this program. If not, see
|
|
# <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
#
|
|
# As a special exception, the copyright holders give permission to link the
|
|
# code of portions of this program with the OpenSSL library under certain
|
|
# conditions as described in each individual source file and distribute
|
|
# linked combinations including the program with the OpenSSL library. You
|
|
# must comply with the Server Side Public License in all respects for
|
|
# all of the code used other than as permitted herein. If you modify file(s)
|
|
# with this exception, you may extend this exception to your version of the
|
|
# file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
# delete this exception statement from your version. If you delete this
|
|
# exception statement from all source files in the program, then also delete
|
|
# it in the license file.
|
|
#
|
|
"""Test cases for IDL binder."""
|
|
|
|
import io
|
|
import textwrap
|
|
import unittest
|
|
|
|
# import package so that it works regardless of whether we run as a module or file
|
|
if __package__ is None:
|
|
import sys
|
|
from os import path
|
|
|
|
sys.path.append(path.dirname(path.abspath(__file__)))
|
|
import testcase
|
|
from context import idl
|
|
else:
|
|
from . import testcase
|
|
from .context import idl
|
|
|
|
|
|
class DictionaryImportResolver(idl.parser.ImportResolverBase):
|
|
"""An import resolver resolves files from a dictionary."""
|
|
|
|
def __init__(self, import_dict):
|
|
# type: (Dict[str, str]) -> None
|
|
"""Construct a DictionaryImportResolver."""
|
|
self._import_dict = import_dict
|
|
super(DictionaryImportResolver, self).__init__()
|
|
|
|
def resolve(self, base_file, imported_file_name):
|
|
# type: (str, str) -> str
|
|
"""Return the complete path to an imported file name."""
|
|
if imported_file_name not in self._import_dict:
|
|
return None
|
|
|
|
return "imported_%s" % (imported_file_name)
|
|
|
|
def open(self, resolved_file_name):
|
|
# type: (str) -> Any
|
|
"""Return an io.Stream for the requested file."""
|
|
assert resolved_file_name.startswith("imported_")
|
|
imported_file_name = resolved_file_name.replace("imported_", "")
|
|
|
|
return io.StringIO(self._import_dict[imported_file_name])
|
|
|
|
|
|
class TestImport(testcase.IDLTestcase):
|
|
"""Test cases for the IDL binder."""
|
|
|
|
# Test: import wrong types
|
|
def test_import_negative_parser(self):
|
|
# type: () -> None
|
|
"""Negative import parser tests."""
|
|
|
|
self.assert_parse_fail(
|
|
textwrap.dedent("""
|
|
imports:
|
|
- "a.idl"
|
|
|
|
imports:
|
|
- "b.idl"
|
|
"""),
|
|
idl.errors.ERROR_ID_DUPLICATE_NODE,
|
|
)
|
|
|
|
self.assert_parse_fail(
|
|
textwrap.dedent("""
|
|
imports: "basetypes.idl"
|
|
"""),
|
|
idl.errors.ERROR_ID_IS_NODE_TYPE,
|
|
)
|
|
|
|
self.assert_parse_fail(
|
|
textwrap.dedent("""
|
|
imports:
|
|
a: "a.idl"
|
|
b: "b.idl"
|
|
"""),
|
|
idl.errors.ERROR_ID_IS_NODE_TYPE,
|
|
)
|
|
|
|
def test_import_positive(self):
|
|
# type: () -> None
|
|
"""Postive import tests."""
|
|
|
|
import_dict = {
|
|
"basetypes.idl": textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
types:
|
|
string:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: string
|
|
serializer: foo
|
|
deserializer: foo
|
|
default: foo
|
|
is_view: false
|
|
serialization_context:
|
|
bson_serialization_type: any
|
|
description: foo
|
|
cpp_type: foo
|
|
internal_only: true
|
|
is_view: false
|
|
|
|
structs:
|
|
bar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
"""),
|
|
"recurse1.idl": textwrap.dedent("""
|
|
imports:
|
|
- "basetypes.idl"
|
|
|
|
types:
|
|
int:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: int
|
|
deserializer: BSONElement::fake
|
|
is_view: false
|
|
|
|
"""),
|
|
"recurse2.idl": textwrap.dedent("""
|
|
imports:
|
|
- "recurse1.idl"
|
|
|
|
types:
|
|
double:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: double
|
|
deserializer: BSONElement::fake
|
|
is_view: false
|
|
|
|
"""),
|
|
"recurse1b.idl": textwrap.dedent("""
|
|
imports:
|
|
- "basetypes.idl"
|
|
|
|
types:
|
|
bool:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: bool
|
|
deserializer: BSONElement::fake
|
|
is_view: false
|
|
"""),
|
|
"cycle1a.idl": textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "cycle1b.idl"
|
|
|
|
types:
|
|
string:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: string
|
|
serializer: foo
|
|
deserializer: foo
|
|
default: foo
|
|
is_view: false
|
|
serialization_context:
|
|
bson_serialization_type: any
|
|
description: foo
|
|
cpp_type: foo
|
|
internal_only: true
|
|
is_view: false
|
|
|
|
structs:
|
|
bar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
foo1: bool
|
|
"""),
|
|
"cycle1b.idl": textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "cycle1a.idl"
|
|
|
|
types:
|
|
bool:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: bool
|
|
deserializer: BSONElement::fake
|
|
is_view: false
|
|
|
|
structs:
|
|
bar2:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
foo1: bool
|
|
"""),
|
|
"cycle2.idl": textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "cycle2.idl"
|
|
|
|
types:
|
|
string:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: string
|
|
serializer: foo
|
|
deserializer: foo
|
|
default: foo
|
|
is_view: false
|
|
serialization_context:
|
|
bson_serialization_type: any
|
|
description: foo
|
|
cpp_type: foo
|
|
internal_only: true
|
|
is_view: false
|
|
"""),
|
|
}
|
|
|
|
resolver = DictionaryImportResolver(import_dict)
|
|
|
|
# Test simple import
|
|
self.assert_bind(
|
|
textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "basetypes.idl"
|
|
|
|
structs:
|
|
foobar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
"""),
|
|
resolver=resolver,
|
|
)
|
|
|
|
# Test nested import
|
|
self.assert_bind(
|
|
textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "recurse2.idl"
|
|
|
|
structs:
|
|
foobar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
foo1: int
|
|
foo2: double
|
|
"""),
|
|
resolver=resolver,
|
|
)
|
|
|
|
# Test diamond import
|
|
self.assert_bind(
|
|
textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "recurse2.idl"
|
|
- "recurse1b.idl"
|
|
|
|
structs:
|
|
foobar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
foo1: int
|
|
foo2: double
|
|
foo3: bool
|
|
"""),
|
|
resolver=resolver,
|
|
)
|
|
|
|
# Test cycle import
|
|
self.assert_bind(
|
|
textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "cycle1a.idl"
|
|
|
|
structs:
|
|
foobar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
foo1: bool
|
|
"""),
|
|
resolver=resolver,
|
|
)
|
|
|
|
# Test self cycle import
|
|
self.assert_bind(
|
|
textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
imports:
|
|
- "cycle2.idl"
|
|
|
|
structs:
|
|
foobar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
"""),
|
|
resolver=resolver,
|
|
)
|
|
|
|
def test_import_negative(self):
|
|
# type: () -> None
|
|
"""Negative import tests."""
|
|
|
|
import_dict = {
|
|
"basetypes.idl": textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
types:
|
|
string:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: string
|
|
serializer: foo
|
|
deserializer: foo
|
|
default: foo
|
|
is_view: false
|
|
|
|
structs:
|
|
bar:
|
|
description: foo
|
|
strict: false
|
|
fields:
|
|
foo: string
|
|
|
|
enums:
|
|
IntEnum:
|
|
description: "An example int enum"
|
|
type: int
|
|
values:
|
|
a0: 0
|
|
b1: 1
|
|
|
|
"""),
|
|
"bug.idl": textwrap.dedent("""
|
|
global:
|
|
cpp_namespace: 'mongo'
|
|
|
|
types:
|
|
bool:
|
|
description: foo
|
|
bson_serialization_type: bool
|
|
deserializer: BSONElement::fake
|
|
is_view: false
|
|
"""),
|
|
}
|
|
|
|
resolver = DictionaryImportResolver(import_dict)
|
|
|
|
# Bad import
|
|
self.assert_parse_fail(
|
|
textwrap.dedent("""
|
|
imports:
|
|
- "notfound.idl"
|
|
"""),
|
|
idl.errors.ERROR_ID_BAD_IMPORT,
|
|
resolver=resolver,
|
|
)
|
|
|
|
# Import a file with errors
|
|
self.assert_parse_fail(
|
|
textwrap.dedent("""
|
|
imports:
|
|
- "basetypes.idl"
|
|
- "bug.idl"
|
|
|
|
types:
|
|
string2:
|
|
description: foo
|
|
cpp_type: foo
|
|
bson_serialization_type: string
|
|
is_view: false
|
|
"""),
|
|
idl.errors.ERROR_ID_MISSING_REQUIRED_FIELD,
|
|
resolver=resolver,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|