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/Testing.h>
18
19 #include <fmt/core.h>
20 #include <folly/lang/Exception.h>
21 #include <folly/portability/GTest.h>
22 #include <thrift/conformance/if/gen-cpp2/any_constants.h>
23
24 namespace apache::thrift::conformance {
25 using type::getUniversalHashSize;
26 const Protocol Number1Serializer::kProtocol = Protocol(thriftType("Number1"));
27 const Protocol kFollyToStringProtocol = Protocol(thriftType("FollyToString"));
28
thriftType(std::string_view type)29 std::string thriftType(std::string_view type) {
30 if (type.empty()) {
31 return {};
32 }
33 return fmt::format("facebook.com/thrift/{}", type);
34 }
35
testThriftType(const std::string & shortName)36 ThriftTypeInfo testThriftType(const std::string& shortName) {
37 return testThriftType({shortName.c_str()});
38 }
39
testThriftType(std::initializer_list<const char * > uris)40 ThriftTypeInfo testThriftType(std::initializer_list<const char*> uris) {
41 ThriftTypeInfo type;
42 type.set_typeHashBytes(0);
43 auto itr = uris.begin();
44 if (itr != uris.end()) {
45 type.set_uri(thriftType(*itr++));
46 }
47 while (itr != uris.end()) {
48 type.altUris_ref()->emplace(thriftType(*itr++));
49 }
50 return type;
51 }
52
toString(const folly::IOBuf & buf)53 std::string toString(const folly::IOBuf& buf) {
54 std::string result;
55 folly::IOBufQueue queue;
56 queue.append(buf);
57 queue.appendToString(result);
58 return result;
59 }
60
encode(any_ref value,folly::io::QueueAppender && appender) const61 void MultiSerializer::encode(
62 any_ref value, folly::io::QueueAppender&& appender) const {
63 if (value.type() == typeid(int)) {
64 ++intEncCount;
65 FollyToStringSerializer<int>().encode(value, std::move(appender));
66 } else if (value.type() == typeid(double)) {
67 ++dblEncCount;
68 FollyToStringSerializer<double>().encode(value, std::move(appender));
69 } else {
70 folly::throw_exception<std::bad_any_cast>();
71 }
72 }
73
shortThriftType(int ordinal)74 ThriftTypeInfo shortThriftType(int ordinal) {
75 ThriftTypeInfo type;
76 type.set_uri(fmt::format("s.r/t/{}", ordinal));
77 assert(type.get_uri().size() <= kMinTypeHashBytes);
78 return type;
79 }
80
longThriftType(int ordinal)81 ThriftTypeInfo longThriftType(int ordinal) {
82 ThriftTypeInfo type;
83 type.set_uri(
84 fmt::format("seriously.long.type/seriously/long/type/{}", ordinal));
85 assert(
86 type.get_uri().size() >
87 size_t(getUniversalHashSize(type::UniversalHashAlgorithm::Sha2_256)));
88 return type;
89 }
90
decode(const std::type_info & typeInfo,folly::io::Cursor & cursor,any_ref value) const91 void MultiSerializer::decode(
92 const std::type_info& typeInfo,
93 folly::io::Cursor& cursor,
94 any_ref value) const {
95 if (value.type() == typeid(std::any)) {
96 // It is being decoded into an any.
97 ++anyDecCount;
98 }
99 if (typeInfo == typeid(int)) {
100 ++intDecCount;
101 FollyToStringSerializer<int>().decode(typeInfo, cursor, value);
102 } else if (typeInfo == typeid(double)) {
103 ++dblDecCount;
104 FollyToStringSerializer<double>().decode(typeInfo, cursor, value);
105 } else {
106 folly::throw_exception<std::bad_any_cast>();
107 }
108 }
109
checkAndResetInt(size_t enc,size_t dec) const110 void MultiSerializer::checkAndResetInt(size_t enc, size_t dec) const {
111 EXPECT_EQ(intEncCount, enc);
112 EXPECT_EQ(intDecCount, dec);
113 intEncCount = 0;
114 intDecCount = 0;
115 }
checkAndResetDbl(size_t enc,size_t dec) const116 void MultiSerializer::checkAndResetDbl(size_t enc, size_t dec) const {
117 EXPECT_EQ(dblEncCount, enc);
118 EXPECT_EQ(dblDecCount, dec);
119 dblEncCount = 0;
120 dblDecCount = 0;
121 }
checkAndResetAny(size_t dec) const122 void MultiSerializer::checkAndResetAny(size_t dec) const {
123 EXPECT_EQ(anyDecCount, dec);
124 anyDecCount = 0;
125 }
checkAndResetAll() const126 void MultiSerializer::checkAndResetAll() const {
127 checkAndResetInt(0, 0);
128 checkAndResetDbl(0, 0);
129 checkAndResetAny(0);
130 }
checkAnyDec() const131 void MultiSerializer::checkAnyDec() const {
132 checkAndResetAny(1);
133 checkAndResetAll();
134 }
checkIntEnc() const135 void MultiSerializer::checkIntEnc() const {
136 checkAndResetInt(1, 0);
137 checkAndResetAll();
138 }
checkIntDec() const139 void MultiSerializer::checkIntDec() const {
140 checkAndResetInt(0, 1);
141 checkAndResetAll();
142 }
checkDblEnc() const143 void MultiSerializer::checkDblEnc() const {
144 checkAndResetDbl(1, 0);
145 checkAndResetAll();
146 }
checkDblDec() const147 void MultiSerializer::checkDblDec() const {
148 checkAndResetDbl(0, 1);
149 checkAndResetAll();
150 }
checkAnyIntDec() const151 void MultiSerializer::checkAnyIntDec() const {
152 checkAndResetAny(1);
153 checkAndResetInt(0, 1);
154 checkAndResetAll();
155 }
checkAnyDblDec() const156 void MultiSerializer::checkAnyDblDec() const {
157 checkAndResetAny(1);
158 checkAndResetDbl(0, 1);
159 checkAndResetAll();
160 }
161
162 } // namespace apache::thrift::conformance
163