1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <thrift/conformance/cpp2/AnySerializer.h>
18
19 #include <any>
20
21 #include <folly/portability/GTest.h>
22 #include <thrift/conformance/cpp2/Testing.h>
23
24 namespace apache::thrift::conformance {
25
26 namespace {
27
28 // Helpers for encoding/decoding using stirngs.
encode(const AnySerializer & serializer,any_ref value)29 std::string encode(const AnySerializer& serializer, any_ref value) {
30 folly::IOBufQueue queue(folly::IOBufQueue::cacheChainLength());
31 // Allocate 16KB at a time; leave some room for the IOBuf overhead
32 constexpr size_t kDesiredGrowth = (1 << 14) - 64;
33 serializer.encode(value, folly::io::QueueAppender(&queue, kDesiredGrowth));
34
35 std::string result;
36 queue.appendToString(result);
37 return result;
38 }
39
40 template <typename T>
decode(const AnySerializer & serializer,std::string_view data)41 T decode(const AnySerializer& serializer, std::string_view data) {
42 folly::IOBuf buf(folly::IOBuf::WRAP_BUFFER, data.data(), data.size());
43 folly::io::Cursor cursor{&buf};
44 return serializer.decode<T>(cursor);
45 }
46
decode(const AnySerializer & serializer,const std::type_info & typeinfo,std::string_view data)47 std::any decode(
48 const AnySerializer& serializer,
49 const std::type_info& typeinfo,
50 std::string_view data) {
51 folly::IOBuf buf(folly::IOBuf::WRAP_BUFFER, data.data(), data.size());
52 folly::io::Cursor cursor{&buf};
53 std::any result;
54 serializer.decode(typeinfo, cursor, result);
55 return result;
56 }
57
TEST(AnySerializerTest,TypedSerializer)58 TEST(AnySerializerTest, TypedSerializer) {
59 FollyToStringSerializer<int> intCodec;
60 EXPECT_EQ(encode(intCodec, 1), "1");
61 EXPECT_EQ(decode<int>(intCodec, "1"), 1);
62
63 AnySerializer& anyCodec(intCodec);
64 EXPECT_EQ(encode(anyCodec, 1), "1");
65 EXPECT_EQ(encode(anyCodec, std::any(1)), "1");
66 EXPECT_THROW(encode(anyCodec, 2.5), std::bad_any_cast);
67 EXPECT_THROW(encode(anyCodec, std::any(2.5)), std::bad_any_cast);
68
69 EXPECT_EQ(decode<int>(anyCodec, "1"), 1);
70 EXPECT_EQ(std::any_cast<int>(decode(anyCodec, typeid(int), "1")), 1);
71
72 EXPECT_THROW(decode<double>(anyCodec, "1.0"), std::bad_any_cast);
73 EXPECT_THROW(decode(anyCodec, typeid(double), "1.0"), std::bad_any_cast);
74 }
75
TEST(SerializerTest,MultiSerializer)76 TEST(SerializerTest, MultiSerializer) {
77 MultiSerializer multiSerializer;
78 const AnySerializer& serializer = multiSerializer;
79
80 THRIFT_SCOPED_CHECK(multiSerializer.checkAndResetAll());
81
82 // Can handle ints.
83 EXPECT_EQ(encode(serializer, 1), "1");
84 THRIFT_SCOPED_CHECK(multiSerializer.checkIntEnc());
85 EXPECT_EQ(decode<int>(serializer, "1"), 1);
86 THRIFT_SCOPED_CHECK(multiSerializer.checkIntDec());
87
88 // Can handle std::any(int).
89 std::any a = decode(serializer, typeid(int), "1");
90 THRIFT_SCOPED_CHECK(multiSerializer.checkAnyIntDec());
91 EXPECT_EQ(std::any_cast<int>(a), 1);
92 EXPECT_EQ(encode(serializer, a), "1");
93 THRIFT_SCOPED_CHECK(multiSerializer.checkIntEnc());
94
95 // Can handle doubles.
96 EXPECT_EQ(encode(serializer, 2.5), "2.5");
97 THRIFT_SCOPED_CHECK(multiSerializer.checkDblEnc());
98 EXPECT_EQ(decode<double>(serializer, "0.5"), 0.5f);
99 THRIFT_SCOPED_CHECK(multiSerializer.checkDblDec());
100
101 // Can handle std::any(double).
102 a = decode(serializer, typeid(double), "1");
103 THRIFT_SCOPED_CHECK(multiSerializer.checkAnyDblDec());
104 EXPECT_EQ(std::any_cast<double>(a), 1.0);
105 EXPECT_EQ(encode(serializer, a), "1");
106 THRIFT_SCOPED_CHECK(multiSerializer.checkDblEnc());
107
108 // Cannot handle float.
109 EXPECT_THROW(encode(serializer, 1.0f), std::bad_any_cast);
110 THRIFT_SCOPED_CHECK(multiSerializer.checkAndResetAll());
111 EXPECT_THROW(decode<float>(serializer, "1"), std::bad_any_cast);
112 THRIFT_SCOPED_CHECK(multiSerializer.checkAndResetAll());
113
114 // Cannot handle std::any(float).
115 a = 1.0f;
116 EXPECT_THROW(decode(serializer, typeid(float), "1"), std::bad_any_cast);
117 THRIFT_SCOPED_CHECK(multiSerializer.checkAndResetAny(1));
118 THRIFT_SCOPED_CHECK(multiSerializer.checkAndResetAll());
119 EXPECT_THROW(encode(serializer, a), std::bad_any_cast);
120 THRIFT_SCOPED_CHECK(multiSerializer.checkAndResetAll());
121 }
122
123 } // namespace
124 } // namespace apache::thrift::conformance
125