]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | ||
20 | #ifndef _THRIFT_TEST_GENERICPROTOCOLTEST_TCC_ | |
21 | #define _THRIFT_TEST_GENERICPROTOCOLTEST_TCC_ 1 | |
22 | ||
23 | #include <limits> | |
24 | ||
25 | #include <thrift/protocol/TBinaryProtocol.h> | |
26 | #include <thrift/transport/TBufferTransports.h> | |
27 | #include <thrift/Thrift.h> | |
28 | ||
29 | #include "GenericHelpers.h" | |
30 | ||
31 | using std::shared_ptr; | |
32 | using namespace apache::thrift; | |
33 | using namespace apache::thrift::protocol; | |
34 | using namespace apache::thrift::transport; | |
35 | ||
36 | #define ERR_LEN 512 | |
37 | extern char errorMessage[ERR_LEN]; | |
38 | ||
39 | template <typename TProto, typename Val> | |
40 | void testNaked(Val val) { | |
41 | shared_ptr<TTransport> transport(new TMemoryBuffer()); | |
42 | shared_ptr<TProtocol> protocol(new TProto(transport)); | |
43 | ||
44 | GenericIO::write(protocol, val); | |
45 | Val out; | |
46 | GenericIO::read(protocol, out); | |
47 | if (out != val) { | |
48 | THRIFT_SNPRINTF(errorMessage, | |
49 | ERR_LEN, | |
50 | "Invalid naked test (type: %s)", | |
51 | ClassNames::getName<Val>()); | |
52 | throw TException(errorMessage); | |
53 | } | |
54 | } | |
55 | ||
56 | template <typename TProto, TType type, typename Val> | |
57 | void testField(const Val val) { | |
58 | shared_ptr<TTransport> transport(new TMemoryBuffer()); | |
59 | shared_ptr<TProtocol> protocol(new TProto(transport)); | |
60 | ||
61 | protocol->writeStructBegin("test_struct"); | |
62 | protocol->writeFieldBegin("test_field", type, (int16_t)15); | |
63 | ||
64 | GenericIO::write(protocol, val); | |
65 | ||
66 | protocol->writeFieldEnd(); | |
67 | protocol->writeStructEnd(); | |
68 | ||
69 | std::string name; | |
70 | TType fieldType; | |
71 | int16_t fieldId; | |
72 | ||
73 | protocol->readStructBegin(name); | |
74 | protocol->readFieldBegin(name, fieldType, fieldId); | |
75 | ||
76 | if (fieldId != 15) { | |
77 | THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid ID (type: %s)", typeid(val).name()); | |
78 | throw TException(errorMessage); | |
79 | } | |
80 | if (fieldType != type) { | |
81 | THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid Field Type (type: %s)", typeid(val).name()); | |
82 | throw TException(errorMessage); | |
83 | } | |
84 | ||
85 | Val out; | |
86 | GenericIO::read(protocol, out); | |
87 | ||
88 | if (out != val) { | |
89 | THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid value read (type: %s)", typeid(val).name()); | |
90 | throw TException(errorMessage); | |
91 | } | |
92 | ||
93 | protocol->readFieldEnd(); | |
94 | protocol->readStructEnd(); | |
95 | } | |
96 | ||
97 | template <typename TProto> | |
98 | void testMessage() { | |
99 | struct TMessage { | |
100 | const char* name; | |
101 | TMessageType type; | |
102 | int32_t seqid; | |
103 | } messages[] = {{"short message name", T_CALL, 0}, | |
104 | {"1", T_REPLY, 12345}, | |
105 | {"loooooooooooooooooooooooooooooooooong", T_EXCEPTION, 1 << 16}, | |
106 | {"one way push", T_ONEWAY, 12}, | |
107 | {"Janky", T_CALL, 0}}; | |
108 | const int messages_count = sizeof(messages) / sizeof(TMessage); | |
109 | ||
110 | for (int i = 0; i < messages_count; i++) { | |
111 | shared_ptr<TTransport> transport(new TMemoryBuffer()); | |
112 | shared_ptr<TProtocol> protocol(new TProto(transport)); | |
113 | ||
114 | protocol->writeMessageBegin(messages[i].name, messages[i].type, messages[i].seqid); | |
115 | protocol->writeMessageEnd(); | |
116 | ||
117 | std::string name; | |
118 | TMessageType type; | |
119 | int32_t seqid; | |
120 | ||
121 | protocol->readMessageBegin(name, type, seqid); | |
122 | if (name != messages[i].name || type != messages[i].type || seqid != messages[i].seqid) { | |
123 | throw TException("readMessageBegin failed."); | |
124 | } | |
125 | } | |
126 | } | |
127 | ||
128 | template <typename TProto> | |
129 | void testProtocol(const char* protoname) { | |
130 | try { | |
131 | testNaked<TProto, int8_t>((int8_t)123); | |
132 | ||
133 | for (int32_t i = 0; i < 128; i++) { | |
134 | testField<TProto, T_BYTE, int8_t>((int8_t)i); | |
135 | testField<TProto, T_BYTE, int8_t>((int8_t)-i); | |
136 | } | |
137 | ||
138 | testNaked<TProto, int16_t>((int16_t)0); | |
139 | testNaked<TProto, int16_t>((int16_t)1); | |
140 | testNaked<TProto, int16_t>((int16_t)15000); | |
141 | testNaked<TProto, int16_t>((int16_t)0x7fff); | |
142 | testNaked<TProto, int16_t>((int16_t)-1); | |
143 | testNaked<TProto, int16_t>((int16_t)-15000); | |
144 | testNaked<TProto, int16_t>((int16_t)-0x7fff); | |
145 | testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::min)()); | |
146 | testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::max)()); | |
147 | ||
148 | testField<TProto, T_I16, int16_t>((int16_t)0); | |
149 | testField<TProto, T_I16, int16_t>((int16_t)1); | |
150 | testField<TProto, T_I16, int16_t>((int16_t)7); | |
151 | testField<TProto, T_I16, int16_t>((int16_t)150); | |
152 | testField<TProto, T_I16, int16_t>((int16_t)15000); | |
153 | testField<TProto, T_I16, int16_t>((int16_t)0x7fff); | |
154 | testField<TProto, T_I16, int16_t>((int16_t)-1); | |
155 | testField<TProto, T_I16, int16_t>((int16_t)-7); | |
156 | testField<TProto, T_I16, int16_t>((int16_t)-150); | |
157 | testField<TProto, T_I16, int16_t>((int16_t)-15000); | |
158 | testField<TProto, T_I16, int16_t>((int16_t)-0x7fff); | |
159 | ||
160 | testNaked<TProto, int32_t>(0); | |
161 | testNaked<TProto, int32_t>(1); | |
162 | testNaked<TProto, int32_t>(15000); | |
163 | testNaked<TProto, int32_t>(0xffff); | |
164 | testNaked<TProto, int32_t>(-1); | |
165 | testNaked<TProto, int32_t>(-15000); | |
166 | testNaked<TProto, int32_t>(-0xffff); | |
167 | testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::min)()); | |
168 | testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::max)()); | |
169 | ||
170 | testField<TProto, T_I32, int32_t>(0); | |
171 | testField<TProto, T_I32, int32_t>(1); | |
172 | testField<TProto, T_I32, int32_t>(7); | |
173 | testField<TProto, T_I32, int32_t>(150); | |
174 | testField<TProto, T_I32, int32_t>(15000); | |
175 | testField<TProto, T_I32, int32_t>(31337); | |
176 | testField<TProto, T_I32, int32_t>(0xffff); | |
177 | testField<TProto, T_I32, int32_t>(0xffffff); | |
178 | testField<TProto, T_I32, int32_t>(-1); | |
179 | testField<TProto, T_I32, int32_t>(-7); | |
180 | testField<TProto, T_I32, int32_t>(-150); | |
181 | testField<TProto, T_I32, int32_t>(-15000); | |
182 | testField<TProto, T_I32, int32_t>(-0xffff); | |
183 | testField<TProto, T_I32, int32_t>(-0xffffff); | |
184 | testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)()); | |
185 | testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)()); | |
186 | testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)() + 10); | |
187 | testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)() - 16); | |
188 | testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::min)()); | |
189 | testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::max)()); | |
190 | ||
191 | testNaked<TProto, int64_t>(0); | |
192 | for (int64_t i = 0; i < 62; i++) { | |
193 | testNaked<TProto, int64_t>(1LL << i); | |
194 | testNaked<TProto, int64_t>(-(1LL << i)); | |
195 | } | |
196 | ||
197 | testField<TProto, T_I64, int64_t>(0); | |
198 | for (int i = 0; i < 62; i++) { | |
199 | testField<TProto, T_I64, int64_t>(1LL << i); | |
200 | testField<TProto, T_I64, int64_t>(-(1LL << i)); | |
201 | } | |
202 | ||
203 | testNaked<TProto, double>(123.456); | |
204 | ||
205 | testNaked<TProto, std::string>(""); | |
206 | testNaked<TProto, std::string>("short"); | |
207 | testNaked<TProto, std::string>("borderlinetiny"); | |
208 | testNaked<TProto, std::string>("a bit longer than the smallest possible"); | |
209 | testNaked<TProto, std::string>("\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA"); // kinda binary test | |
210 | ||
211 | testField<TProto, T_STRING, std::string>(""); | |
212 | testField<TProto, T_STRING, std::string>("short"); | |
213 | testField<TProto, T_STRING, std::string>("borderlinetiny"); | |
214 | testField<TProto, T_STRING, std::string>("a bit longer than the smallest possible"); | |
215 | ||
216 | testMessage<TProto>(); | |
217 | ||
218 | printf("%s => OK\n", protoname); | |
219 | } catch (const TException &e) { | |
220 | THRIFT_SNPRINTF(errorMessage, ERR_LEN, "%s => Test FAILED: %s", protoname, e.what()); | |
221 | throw TException(errorMessage); | |
222 | } | |
223 | } | |
224 | ||
225 | #endif |