blob: cb98917d3ea7cb69e297a503a931d15e1983643c [file] [log] [blame]
David Reisse4d4ea02009-04-02 21:37:17 +00001/*
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
Roger Meier33eaa0f2012-04-13 09:13:13 +000023#include <limits>
David Reisse4d4ea02009-04-02 21:37:17 +000024
Roger Meier49ff8b12012-04-13 09:12:31 +000025#include <thrift/protocol/TBinaryProtocol.h>
26#include <thrift/transport/TBufferTransports.h>
27#include <thrift/Thrift.h>
Carel Combrink3da784b2025-05-15 12:22:37 +000028#include <thrift/TUuid.h>
David Reisse4d4ea02009-04-02 21:37:17 +000029
30#include "GenericHelpers.h"
31
cyy316723a2019-01-05 16:35:14 +080032using std::shared_ptr;
David Reisse4d4ea02009-04-02 21:37:17 +000033using namespace apache::thrift;
34using namespace apache::thrift::protocol;
35using namespace apache::thrift::transport;
36
37#define ERR_LEN 512
38extern char errorMessage[ERR_LEN];
39
40template <typename TProto, typename Val>
41void testNaked(Val val) {
42 shared_ptr<TTransport> transport(new TMemoryBuffer());
43 shared_ptr<TProtocol> protocol(new TProto(transport));
44
45 GenericIO::write(protocol, val);
46 Val out;
47 GenericIO::read(protocol, out);
48 if (out != val) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010049 THRIFT_SNPRINTF(errorMessage,
50 ERR_LEN,
51 "Invalid naked test (type: %s)",
52 ClassNames::getName<Val>());
David Reisse4d4ea02009-04-02 21:37:17 +000053 throw TException(errorMessage);
54 }
55}
56
57template <typename TProto, TType type, typename Val>
58void testField(const Val val) {
59 shared_ptr<TTransport> transport(new TMemoryBuffer());
60 shared_ptr<TProtocol> protocol(new TProto(transport));
61
62 protocol->writeStructBegin("test_struct");
63 protocol->writeFieldBegin("test_field", type, (int16_t)15);
64
65 GenericIO::write(protocol, val);
66
67 protocol->writeFieldEnd();
68 protocol->writeStructEnd();
69
70 std::string name;
71 TType fieldType;
72 int16_t fieldId;
73
74 protocol->readStructBegin(name);
75 protocol->readFieldBegin(name, fieldType, fieldId);
76
77 if (fieldId != 15) {
Jake Farrell5d02b802014-01-07 21:42:01 -050078 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid ID (type: %s)", typeid(val).name());
David Reisse4d4ea02009-04-02 21:37:17 +000079 throw TException(errorMessage);
80 }
81 if (fieldType != type) {
Jake Farrell5d02b802014-01-07 21:42:01 -050082 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid Field Type (type: %s)", typeid(val).name());
David Reisse4d4ea02009-04-02 21:37:17 +000083 throw TException(errorMessage);
84 }
85
86 Val out;
87 GenericIO::read(protocol, out);
88
89 if (out != val) {
Jake Farrell5d02b802014-01-07 21:42:01 -050090 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid value read (type: %s)", typeid(val).name());
David Reisse4d4ea02009-04-02 21:37:17 +000091 throw TException(errorMessage);
92 }
93
94 protocol->readFieldEnd();
95 protocol->readStructEnd();
96}
97
98template <typename TProto>
99void testMessage() {
100 struct TMessage {
101 const char* name;
102 TMessageType type;
103 int32_t seqid;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100104 } messages[] = {{"short message name", T_CALL, 0},
105 {"1", T_REPLY, 12345},
106 {"loooooooooooooooooooooooooooooooooong", T_EXCEPTION, 1 << 16},
107 {"one way push", T_ONEWAY, 12},
108 {"Janky", T_CALL, 0}};
Jens Geyera86886e2014-09-17 22:25:48 +0200109 const int messages_count = sizeof(messages) / sizeof(TMessage);
David Reisse4d4ea02009-04-02 21:37:17 +0000110
Jens Geyera86886e2014-09-17 22:25:48 +0200111 for (int i = 0; i < messages_count; i++) {
David Reisse4d4ea02009-04-02 21:37:17 +0000112 shared_ptr<TTransport> transport(new TMemoryBuffer());
113 shared_ptr<TProtocol> protocol(new TProto(transport));
114
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100115 protocol->writeMessageBegin(messages[i].name, messages[i].type, messages[i].seqid);
David Reisse4d4ea02009-04-02 21:37:17 +0000116 protocol->writeMessageEnd();
117
118 std::string name;
119 TMessageType type;
120 int32_t seqid;
121
122 protocol->readMessageBegin(name, type, seqid);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100123 if (name != messages[i].name || type != messages[i].type || seqid != messages[i].seqid) {
David Reisse4d4ea02009-04-02 21:37:17 +0000124 throw TException("readMessageBegin failed.");
125 }
126 }
127}
128
129template <typename TProto>
130void testProtocol(const char* protoname) {
131 try {
132 testNaked<TProto, int8_t>((int8_t)123);
133
134 for (int32_t i = 0; i < 128; i++) {
135 testField<TProto, T_BYTE, int8_t>((int8_t)i);
136 testField<TProto, T_BYTE, int8_t>((int8_t)-i);
137 }
138
139 testNaked<TProto, int16_t>((int16_t)0);
140 testNaked<TProto, int16_t>((int16_t)1);
141 testNaked<TProto, int16_t>((int16_t)15000);
142 testNaked<TProto, int16_t>((int16_t)0x7fff);
143 testNaked<TProto, int16_t>((int16_t)-1);
144 testNaked<TProto, int16_t>((int16_t)-15000);
145 testNaked<TProto, int16_t>((int16_t)-0x7fff);
Jake Farrell5d02b802014-01-07 21:42:01 -0500146 testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::min)());
147 testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::max)());
David Reisse4d4ea02009-04-02 21:37:17 +0000148
149 testField<TProto, T_I16, int16_t>((int16_t)0);
150 testField<TProto, T_I16, int16_t>((int16_t)1);
151 testField<TProto, T_I16, int16_t>((int16_t)7);
152 testField<TProto, T_I16, int16_t>((int16_t)150);
153 testField<TProto, T_I16, int16_t>((int16_t)15000);
154 testField<TProto, T_I16, int16_t>((int16_t)0x7fff);
155 testField<TProto, T_I16, int16_t>((int16_t)-1);
156 testField<TProto, T_I16, int16_t>((int16_t)-7);
157 testField<TProto, T_I16, int16_t>((int16_t)-150);
158 testField<TProto, T_I16, int16_t>((int16_t)-15000);
159 testField<TProto, T_I16, int16_t>((int16_t)-0x7fff);
160
161 testNaked<TProto, int32_t>(0);
162 testNaked<TProto, int32_t>(1);
163 testNaked<TProto, int32_t>(15000);
164 testNaked<TProto, int32_t>(0xffff);
165 testNaked<TProto, int32_t>(-1);
166 testNaked<TProto, int32_t>(-15000);
167 testNaked<TProto, int32_t>(-0xffff);
Jake Farrell5d02b802014-01-07 21:42:01 -0500168 testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::min)());
169 testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::max)());
David Reisse4d4ea02009-04-02 21:37:17 +0000170
171 testField<TProto, T_I32, int32_t>(0);
172 testField<TProto, T_I32, int32_t>(1);
173 testField<TProto, T_I32, int32_t>(7);
174 testField<TProto, T_I32, int32_t>(150);
175 testField<TProto, T_I32, int32_t>(15000);
176 testField<TProto, T_I32, int32_t>(31337);
177 testField<TProto, T_I32, int32_t>(0xffff);
178 testField<TProto, T_I32, int32_t>(0xffffff);
179 testField<TProto, T_I32, int32_t>(-1);
180 testField<TProto, T_I32, int32_t>(-7);
181 testField<TProto, T_I32, int32_t>(-150);
182 testField<TProto, T_I32, int32_t>(-15000);
183 testField<TProto, T_I32, int32_t>(-0xffff);
184 testField<TProto, T_I32, int32_t>(-0xffffff);
Jake Farrell5d02b802014-01-07 21:42:01 -0500185 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)());
186 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)());
187 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)() + 10);
188 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)() - 16);
189 testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::min)());
190 testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::max)());
David Reisse4d4ea02009-04-02 21:37:17 +0000191
David Reisse4d4ea02009-04-02 21:37:17 +0000192 testNaked<TProto, int64_t>(0);
193 for (int64_t i = 0; i < 62; i++) {
James E. King, III7edc8fa2017-01-20 10:11:41 -0500194 testNaked<TProto, int64_t>(1LL << i);
195 testNaked<TProto, int64_t>(-(1LL << i));
David Reisse4d4ea02009-04-02 21:37:17 +0000196 }
197
198 testField<TProto, T_I64, int64_t>(0);
199 for (int i = 0; i < 62; i++) {
James E. King, III7edc8fa2017-01-20 10:11:41 -0500200 testField<TProto, T_I64, int64_t>(1LL << i);
201 testField<TProto, T_I64, int64_t>(-(1LL << i));
David Reisse4d4ea02009-04-02 21:37:17 +0000202 }
203
204 testNaked<TProto, double>(123.456);
205
206 testNaked<TProto, std::string>("");
207 testNaked<TProto, std::string>("short");
208 testNaked<TProto, std::string>("borderlinetiny");
209 testNaked<TProto, std::string>("a bit longer than the smallest possible");
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100210 testNaked<TProto, std::string>("\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA"); // kinda binary test
David Reisse4d4ea02009-04-02 21:37:17 +0000211
Carel Combrink3da784b2025-05-15 12:22:37 +0000212 testNaked<TProto, TUuid>(TUuid("5e2ab188-1726-4e75-a04f-1ed9a6a89c4c"));
213 testField<TProto, T_UUID, TUuid>(TUuid("5e2ab188-1726-4e75-a04f-1ed9a6a89c4c"));
214
David Reisse4d4ea02009-04-02 21:37:17 +0000215 testField<TProto, T_STRING, std::string>("");
216 testField<TProto, T_STRING, std::string>("short");
217 testField<TProto, T_STRING, std::string>("borderlinetiny");
218 testField<TProto, T_STRING, std::string>("a bit longer than the smallest possible");
219
220 testMessage<TProto>();
221
222 printf("%s => OK\n", protoname);
cyy9fed9012019-01-16 14:43:51 +0800223 } catch (const TException &e) {
Jake Farrell5d02b802014-01-07 21:42:01 -0500224 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "%s => Test FAILED: %s", protoname, e.what());
David Reisse4d4ea02009-04-02 21:37:17 +0000225 throw TException(errorMessage);
226 }
227}
228
229#endif