/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include namespace apache::thrift::conformance::data { namespace { const uint32_t kMaxFrameSize = (1 << 24) - 1; const std::string kLargeData = std::string(kMaxFrameSize * 2, 'a'); const uint64_t kDefaultBufferSize = 100; // =================== Request-Response =================== Test createRequestResponseBasicTest() { Test ret; ret.name() = "RequestResponseBasicTest"; ret.tags()->emplace("spec/protocol/interface/#request-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "RequestResponseBasic/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .requestResponseBasic_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.clientTestResult() .emplace() .requestResponseBasic_ref() .emplace() .response() .emplace() .data() = "world"; rpcTest.serverInstruction() .emplace() .requestResponseBasic_ref() .emplace() .response() .emplace() .data() = "world"; rpcTest.serverTestResult() .emplace() .requestResponseBasic_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createRequestResponseDeclaredExceptionTest() { Test ret; ret.name() = "RequestResponseDeclaredExceptionTest"; ret.tags()->emplace( "spec/protocol/interface/#declared-response-and-declared-exception"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "RequestResponseDeclaredException/Success"; UserException userException; userException.msg() = "world"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .requestResponseDeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.clientTestResult() .emplace() .requestResponseDeclaredException_ref() .emplace() .userException() = userException; rpcTest.serverInstruction() .emplace() .requestResponseDeclaredException_ref() .emplace() .userException() = userException; rpcTest.serverTestResult() .emplace() .requestResponseDeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createRequestResponseUndeclaredExceptionTest() { Test ret; ret.name() = "RequestResponseUndeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/#undeclared-exception"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "RequestResponseUndeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .requestResponseUndeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.clientTestResult() .emplace() .requestResponseUndeclaredException_ref() .emplace() .exceptionMessage() = "my undeclared exception"; rpcTest.serverInstruction() .emplace() .requestResponseUndeclaredException_ref() .emplace() .exceptionMessage() = "my undeclared exception"; rpcTest.serverTestResult() .emplace() .requestResponseUndeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createRequestResponseNoArgVoidResponse() { Test ret; ret.name() = "RequestResponseNoArgVoidResponseTest"; ret.tags()->emplace("spec/protocol/interface/#request-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "RequestResponseNoArgVoidResponse/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .requestResponseNoArgVoidResponse_ref() .emplace(); rpcTest.clientTestResult() .emplace() .requestResponseNoArgVoidResponse_ref() .emplace(); rpcTest.serverInstruction() .emplace() .requestResponseNoArgVoidResponse_ref() .emplace(); rpcTest.serverTestResult() .emplace() .requestResponseNoArgVoidResponse_ref() .emplace(); return ret; } Test createRequestResponseTimeoutTest() { Test ret; ret.name() = "RequestResponseTimeoutTest"; ret.tags()->emplace("spec/protocol/interface/#client-timeout"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "RequestResponseTimeout/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction() .emplace() .requestResponseTimeout_ref() .emplace(); clientInstruction.request().emplace().data() = "hello"; clientInstruction.timeoutMs() = 100; rpcTest.clientTestResult() .emplace() .requestResponseTimeout_ref() .emplace() .timeoutException() = true; rpcTest.serverInstruction() .emplace() .requestResponseTimeout_ref() .emplace() .timeoutMs() = 150; rpcTest.serverTestResult() .emplace() .requestResponseTimeout_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createRequestResponseFragmentationTest() { Test ret; ret.name() = "RequestResponseFragmentationTest"; ret.tags()->emplace("spec/protocol/interface/rocket#request-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "RequestResponseFragmentation/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .requestResponseBasic_ref() .emplace() .request() .emplace() .data() = kLargeData; rpcTest.clientTestResult() .emplace() .requestResponseBasic_ref() .emplace() .response() .emplace() .data() = kLargeData; rpcTest.serverInstruction() .emplace() .requestResponseBasic_ref() .emplace() .response() .emplace() .data() = kLargeData; rpcTest.serverTestResult() .emplace() .requestResponseBasic_ref() .emplace() .request() .emplace() .data() = kLargeData; return ret; } // =================== Stream =================== Test createStreamBasicTest() { Test ret; ret.name() = "StreamBasicTest"; ret.tags()->emplace("spec/protocol/interface/#stream"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamBasic/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().streamBasic_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; clientInstruction.bufferSize() = kDefaultBufferSize; auto& serverInstruction = rpcTest.serverInstruction().emplace().streamBasic_ref().emplace(); for (int i = 0; i < 100; i++) { auto& payload = serverInstruction.streamPayloads()->emplace_back(); payload.data() = folly::to(i); } rpcTest.clientTestResult() .emplace() .streamBasic_ref() .emplace() .streamPayloads() .copy_from(serverInstruction.streamPayloads()); rpcTest.serverTestResult() .emplace() .streamBasic_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamChunkTimeoutTest() { Test ret; ret.name() = "StreamChunkTimeoutTest"; ret.tags()->emplace("spec/protocol/interface/#stream-chunk-timeout"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamChunkTimeout/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().streamChunkTimeout_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; clientInstruction.chunkTimeoutMs() = 100; auto& serverInstruction = rpcTest.serverInstruction().emplace().streamChunkTimeout_ref().emplace(); for (int i = 0; i < 100; i++) { auto& payload = serverInstruction.streamPayloads()->emplace_back(); payload.data() = folly::to(i); } serverInstruction.chunkTimeoutMs() = 150; auto& clientTestResult = rpcTest.clientTestResult().emplace().streamChunkTimeout_ref().emplace(); clientTestResult.streamPayloads().copy_from( serverInstruction.streamPayloads()); clientTestResult.chunkTimeoutException() = true; rpcTest.serverTestResult() .emplace() .streamChunkTimeout_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamFragmentationTest() { Test ret; ret.name() = "StreamFragmentationTest"; ret.tags()->emplace("spec/protocol/interface/rocket/#stream"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamFragmentation/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().streamBasic_ref().emplace(); clientInstruction.request().emplace().data() = kLargeData; clientInstruction.bufferSize() = kDefaultBufferSize; auto& serverInstruction = rpcTest.serverInstruction().emplace().streamBasic_ref().emplace(); serverInstruction.streamPayloads()->emplace_back().data() = kLargeData; rpcTest.clientTestResult() .emplace() .streamBasic_ref() .emplace() .streamPayloads() .copy_from(serverInstruction.streamPayloads()); rpcTest.serverTestResult() .emplace() .streamBasic_ref() .emplace() .request() .emplace() .data() = kLargeData; return ret; } Test createStreamInitialResponseTest() { Test ret; ret.name() = "StreamInitialResponseTest"; ret.tags()->emplace("spec/protocol/interface/#stream-initial-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamInitialResponse/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .streamInitialResponse_ref() .emplace() .request() .emplace() .data() = "hello"; auto& serverInstruction = rpcTest.serverInstruction() .emplace() .streamInitialResponse_ref() .emplace(); for (int i = 0; i < 100; i++) { auto& payload = serverInstruction.streamPayloads()->emplace_back(); payload.data() = folly::to(i); } serverInstruction.initialResponse().emplace().data() = "world"; auto& clientTestResult = rpcTest.clientTestResult() .emplace() .streamInitialResponse_ref() .emplace(); clientTestResult.streamPayloads().copy_from( serverInstruction.streamPayloads()); clientTestResult.initialResponse().emplace().data() = "world"; rpcTest.serverTestResult() .emplace() .streamInitialResponse_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamSubsequentCreditsTest() { // Same as StreamBasicTest but the chunk buffer size is smaller than the // number of stream payloads, so the client must keep sending subsequent // credits in order to receive all stream payloads. Test ret; ret.name() = "StreamSubsequentCreditsTest"; ret.tags()->emplace("spec/protocol/interface/#stream-flow-control"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamSubsequentCredits/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().streamBasic_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; clientInstruction.bufferSize() = 10; auto& serverInstruction = rpcTest.serverInstruction().emplace().streamBasic_ref().emplace(); for (int i = 0; i < 100; i++) { auto& payload = serverInstruction.streamPayloads()->emplace_back(); payload.data() = folly::to(i); } rpcTest.clientTestResult() .emplace() .streamBasic_ref() .emplace() .streamPayloads() .copy_from(serverInstruction.streamPayloads()); rpcTest.serverTestResult() .emplace() .streamBasic_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamCreditTimeoutTest() { Test ret; ret.name() = "StreamCreditTimeoutTest"; ret.tags()->emplace("spec/protocol/interface/#stream-expire-time"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamCreditTimeout/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().streamCreditTimeout_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; clientInstruction.creditTimeoutMs() = 100; auto& serverInstruction = rpcTest.serverInstruction().emplace().streamCreditTimeout_ref().emplace(); for (int i = 0; i < 100; i++) { auto& payload = serverInstruction.streamPayloads()->emplace_back(); payload.data() = folly::to(i); } serverInstruction.streamExpireTime() = 50; auto& clientTestResult = rpcTest.clientTestResult().emplace().streamCreditTimeout_ref().emplace(); clientTestResult.creditTimeoutException() = true; rpcTest.serverTestResult() .emplace() .streamCreditTimeout_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamDeclaredExceptionTest() { Test ret; ret.name() = "StreamDeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/rocket#stream-exception"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamDeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .streamDeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.serverInstruction() .emplace() .streamDeclaredException_ref() .emplace() .userException() .emplace() .msg() = "world"; rpcTest.clientTestResult() .emplace() .streamDeclaredException_ref() .emplace() .userException() .emplace() .msg() = "world"; rpcTest.serverTestResult() .emplace() .streamDeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamUndeclaredExceptionTest() { Test ret; ret.name() = "StreamUndeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/rocket#stream-exception"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamUndeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .streamUndeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.serverInstruction() .emplace() .streamUndeclaredException_ref() .emplace() .exceptionMessage() = "world"; rpcTest.clientTestResult() .emplace() .streamUndeclaredException_ref() .emplace() .exceptionMessage() = "world"; rpcTest.serverTestResult() .emplace() .streamUndeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamInitialDeclaredExceptionTest() { Test ret; ret.name() = "StreamInitialDeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/#stream-initial-response"); ret.tags()->emplace("spec/protocol/interface/rocket#stream-initial-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamInitialDeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .streamInitialDeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.serverInstruction() .emplace() .streamInitialDeclaredException_ref() .emplace() .userException() .emplace() .msg() = "world"; rpcTest.clientTestResult() .emplace() .streamInitialDeclaredException_ref() .emplace() .userException() .emplace() .msg() = "world"; rpcTest.serverTestResult() .emplace() .streamInitialDeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamInitialUndeclaredExceptionTest() { Test ret; ret.name() = "StreamInitialUndeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/#stream-initial-response"); ret.tags()->emplace("spec/protocol/interface/rocket#stream-initial-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamInitialUndeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .streamInitialUndeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; rpcTest.serverInstruction() .emplace() .streamInitialUndeclaredException_ref() .emplace() .exceptionMessage() = "world"; rpcTest.clientTestResult() .emplace() .streamInitialUndeclaredException_ref() .emplace() .exceptionMessage() = "world"; rpcTest.serverTestResult() .emplace() .streamInitialUndeclaredException_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } Test createStreamInitialTimeoutTest() { Test ret; ret.name() = "StreamInitialTimeoutTest"; ret.tags()->emplace("spec/protocol/interface/#client-timeout"); ret.tags()->emplace("spec/protocol/interface/#client-detected-exceptions"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "StreamInitialTimeout/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction() .emplace() .streamInitialTimeout_ref() .emplace(); clientInstruction.request().emplace().data() = "hello"; clientInstruction.timeoutMs() = 100; rpcTest.serverInstruction() .emplace() .streamInitialTimeout_ref() .emplace() .timeoutMs() = 150; rpcTest.clientTestResult() .emplace() .streamInitialTimeout_ref() .emplace() .timeoutException() = true; rpcTest.serverTestResult() .emplace() .streamInitialTimeout_ref() .emplace() .request() .emplace() .data() = "hello"; return ret; } // =================== Sink =================== Test createSinkBasicTest() { Test ret; ret.name() = "SinkBasicTest"; ret.tags()->emplace("spec/protocol/interface/#sink"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkBasic/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().sinkBasic_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; for (int i = 0; i < 100; i++) { auto& sinkPayload = clientInstruction.sinkPayloads()->emplace_back(); sinkPayload.data() = folly::to(i); } rpcTest.clientTestResult() .emplace() .sinkBasic_ref() .emplace() .finalResponse() .emplace() .data() = "world"; auto& serverInstruction = rpcTest.serverInstruction().emplace().sinkBasic_ref().emplace(); serverInstruction.finalResponse().emplace().data() = "world"; serverInstruction.bufferSize() = kDefaultBufferSize; auto& serverResult = rpcTest.serverTestResult().emplace().sinkBasic_ref().emplace(); serverResult.request().emplace().data() = "hello"; serverResult.sinkPayloads().copy_from(clientInstruction.sinkPayloads()); return ret; } Test createSinkFragmentationTest() { Test ret; ret.name() = "SinkFragmentationTest"; ret.tags()->emplace("spec/protocol/interface/rocket/#sink"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkFragmentation/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().sinkBasic_ref().emplace(); clientInstruction.request().emplace().data() = kLargeData; clientInstruction.sinkPayloads()->emplace_back().data() = kLargeData; rpcTest.clientTestResult() .emplace() .sinkBasic_ref() .emplace() .finalResponse() .emplace() .data() = kLargeData; auto& serverInstruction = rpcTest.serverInstruction().emplace().sinkBasic_ref().emplace(); serverInstruction.finalResponse().emplace().data() = kLargeData; serverInstruction.bufferSize() = kDefaultBufferSize; auto& serverResult = rpcTest.serverTestResult().emplace().sinkBasic_ref().emplace(); serverResult.request().emplace().data() = kLargeData; serverResult.sinkPayloads().copy_from(clientInstruction.sinkPayloads()); return ret; } Test createSinkSubsequentCreditsTest() { // Same as SinkBasicTest but the server buffer size is smaller than the number // of sink payloads, so the server must keep sending subsequent credits in // order to receive all sink payloads. Test ret; ret.name() = "SinkSubsequentCreditsTest"; ret.tags()->emplace("spec/protocol/interface/#sink-flow-control"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkSubsequestCredits/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().sinkBasic_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; for (int i = 0; i < 100; i++) { auto& sinkPayload = clientInstruction.sinkPayloads()->emplace_back(); sinkPayload.data() = folly::to(i); } rpcTest.clientTestResult() .emplace() .sinkBasic_ref() .emplace() .finalResponse() .emplace() .data() = "world"; auto& serverInstruction = rpcTest.serverInstruction().emplace().sinkBasic_ref().emplace(); serverInstruction.finalResponse().emplace().data() = "world"; serverInstruction.bufferSize() = 10; auto& serverResult = rpcTest.serverTestResult().emplace().sinkBasic_ref().emplace(); serverResult.request().emplace().data() = "hello"; serverResult.sinkPayloads().copy_from(clientInstruction.sinkPayloads()); return ret; } Test createSinkChunkTimeoutTest() { Test ret; ret.name() = "SinkChunkTimeoutTest"; ret.tags()->emplace("spec/protocol/interface/#sink-chunk-timeout"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkChunkTimeout/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().sinkChunkTimeout_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; for (int i = 0; i < 100; i++) { auto& sinkPayload = clientInstruction.sinkPayloads()->emplace_back(); sinkPayload.data() = folly::to(i); } clientInstruction.chunkTimeoutMs() = 150; rpcTest.clientTestResult() .emplace() .sinkChunkTimeout_ref() .emplace() .chunkTimeoutException() = true; auto& serverInstruction = rpcTest.serverInstruction().emplace().sinkChunkTimeout_ref().emplace(); serverInstruction.finalResponse().emplace().data() = "world"; serverInstruction.chunkTimeoutMs() = 100; auto& serverResult = rpcTest.serverTestResult().emplace().sinkChunkTimeout_ref().emplace(); serverResult.request().emplace().data() = "hello"; serverResult.sinkPayloads().copy_from(clientInstruction.sinkPayloads()); serverResult.chunkTimeoutException() = true; return ret; } Test createSinkInitialResponseTest() { Test ret; ret.name() = "SinkInitialResponseTest"; ret.tags()->emplace("spec/protocol/interface/#sink-initial-response"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkInitialResponse/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction().emplace().sinkInitialResponse_ref().emplace(); clientInstruction.request().emplace().data() = "hello"; for (int i = 0; i < 100; i++) { auto& sinkPayload = clientInstruction.sinkPayloads()->emplace_back(); sinkPayload.data() = folly::to(i); } auto& testResult = rpcTest.clientTestResult().emplace().sinkInitialResponse_ref().emplace(); testResult.initialResponse().emplace().data() = "hello"; testResult.finalResponse().emplace().data() = "world"; auto& serverInstruction = rpcTest.serverInstruction().emplace().sinkInitialResponse_ref().emplace(); serverInstruction.initialResponse().emplace().data() = "hello"; serverInstruction.finalResponse().emplace().data() = "world"; serverInstruction.bufferSize() = kDefaultBufferSize; auto& serverResult = rpcTest.serverTestResult().emplace().sinkInitialResponse_ref().emplace(); serverResult.request().emplace().data() = "hello"; serverResult.sinkPayloads().copy_from(clientInstruction.sinkPayloads()); return ret; } Test createSinkDeclaredExceptionTest() { Test ret; ret.name() = "SinkDeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/#sink-declared-exception"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkDeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction() .emplace() .sinkDeclaredException_ref() .emplace(); clientInstruction.request().emplace().data() = "request"; clientInstruction.userException().emplace().msg() = "user_exception"; rpcTest.clientTestResult() .emplace() .sinkDeclaredException_ref() .emplace() .sinkThrew() = true; rpcTest.serverInstruction() .emplace() .sinkDeclaredException_ref() .emplace() .bufferSize() = kDefaultBufferSize; auto& serverResult = rpcTest.serverTestResult() .emplace() .sinkDeclaredException_ref() .emplace(); serverResult.request().emplace().data() = "request"; serverResult.userException().copy_from(clientInstruction.userException()); return ret; } Test createSinkUndeclaredExceptionTest() { Test ret; ret.name() = "SinkUndeclaredExceptionTest"; ret.tags()->emplace("spec/protocol/interface/#sink-undeclared-exception"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "SinkUndeclaredException/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction() .emplace() .sinkUndeclaredException_ref() .emplace(); clientInstruction.request().emplace().data() = "request"; clientInstruction.exceptionMessage() = "undeclared_exception"; rpcTest.clientTestResult() .emplace() .sinkUndeclaredException_ref() .emplace() .sinkThrew() = true; rpcTest.serverInstruction() .emplace() .sinkUndeclaredException_ref() .emplace() .bufferSize() = kDefaultBufferSize; auto& serverResult = rpcTest.serverTestResult() .emplace() .sinkUndeclaredException_ref() .emplace(); serverResult.request().copy_from(clientInstruction.request()); serverResult.exceptionMessage().copy_from( clientInstruction.exceptionMessage()); return ret; } // =================== Interactions =================== Test createInteractionConstructorTest() { Test ret; ret.name() = "InteractionConstructorTest"; ret.tags()->emplace("spec/protocol/interface/#constructors-deprecated"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "InteractionConstructorTest/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction().emplace().interactionConstructor_ref().emplace(); rpcTest.clientTestResult().emplace().interactionConstructor_ref().emplace(); rpcTest.serverInstruction().emplace().interactionConstructor_ref().emplace(); rpcTest.serverTestResult() .emplace() .interactionConstructor_ref() .emplace() .constructorCalled() = true; return ret; } Test createInteractionFactoryFunctionTest() { Test ret; ret.name() = "InteractionFactoryFunctionTest"; ret.tags()->emplace("spec/protocol/interface/#factory-functions"); ret.tags()->emplace("spec/protocol/interface/rocket/#factory-functions"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "InteractionFactoryFunctionTest/Success"; constexpr int initialSum = 10; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .interactionFactoryFunction_ref() .emplace() .initialSum() = initialSum; rpcTest.clientTestResult() .emplace() .interactionFactoryFunction_ref() .emplace(); rpcTest.serverInstruction() .emplace() .interactionFactoryFunction_ref() .emplace(); rpcTest.serverTestResult() .emplace() .interactionFactoryFunction_ref() .emplace() .initialSum() = initialSum; return ret; } Test createInteractionConstructorPersistsStateTest() { Test ret; ret.name() = "InteractionConstructorPersistsStateTest"; ret.tags()->emplace("spec/protocol/interface/#interactions"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "InteractionConstructorPersistsStateTest/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction() .emplace() .interactionPersistsState_ref() .emplace(); auto& clientTestResult = rpcTest.clientTestResult() .emplace() .interactionPersistsState_ref() .emplace(); int sum = 0; for (int i = 1; i <= 5; i++) { sum += i; clientInstruction.valuesToAdd()->emplace_back(i); clientTestResult.responses()->emplace_back(sum); } rpcTest.serverInstruction() .emplace() .interactionPersistsState_ref() .emplace(); rpcTest.serverTestResult().emplace().interactionPersistsState_ref().emplace(); return ret; } Test createInteractionFactoryFunctionPersistsStateTest() { Test ret; ret.name() = "InteractionFactoryFunctionPersistsStateTest"; ret.tags()->emplace("spec/protocol/interface/#interactions"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "InteractionFactoryFunctionPersistsStateTest/Success"; constexpr int initialSum = 10; auto& rpcTest = testCase.rpc_ref().emplace(); auto& clientInstruction = rpcTest.clientInstruction() .emplace() .interactionPersistsState_ref() .emplace(); clientInstruction.initialSum() = initialSum; auto& clientTestResult = rpcTest.clientTestResult() .emplace() .interactionPersistsState_ref() .emplace(); int sum = initialSum; for (int i = 1; i <= 5; i++) { sum += i; clientInstruction.valuesToAdd()->emplace_back(i); clientTestResult.responses()->emplace_back(sum); } rpcTest.serverInstruction() .emplace() .interactionPersistsState_ref() .emplace(); rpcTest.serverTestResult().emplace().interactionPersistsState_ref().emplace(); return ret; } Test createInteractionConstructorTerminationTest() { Test ret; ret.name() = "InteractionConstructorTerminationTest"; ret.tags()->emplace("spec/protocol/interface/#termination"); ret.tags()->emplace("spec/protocol/interface/rocket/#termination"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "InteractionConstructorTerminationTest/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction().emplace().interactionTermination_ref().emplace(); rpcTest.clientTestResult().emplace().interactionTermination_ref().emplace(); rpcTest.serverInstruction().emplace().interactionTermination_ref().emplace(); rpcTest.serverTestResult() .emplace() .interactionTermination_ref() .emplace() .terminationReceived() = true; return ret; } Test createInteractionFactoryFunctionTerminationTest() { Test ret; ret.name() = "InteractionFactoryFunctionTerminationTest"; ret.tags()->emplace("spec/protocol/interface/#sink-chunk-timeout"); ret.tags()->emplace("spec/protocol/interface/rocket/#termination"); auto& testCase = ret.testCases()->emplace_back(); testCase.name() = "InteractionFactoryFunctionTerminationTest/Success"; auto& rpcTest = testCase.rpc_ref().emplace(); rpcTest.clientInstruction() .emplace() .interactionTermination_ref() .emplace() .initialSum() = 10; rpcTest.clientTestResult().emplace().interactionTermination_ref().emplace(); rpcTest.serverInstruction().emplace().interactionTermination_ref().emplace(); rpcTest.serverTestResult() .emplace() .interactionTermination_ref() .emplace() .terminationReceived() = true; return ret; } void addCommonRequestResponseTests(TestSuite& suite) { // =================== Request-Response =================== suite.tests()->push_back(createRequestResponseBasicTest()); suite.tests()->push_back(createRequestResponseDeclaredExceptionTest()); suite.tests()->push_back(createRequestResponseUndeclaredExceptionTest()); suite.tests()->push_back(createRequestResponseNoArgVoidResponse()); suite.tests()->push_back(createRequestResponseFragmentationTest()); } void addCommonRPCTests(TestSuite& suite) { // =================== Request-Response =================== addCommonRequestResponseTests(suite); // =================== Stream =================== suite.tests()->push_back(createStreamBasicTest()); suite.tests()->push_back(createStreamFragmentationTest()); suite.tests()->push_back(createStreamInitialResponseTest()); suite.tests()->push_back(createStreamSubsequentCreditsTest()); suite.tests()->push_back(createStreamDeclaredExceptionTest()); suite.tests()->push_back(createStreamUndeclaredExceptionTest()); suite.tests()->push_back(createStreamInitialDeclaredExceptionTest()); suite.tests()->push_back(createStreamInitialUndeclaredExceptionTest()); // =================== Sink =================== suite.tests()->push_back(createSinkBasicTest()); suite.tests()->push_back(createSinkFragmentationTest()); suite.tests()->push_back(createSinkSubsequentCreditsTest()); suite.tests()->push_back(createSinkInitialResponseTest()); suite.tests()->push_back(createSinkDeclaredExceptionTest()); suite.tests()->push_back(createSinkUndeclaredExceptionTest()); // =================== Interactions =================== suite.tests()->push_back(createInteractionConstructorTest()); suite.tests()->push_back(createInteractionFactoryFunctionTest()); suite.tests()->push_back(createInteractionConstructorPersistsStateTest()); suite.tests()->push_back(createInteractionFactoryFunctionPersistsStateTest()); suite.tests()->push_back(createInteractionConstructorTerminationTest()); suite.tests()->push_back(createInteractionFactoryFunctionTerminationTest()); } } // namespace TestSuite createRPCServerTestSuite() { TestSuite suite; suite.name() = "ThriftRPCServerTest"; suite.tags()->emplace("spec/protocol/interface/"); addCommonRPCTests(suite); // =================== Sink =================== suite.tests()->push_back(createSinkChunkTimeoutTest()); return suite; } TestSuite createBasicRPCServerTestSuite() { TestSuite suite; suite.name() = "ThriftBasicRPCServerTest"; suite.tags()->emplace("spec/protocol/interface/"); addCommonRequestResponseTests(suite); return suite; } TestSuite createRPCClientTestSuite() { TestSuite suite; suite.name() = "ThriftRPCClientTest"; suite.tags()->emplace("spec/protocol/interface/"); addCommonRPCTests(suite); // =================== Request-Response =================== suite.tests()->push_back(createRequestResponseTimeoutTest()); // =================== Stream =================== suite.tests()->push_back(createStreamChunkTimeoutTest()); suite.tests()->push_back(createStreamCreditTimeoutTest()); suite.tests()->push_back(createStreamInitialTimeoutTest()); return suite; } } // namespace apache::thrift::conformance::data