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_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_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_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_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_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_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 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 CreateModels(documents): for document in documents: visitor = IncludeVisitor() document.includes = visitor.visit(document.parseTree) visitor = ExceptionVisitor() document.exceptions = visitor.visit(document.parseTree) visitor = EnumerationVisitor() document.enumerations = visitor.visit(document.parseTree) visitor = StructureVisitor() document.structures = visitor.visit(document.parseTree) visitor = ServiceVisitor() document.services = visitor.visit(document.parseTree) for document in documents: visitor = ValidationVisitor(documents, document.name) visitor.visit(document.parseTree)
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)