def test_ValidationVisitor_FunctionOnlyThrowsExceptions_NoErrorRaised(): treeA = RpcDefinition( "exception RuntimeException { 1:string description; }").parse() treeB = RpcDefinition( "exception ConfigurationException { 1:string description; }").parse() treeC = RpcDefinition(""" exception ParameterException { 1:string description; } service MainService { void Foo() throws (1:Types.RuntimeException ex, 2:Configuration.ConfigurationException ex, 3:ParameterException ex) void Bar(1:i32 foobar) throws(1:Types.RuntimeException ex) } """).parse() documentA = Document("Types", treeA) documentB = Document("Configuration", treeB) documentC = Document("Main", treeC) visitor = ExceptionVisitor() documentA.exceptions = visitor.visit(treeA) documentB.exceptions = visitor.visit(treeB) documentC.exceptions = visitor.visit(treeC) visitor = ServiceVisitor() documentC.services = visitor.visit(treeC) documentC.includes = [ IncludeDeclaration("Types", "Types.rpc"), IncludeDeclaration("Configuration", "Configuration.rpc") ] visitor = ValidationVisitor([documentA, documentB, documentC], documentC.name) visitor.visit(documentC.parseTree)
def test_ValidationVisitor_ImportedTypeInStructure_NoErrorThrown(): treeA = RpcDefinition("struct A { 1:i32 a; }").parse() treeB = RpcDefinition("struct B { 1:Types.A a; }").parse() documentA = Document("Types", treeA) documentB = Document("test", treeB) documentB.includes = [IncludeDeclaration("Types", "Types.rpc")] visitor = StructureVisitor() documentA.structures = visitor.visit(treeA) documentB.structures = visitor.visit(treeB) visitor = ValidationVisitor([documentA, documentB], documentB.name) visitor.visit(documentB.parseTree)
def test_ParseServices_FunctionWithAmbiguousArgumentIds_RaisesRuntimeError(): text = """ service Foo { void Bar(1:i16 foo, 1:i32 bar); } """ definition = RpcDefinition(text) tree = definition.parse() visitor = ServiceVisitor() with pytest.raises(RuntimeError): visitor.visit(tree)
def test_ValidationVisitor_ImportedEnumInStructure_NoErrorRaised(): treeA = RpcDefinition("enum A { a = 0, b = 1 }").parse() treeB = RpcDefinition("struct B { 1:Types.A a; } ").parse() documentA = Document("Types", treeA) documentB = Document("test", treeB) documentB.includes = [IncludeDeclaration("Types", "Types.rpc")] visitor = EnumerationVisitor() documentA.enumerations = visitor.visit(treeA) visitor = StructureVisitor() documentB.structures = visitor.visit(treeB) visitor = ValidationVisitor([documentA, documentB], documentB.name) visitor.visit(documentB.parseTree)
def test_ParseEnumeration_NoEnumeration_EmptyResult(): tree = RpcDefinition("struct A { 1:i32 value; }").parse() visitor = EnumerationVisitor() enums = visitor.visit(tree) assert len(enums) == 0
def test_ParseStructure_StructWithoutMember_EmptyResult(): tree = RpcDefinition(" struct A { } ").parse() visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 0
def test_ParseStructure_NoStructure_EmptyResult(): tree = RpcDefinition("enum A { 1:i64 value; }").parse() visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 0
def test_ParseExceptions_NoException_Parsed(): tree = RpcDefinition("enum A { a = 0 }").parse() visitor = ExceptionVisitor() exceptions = visitor.visit(tree) assert len(exceptions) == 0
def test_ParseEnumeration_MultipleMembersDifferentValues_Parsed(): text = """ enum A { a, b = 3, c, d = 0xff, e, f } """ tree = RpcDefinition(text).parse() visitor = EnumerationVisitor() enums = visitor.visit(tree) expectedNumberOfValues = 6 expectedValues = [('a', 0), ('b', 3), ('c', 4), ('d', 255), ('e', 256), ('f', 257)] assert len(enums) == 1 assert len(enums[0].values) == expectedNumberOfValues for i in range(expectedNumberOfValues): assert expectedValues[i] == enums[0].values[i]
def test_ParseServices_ComplexFunctionDefinition_Parsed(): text = """ service A { void Foo(1:i64 a, 2:i32 b, 4:i16 c) throws (1:ConfigurationException a, 2:RuntimeError b); } """ tree = RpcDefinition(text).parse() visitor = ServiceVisitor() services = visitor.visit(tree) assert len(services) == 1 assert len(services[0].functions) == 1 function = services[0].functions[0] assert function.name == "Foo" expectedNumberOfArguments = 3 expectedArguments = [(1, 'i64', 'a'), (2, 'i32', 'b'), (4, 'i16', 'c')] expectedNumberOfExceptions = 2 expectedExceptions = [(1, 'ConfigurationException', 'a'), (2, 'RuntimeError', 'b')] for i in range(expectedNumberOfArguments): argument = function.args[i] argument = (argument.uniqueId, argument.valueType.name, argument.name) assert expectedArguments[i] == argument for i in range(expectedNumberOfExceptions): exception = function.exceptions[i] exception = (exception.uniqueId, exception.valueType.name, exception.name) assert expectedExceptions[i] == exception
def test_ValidationVisitor_FunctionThrowsNonException_ErrorRaised(): tree = RpcDefinition( "service MainService { void Foo() throws (1:i64 ex) }").parse() document = Document("test", tree) with pytest.raises(RuntimeError): visitor = ValidationVisitor([document], "test") visitor.visit(document.parseTree)
def checkReturnTypes(functionAsText: str): tree = RpcDefinition("service test { " + functionAsText + " }").parse() document = Document("test", tree) visitor = ServiceVisitor() document.services = visitor.visit(document.parseTree) visitor = ValidationVisitor([document], document.name) visitor.visit(document.parseTree)
def test_ParseExceptions_MembersWithAmbiguousIds_RaisesRuntimeError(): text = "exception A { 42:i32 a; 42:i64 b; }" tree = RpcDefinition(text).parse() visitor = ExceptionVisitor() with pytest.raises(RuntimeError): visitor.visit(tree)
def test_ParseStructure_MembersWithAmbiguousIds_RaisesRuntimeError(): text = "struct A { 1:i32 a; 1:i64 b; }" tree = RpcDefinition(text).parse() visitor = StructureVisitor() with pytest.raises(RuntimeError): visitor.visit(tree)
def test_ParseStructure_TwoStructures_BothParsed(): text = " struct A { 1:i16 B; } struct B { 1: i32 C; } " tree = RpcDefinition(text).parse() visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 2
def test_ParseServices_FunctionWithAmbiguousExceptionIds_RaisesRuntimeError(): text = """ exception ArgumentError { 1:i32 description; } exception ConfigurationError { 1:i32 description; } service Foo { void Bar() throws (1:ArgumentError error, 1:ConfigurationError error); } """ definition = RpcDefinition(text) tree = definition.parse() visitor = ServiceVisitor() with pytest.raises(RuntimeError): visitor.visit(tree)
def test_ParseStructure_ListMember_Parsed(): tree = RpcDefinition("struct A { 1:list<i64> value; }").parse() visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 1 assert len(structures[0].args) == 1 assert isinstance(structures[0].args[0].valueType, ListType) assert isinstance(structures[0].args[0].valueType.valueType, RegularType) assert structures[0].args[0].valueType.valueType.name == "i64"
def test_ParseEnumerations_TwoEnumerations_BothParsed(): text = """ enum A { a = 0 } enum B { b = 1 } """ tree = RpcDefinition(text).parse() visitor = EnumerationVisitor() enums = visitor.visit(tree) assert len(enums) == 2
def test_ParseExceptions_TwoExceptions_BothParsed(): text = """ exception A { 1:i32 a; } exception B { 1:i64 b; } """ tree = RpcDefinition(text).parse() visitor = ExceptionVisitor() exceptions = visitor.visit(tree) assert len(exceptions) == 2
def test_ParseEnumeration_SingleMemberNoValue_Parsed(): tree = RpcDefinition("enum A { a }").parse() visitor = EnumerationVisitor() enums = visitor.visit(tree) assert len(enums) == 1 assert enums[0].name == "A" assert len(enums[0].values) == 1 name, value = enums[0].values[0] assert name == "a" assert value == 0
def test_ParseServices_FullSample_Parsed(): text = """ include \"Types.thrift\" exception InvalidHandle { 1:i32 c; 2:binary d; } struct Parameters { 1:i64 a; 2:i16 b; } enum OperationMode { Sync = 4, Async, Both = 0x87 } service Database { void Run(0xf:i32 a, 2:i64 b); void Stop(3:i64 c); } """ tree = RpcDefinition(text).parse() visitor = IncludeVisitor() includes = visitor.visit(tree) assert len(includes) == 1 visitor = ExceptionVisitor() exceptions = visitor.visit(tree) assert len(exceptions) == 1 visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 1 visitor = EnumerationVisitor() enums = visitor.visit(tree) assert len(enums) == 1 visitor = ServiceVisitor() services = visitor.visit(tree) assert len(services) == 1
def test_ParseStructure_SingleMemberStructure_Parsed(): tree = RpcDefinition("struct A { 1:i64 B; }").parse() visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 1 assert structures[0].name == "A" assert len(structures[0].args) == 1 arg = structures[0].args[0] assert arg.name == "B" assert arg.uniqueId == 1 assert arg.valueType.name == "i64"
def test_ParseIncludes_MultipleIncludes_Parsed(): text = """ include \"common.thrift\" include \"shared.thrift\" """ tree = RpcDefinition(text).parse() visitor = IncludeVisitor() includes = visitor.visit(tree) assert len(includes) == 2 assert includes[0].name == "common" assert includes[0].fileName == "common.thrift" assert includes[1].name == "shared" assert includes[1].fileName == "shared.thrift"
def test_ParseServices_SingleService_Parsed(): text = """ service A { void a(1:i64 b), binary b(3:i16 c); } """ tree = RpcDefinition(text).parse() visitor = ServiceVisitor() services = visitor.visit(tree) assert len(services) == 1 assert services[0].name == "A" assert len(services[0].functions) == 2
def test_ParseServices_FunctionWithoutArgumentsButExceptions_Parsed(): text = """ exception ArgumentError { 1:i32 description; } exception ConfigurationError { 1:i32 description; } service Foo { void Bar() throws (1:ArgumentError error, 2:ConfigurationError error); } """ tree = RpcDefinition(text).parse() visitor = ServiceVisitor() services = visitor.visit(tree) assert len(services) == 1 assert len(services[0].functions) == 1 assert len(services[0].functions[0].args) == 0 assert len(services[0].functions[0].exceptions) == 2
def test_ValidationVisitor_DifferentFunctionArgTypes_NoErrorRaised(): tree = RpcDefinition(""" enum Event { foo = 0, bla = 1 } struct Data { 1:Event value; } service MainService { void Foo(1:i64 a, 2:Event b, 3:Data c); } """).parse() document = Document("test", tree) visitor = EnumerationVisitor() document.enumerations = visitor.visit(document.parseTree) visitor = StructureVisitor() document.structures = visitor.visit(document.parseTree) visitor = ServiceVisitor() document.services = visitor.visit(document.parseTree) visitor = ValidationVisitor([document], document.name) visitor.visit(document.parseTree)
def test_ParseStructure_MultipleMemberStructure_Parsed(): text = "struct A { 1:i32 B; 2:binary C; }" tree = RpcDefinition(text).parse() visitor = StructureVisitor() structures = visitor.visit(tree) assert len(structures) == 1 assert structures[0].name == "A" assert len(structures[0].args) == 2 arg1 = structures[0].args[0] arg2 = structures[0].args[1] assert arg1.name == "B" assert arg1.uniqueId == 1 assert arg1.valueType.name == "i32" assert arg2.name == "C" assert arg2.uniqueId == 2 assert arg2.valueType.name == "binary"
def test_ParseExceptions_SingleException_Parsed(): text = """ exception A { 1:i32 a; 2:i64 b; 4:binary c; } """ tree = RpcDefinition(text).parse() visitor = ExceptionVisitor() exceptions = visitor.visit(tree) assert len(exceptions) == 1 expectedNumberOfValues = 3 expectedValues = [(1, 'i32', 'a'), (2, 'i64', 'b'), (4, 'binary', 'c')] assert len(exceptions[0].args) == expectedNumberOfValues for i in range(expectedNumberOfValues): arg = exceptions[0].args[i] actualValue = (arg.uniqueId, arg.valueType.name, arg.name) assert expectedValues[i] == actualValue
def parseStructure(text: str): tree = RpcDefinition(text).parse() document = Document("test", tree) visitor = StructureVisitor() document.structures = visitor.visit(tree) return document