/* * 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 #include #include #include #include #include #include using namespace cpp2; using namespace apache::thrift; using namespace apache::thrift::util; class PresultServiceInterface : public apache::thrift::ServiceHandler { public: void methodVoid() override {} bool methodBool(bool x) override { return x; } int8_t methodByte(int8_t x) override { return x; } int16_t methodI16(int16_t x) override { return x; } int32_t methodI32(int32_t x) override { return x; } int64_t methodI64(int64_t x) override { return x; } float methodFloat(float x) override { return x; } double methodDouble(double x) override { return x; } Enum methodEnum(Enum x) override { return x; } void methodString(std::string& ret, std::unique_ptr x) override { ret = *x; } void methodBinary(std::string& ret, std::unique_ptr x) override { ret = *x; } void methodIOBuf( folly::IOBuf& ret, std::unique_ptr x) override { ret = std::move(*x); } void methodIOBufPtr( std::unique_ptr& ret, std::unique_ptr> x) override { ret = std::move(*x); } void methodList( std::vector& ret, std::unique_ptr> x) override { ret = *x; } void methodListBool( std::vector& ret, std::unique_ptr> x) override { ret = *x; } void methodDeque( std::deque& ret, std::unique_ptr> x) override { ret = *x; } void methodMap( std::map& ret, std::unique_ptr> x) override { ret = *x; } void methodUnorderedMap( std::unordered_map& ret, std::unique_ptr> x) override { ret = *x; } void methodSet( std::set& ret, std::unique_ptr> x) override { ret = *x; } void methodUnorderedSet( std::unordered_set& ret, std::unique_ptr> x) override { ret = *x; } void methodStruct(Struct& ret, std::unique_ptr x) override { ret = *x; } void methodException(Struct& /* ret */, int32_t which) override { if (which) { throw Exception1(FRAGILE, 5); } else { throw Exception2(FRAGILE, "ex2"); } } }; std::shared_ptr getClient( const ScopedServerThread& sst, folly::EventBase& eb) { auto socket = folly::AsyncSocket::newSocket(&eb, *sst.getAddress()); auto channel = HeaderClientChannel::newChannel(std::move(socket)); auto client = std::make_shared(std::move(channel)); return client; } template void run(int& count, F&& f, Arg&& arg) { count++; f().thenValue([arg, &count](const Arg& res) { EXPECT_EQ(arg, res); count--; }); } template void run(int& count, F&& f) { count++; f().thenValue([&count](auto&&) { count--; }); } #define F(method, ...) \ [client] { return client->future_##method(__VA_ARGS__); }, ##__VA_ARGS__ TEST(Presult, Presult) { folly::EventBase eb; apache::thrift::TestThriftServerFactory factory; factory.useSimpleThreadManager(false); ScopedServerThread sst(factory.create()); auto client = getClient(sst, eb); int count = 0; run(count, F(methodVoid)); run(count, F(methodBool, true)); run(count, F(methodByte, 5)); run(count, F(methodI16, 2000)); run(count, F(methodI32, 1 << 20)); run(count, F(methodI64, 1L << 40)); run(count, F(methodFloat, 3.14f)); run(count, F(methodDouble, 2.71)); run(count, F(methodEnum, Enum::Value2)); run(count, F(methodString, std::string("hello"))); run(count, F(methodBinary, std::string("binary"))); run(count, F(methodList, std::vector({1, 2, 3}))); run(count, F(methodListBool, std::vector({true, false, true}))); run(count, F(methodDeque, std::deque({1, 2, 3}))); run(count, F(methodMap, std::map({{1, 11}, {2, 22}, {3, 33}}))); run(count, F(methodUnorderedMap, std::unordered_map({{1, 11}, {2, 22}, {3, 33}}))); run(count, F(methodSet, std::set({1, 2, 3}))); run(count, F(methodUnorderedSet, std::unordered_set({1, 2, 3}))); run(count, F(methodStruct, Struct(FRAGILE, 5))); { count++; std::string data = "iobuf"; auto iobuf = folly::IOBuf::wrapBuffer(folly::StringPiece(data)); client->future_methodIOBuf(*iobuf).thenValue( [data, &count](folly::IOBuf&& res) { EXPECT_EQ(folly::StringPiece(res.coalesce()).str(), data); count--; }); } { count++; std::string data = "iobufptr"; auto iobuf = folly::IOBuf::wrapBuffer(folly::StringPiece(data)); client->future_methodIOBufPtr(std::move(iobuf)) .thenValue([data, &count](std::unique_ptr res) { EXPECT_EQ(folly::StringPiece(res->coalesce()).str(), data); count--; }); } count++; client->future_methodException(1) .thenValue([](const Struct&) { FAIL(); }) .thenError( folly::tag_t{}, [&count](const Exception1& e) { EXPECT_EQ(*e.code_ref(), 5); count--; }) .thenError(folly::tag_t{}, [](const std::exception&) { FAIL(); }); count++; client->future_methodException(0) .thenValue([](const Struct&) { FAIL(); }) .thenError( folly::tag_t{}, [&count](const Exception2& e) { EXPECT_EQ(*e.message_ref(), "ex2"); count--; }) .thenError(folly::tag_t{}, [](const std::exception&) { FAIL(); }); eb.loop(); EXPECT_EQ(count, 0); }