def test_invalid_type_name(self): with self.assertRaises(ValueError) as ve: Dynabuffers.parse(""" class Test { someVariable: invalidtype } """) self.assertEqual( "The datatype(s) {'invalidtype'} used in the schema are neither built-in datatypes nor class, union or enum references.", str(ve.exception))
def test_valid_class_reference_to_same_namespace(self): Dynabuffers.parse(""" namespace One { class First { someVar: string } class Second { someVar: First } } """)
def test_invalid_type_names(self): with self.assertRaises(ValueError): Dynabuffers.parse(""" class Test { first: FirstInvalidType second: secondInvalidType } class OtherTest { third: thirdInvalidType fourth: FirstInvalidType } """)
def test_invalid_class_reference_to_different_namespace(self): with self.assertRaises(ValueError): Dynabuffers.parse(""" namespace One { class First { someVar: string } } namespace Two { class Second { someVar: First } } """)
def test_deprecated_class(self): engine = Dynabuffers.parse( InputStream("class Color(deprecated) { name:string }")) engine.add_listener(print) map = engine.deserialize(engine.serialize({"name": "red"})) self.assertEqual(map, {"name": "red"})
def test_schema_with_too_many_nested_namespaces(self): engine = Dynabuffers.parse( """ namespace abc{ namespace abc{ namespace abc{ namespace abc{ namespace abc{ namespace abc{ namespace abc{ namespace abc{ class Data { value: string } } } } } } } } } """) map = {"value": "hallo"} with self.assertRaises(ValueError) as ve: engine.serialize(map, ["abc", "abc", "abc", "abc", "abc", "abc", "abc", "abc"]) self.assertEqual("Value 8 of Namespace Depth is too large for field size of 3 bits.", str(ve.exception))
def test_schema_with_nested_namespaces_containing_clases_in_all_levels( self): engine = Dynabuffers.parse(""" namespace `leftshiftone/echo`{ class DataLevel0 { value0: string } namespace abc { class DataLevel1 { value1: int } namespace def { class DataLevel2 { value2: [string] } } } } """) map0 = {"value0": "someString"} map1 = {"value1": 3} map2 = {"value2": ["a", "b"]} result0 = engine.deserialize( engine.serialize(map0, ["`leftshiftone/echo`"]), ["`leftshiftone/echo`"]) self.assertEqual(map0, result0) result1 = engine.deserialize( engine.serialize(map1, ["`leftshiftone/echo`", "abc"]), ["`leftshiftone/echo`", "abc"]) self.assertEqual(map1, result1) result2 = engine.deserialize( engine.serialize(map2, ["`leftshiftone/echo`", "abc", "def"]), ["`leftshiftone/echo`", "abc", "def"]) self.assertEqual(map2, result2)
def test_parse(self): with open(self.root_dir + "/1.jpg", 'rb') as f: data = b"".join(f.readlines()) engine = Dynabuffers.parse(FileStream(self.root_dir + "/schema07.dbs")) map = engine.deserialize(engine.serialize({"image": data})) self.assertEqual(map, {"image": data})
def test_parse(self): engine = Dynabuffers.parse(FileStream(f"{self.root_dir}/schema03.dbs")) map = engine.deserialize( engine.serialize({"results": [{ "text": "hello world" }]})) self.assertEqual(map, {"results": [{"text": "hello world"}]})
def test_implicit_class(self): engine = Dynabuffers.parse(""" class Data(implicit) { value:[byte] } """) result = engine.deserialize(engine.serialize(bytearray(b"test"))) self.assertTrue("value" in result) self.assertTrue(isinstance(result, ImplicitDynabuffersMap)) self.assertEqual(result.get_value(), bytearray(b"test"))
def test_class_with_multiple_fields(self): engine = Dynabuffers.parse( InputStream("class Product { name:string price:float }")) encoded = base64.b64encode( engine.serialize({ "name": "TV", "price": 1000 })).decode("utf-8") self.assertEqual(encoded, "AAJUVkR6AAA=")
def test_parse_class_with_multiple_fields(self): engine = Dynabuffers.parse( InputStream("class Product { name:string price:float }")) map = engine.deserialize( engine.serialize({ "name": "TV", "price": 1000 })) self.assertEqual(map, {"name": "TV", "price": 1000})
def test_schema_with_namespace(self): engine = Dynabuffers.parse(""" namespace abc{ class Data { value: string } } """) map = {"value": "hallo"} result = engine.deserialize(engine.serialize(map, "abc"), "abc") self.assertEqual(map, result)
def test_default_empty_namespaces_will_raise_an_exception(self): engine = Dynabuffers.parse(""" namespace abc{ namespace xyz {} class Data { value: string } } """) self.assertRaises(ValueError, lambda: engine.serialize({'value': 'sadsahjd'}))
def test_deprecated_field(self): engine = Dynabuffers.parse( InputStream("class Color { name:string rgb:string(deprecated) }")) engine.add_listener(print) map = engine.deserialize( engine.serialize({ "name": "red", "rgb": "255,0,0" })) self.assertEqual(map, {"name": "red", "rgb": "255,0,0"})
def test_number_with_dot(self): engine = Dynabuffers.parse(""" class Data { value: float = 0.5 } """) value = round( engine.deserialize(engine.serialize({"value": 0.6}))["value"], 1) self.assertEqual(0.6, value) value = round(engine.deserialize(engine.serialize({}))["value"], 1) self.assertEqual(0.5, value)
def test_optional_value(self): engine = Dynabuffers.parse(""" class Data { type:string = "test" list:[string] = [] attr:map = [:] } """) result = engine.deserialize(engine.serialize({})) self.assertTrue("type" in result) self.assertTrue("list" in result) self.assertTrue("attr" in result)
def test_class_with_enum(self): engine = Dynabuffers.parse( InputStream(""" enum Color { RED GREEN BLUE } class Product { name:string color:Color } """)) encoded = base64.b64encode( engine.serialize({ "name": "TV", "color": "RED" })).decode("utf-8") self.assertEqual(encoded, "AAJUVgNSRUQ=")
def test_bytearray_field(self): engine = Dynabuffers.parse( InputStream("class Image { content:[byte] type:string }")) map = engine.deserialize( engine.serialize({ "type": "jpg", "content": "abc".encode("utf-8") })) self.assertEqual(map, { "type": "jpg", "content": "abc".encode("utf-8") })
def test_parse_enum(self): engine = Dynabuffers.parse( InputStream(""" enum Color { RED GREEN BLUE } class Product { name:string color:Color } """)) map = engine.deserialize( engine.serialize({ "name": "TV", "color": "RED" })) self.assertEqual(map, {"name": "TV", "color": "RED"})
def test_default_namespace_is_used_if_only_one_is_defined(self): engine = Dynabuffers.parse(""" namespace abc{ class Data { value: string } } """) map = {"value": "hallo"} resultmap = {"value": "hallo", ":namespace": "abc"} self.assertEqual(resultmap, engine.deserialize(engine.serialize(map), "abc")) self.assertEqual(resultmap, engine.deserialize(engine.serialize(map, "abc"))) self.assertEqual(resultmap, engine.deserialize(engine.serialize(map)))
def test_schema_with_nested_namespace_but_specified_namespaces_with_wrong_order_have_no_effect( self): engine = Dynabuffers.parse(""" namespace abc{ namespace def { class Data { value: string } } } """) map = {"value": "hallo"} result = engine.deserialize(engine.serialize(map, ["abc", "def"]), ["def", "abc"]) self.assertEqual({**map, **{':namespace': 'abc.def'}}, result)
def test_schema_with_nested_namespace_but_specified_namespaces_have_wrong_order_1( self): engine = Dynabuffers.parse(""" namespace abc{ namespace def { class Data { value: string } } } """) map = {"value": "hallo"} with self.assertRaises(Exception) as ctx: engine.serialize(map, ["def", "abc"]) self.assertTrue( str(ctx.exception) in "no namespace with name def found")
def test_default_namespace_resolution_works_with_nested_namespaces(self): engine = Dynabuffers.parse(""" namespace abc{ namespace xyz { class Data { value: string } } } """) map = {"value": "hallo"} self.assertEqual( map, engine.deserialize(engine.serialize(map, ["abc", "xyz"]))) self.assertEqual( map, engine.deserialize(engine.serialize(map), ["abc", "xyz"])) self.assertEqual(map, engine.deserialize(engine.serialize(map)))
def test_multiple_classes(self): engine = Dynabuffers.parse( InputStream(""" class Product { name:string price:float } class Order(primary) { product:Product amount:int } """)) encoded = base64.b64encode( engine.serialize({ "product": { "name": "TV", "price": 1000 }, "amount": 2 })).decode("utf-8") self.assertEqual(encoded, "AAJUVkR6AAAAAAAC")
def test_default_namespace_resolution_fails_if_multiple_namespaces_are_defined( self): engine = Dynabuffers.parse(""" namespace abc{ class Data { value: string } } namespace xyz { } """) map = {"value": "hallo"} with self.assertRaises(Exception) as ctx: engine.deserialize(engine.serialize(map)) self.assertEqual(str(ctx.exception), "Could not infer default namespace")
def test_schema_with_namespace_containing_slash_in_name(self): engine = Dynabuffers.parse(""" namespace `leftshiftone/echo`{ namespace abc { namespace def { class Data { value: string } } } } """) map = {"value": "hallo"} result = engine.deserialize( engine.serialize(map, ["`leftshiftone/echo`", "abc", "def"]), ["`leftshiftone/echo`", "abc", "def"]) self.assertEqual(map, result)
def test_annotated_field(self): engine = Dynabuffers.parse( InputStream(""" class Product { @NotBlank @MinLength(3) @MaxLength(10) name:string @GreaterThan(0) price:float } """)) map = engine.deserialize( engine.serialize({ "name": "Fernseher", "price": 1000 })) self.assertEqual(map, {"name": "Fernseher", "price": 1000})
def evaluate(self, payload: dict, incoming_namespaces: List[str] = None, outgoing_namespaces: List[str] = None): if not incoming_namespaces: incoming_namespaces = ["incoming"] if not outgoing_namespaces: outgoing_namespaces = ["outgoing"] function = self.import_function(self.evaluate_function, self.handler_module) self._dynabuffers = Dynabuffers.parse(FileStream(self.contract_path)) parsed_payload = self._dynabuffers.deserialize( self._dynabuffers.serialize(payload, incoming_namespaces), incoming_namespaces) response = function(parsed_payload, self.context) parsed_response = self._dynabuffers.deserialize( self._dynabuffers.serialize(response, outgoing_namespaces), outgoing_namespaces) return parsed_response
def test_multiple_classes(self): engine = Dynabuffers.parse( InputStream(""" class Product { name:string price:float } class Order(primary) { product:Product amount:int } """)) map = engine.deserialize( engine.serialize({ "product": { "name": "TV", "price": 1000 }, "amount": 2 })) self.assertEqual(map, { "product": { "name": "TV", "price": 1000 }, "amount": 2 })