#!/usr/bin/env python import textwrap import unittest from stone.frontend.frontend import specs_to_ir class TestStone(unittest.TestCase): def _compare_namespace_names(self, api, expected_names): expected_names = sorted(expected_names) actual_names = sorted(list(api.namespaces.keys())) self.assertEqual(expected_names, actual_names) def _compare_datatype_names(self, namespace, expected_names): expected_names = sorted(expected_names) actual_names = sorted(list(namespace.data_type_by_name.keys())) self.assertEqual(expected_names, actual_names) actual_names_on_datatypes = sorted([d.name for d in namespace.data_type_by_name.values()]) self.assertEqual(actual_names, actual_names_on_datatypes) def test_simple(self): """ Tests that route whitelisting can generate the right datatypes for a namespace. """ text = textwrap.dedent("""\ namespace test struct TestArg f String "test doc" example default f = "asdf" struct TestResult f String "test doc" example default f = "asdf" route TestRoute (TestArg, TestResult, Void) "test doc" struct TestArg2 f String "test doc" example default f = "asdf" struct TestResult2 f String "test doc" example default f = "asdf" route TestRoute:2 (TestArg2, TestResult2, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test": ["TestRoute:2"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test']) self._compare_datatype_names(api.namespaces['test'], ['TestArg2', 'TestResult2']) def test_stable_ordering(self): """ Tests that route generation returns the same route order on generation. """ text = textwrap.dedent("""\ namespace test struct TestArg f String "test doc" example default f = "asdf" struct TestResult f String "test doc" example default f = "asdf" route TestRoute (TestArg, TestResult, Void) "test doc" route OtherRoute (Void, Void, Void) "Additional Route" """) route_whitelist = ["OtherRoute", "TestRoute"] for x in range(2, 100): text += textwrap.dedent("""\ route TestRoute:{} (TestArg, TestResult, Void) "test doc" """.format(x)) route_whitelist.append("TestRoute:{}".format(x)) route_whitelist_filter = { "route_whitelist": {"test": route_whitelist}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) routes = api.namespaces['test'].routes self.assertEqual(len(routes), 100) self.assertEqual(routes[0].name, "OtherRoute") for x in range(1, 100): self.assertEqual(routes[x].name, "TestRoute") self.assertEqual(routes[x].version, x) def test_star(self): """ Tests that inputs with "*" work as expected. """ text = textwrap.dedent("""\ namespace test struct TestArg f String "test doc" example default f = "asdf" struct TestResult f String "test doc" example default f = "asdf" route TestRoute (TestArg, TestResult, Void) "test doc" struct TestArg2 f String "test doc" example default f = "asdf" struct TestResult2 f String "test doc" example default f = "asdf" route TestRoute:2 (TestArg2, TestResult2, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test": ["*"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test']) self._compare_datatype_names(api.namespaces['test'], ['TestArg', 'TestArg2', 'TestResult', 'TestResult2']) def test_alias(self): """ Tests that aliased datatypes are correctly generated. """ text = textwrap.dedent("""\ namespace test struct TestArg f String "test doc" example default f = "asdf" struct TestResult f String "test doc" example default f = "asdf" alias TestAlias = TestArg route TestRoute (TestAlias, TestResult, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test": ["TestRoute"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test']) self._compare_datatype_names(api.namespaces['test'], ['TestArg', 'TestResult']) def test_imports(self): """ Tests that datatypes imported from another namespace are correctly included. """ text = textwrap.dedent("""\ namespace test struct TestArg f String "test doc" example default f = "asdf" struct TestResult f String "test doc" example default f = "asdf" """) text2 = textwrap.dedent("""\ namespace test2 import test route TestRoute (test.TestArg, test.TestResult, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test2": ["TestRoute"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text), ('test2.stone', text2)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test', 'test2']) self._compare_datatype_names(api.namespaces['test'], ['TestArg', 'TestResult']) self._compare_datatype_names(api.namespaces['test2'], []) def test_builtin_types(self): """ Tests that builtin datatypes, like lists, maps, and unions, are correctly evaluated. """ text = textwrap.dedent("""\ namespace test union Foo a "test doc" example default a = null union Bar a "test doc" example default a = null struct TestArg f String "test doc" example default f = "asdf" struct TestResult f List(Foo) "test doc" b Map(String, Bar) "test doc" example default f = [default] b = {"test": default} route TestRoute (TestArg, TestResult, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test": ["TestRoute"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test']) self._compare_datatype_names(api.namespaces['test'], ['TestArg', 'TestResult', 'Foo', 'Bar']) def test_subtype(self): """ Tests that datatypes that inherit from others are correctly generated. """ text = textwrap.dedent("""\ namespace test union Foo a "test doc" example default a = null union Bar extends Foo b "test doc" example default a = null struct TestArg f String "test doc" example default f = "asdf" struct TestResult f Bar "test doc" example default f = default route TestRoute (TestArg, TestResult, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test": ["TestRoute"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test']) self._compare_datatype_names(api.namespaces['test'], ['TestArg', 'TestResult', 'Foo', 'Bar']) # Test enumerated subtypes as well text = textwrap.dedent("""\ namespace test struct Foo union file File folder Folder path String "test doc" example default file = default example folder_default folder = default struct File extends Foo a String "test doc" example default a = "a" path = "a" struct Folder extends Foo b String "test doc" example default b = "b" path = "a" struct TestArg f Foo "test doc" example default f = default struct TestResult f String "test doc" example default f = "asdf" route TestRoute (TestArg, TestResult, Void) "test doc" """) route_whitelist_filter = { "route_whitelist": {"test": ["TestRoute"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test']) self._compare_datatype_names(api.namespaces['test'], ['TestArg', 'TestResult', 'Foo', 'File', 'Folder']) def test_doc_refs(self): """ Tests that datatypes referenced in documentation get generated. """ text = textwrap.dedent("""\ namespace test union Foo a "test doc" example default a = null union Bar a "test doc" example default a = null """) text2 = textwrap.dedent("""\ namespace test2 ":type:`test.Foo`" alias TestAlias = String ":field:`Baz.a`" struct TestStruct a TestAlias "test doc" example default a = "asdf" struct Baz a String "test doc :field:`TestStruct.a`" example default a = "asdf" struct TestArg f String "test doc" example default f = "asdf" struct TestResult f String "test doc" example default f = "asdf" route TestRoute (TestArg, TestResult, Void) ":type:`Baz` test doc" """) route_whitelist_filter = { "route_whitelist": {"test2": ["TestRoute"]}, "datatype_whitelist": {} } api = specs_to_ir([('test.stone', text), ('test2.stone', text2)], route_whitelist_filter=route_whitelist_filter) self._compare_namespace_names(api, ['test', 'test2']) self._compare_datatype_names(api.namespaces['test'], ['Foo']) self._compare_datatype_names(api.namespaces['test2'], ['TestArg', 'TestResult', 'TestStruct', 'Baz']) if __name__ == '__main__': unittest.main()