blob: 3c98943418fccd59f37f7050bea4ed441f521971 [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>
David Reisse4d4ea02009-04-02 21:37:17 +000028
29#include "GenericHelpers.h"
30
31using boost::shared_ptr;
32using namespace apache::thrift;
33using namespace apache::thrift::protocol;
34using namespace apache::thrift::transport;
35
36#define ERR_LEN 512
37extern char errorMessage[ERR_LEN];
38
39template <typename TProto, typename Val>
40void 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) {
Jake Farrell5d02b802014-01-07 21:42:01 -050048 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid naked test (type: %s)", ClassNames::getName<Val>());
David Reisse4d4ea02009-04-02 21:37:17 +000049 throw TException(errorMessage);
50 }
51}
52
53template <typename TProto, TType type, typename Val>
54void testField(const Val val) {
55 shared_ptr<TTransport> transport(new TMemoryBuffer());
56 shared_ptr<TProtocol> protocol(new TProto(transport));
57
58 protocol->writeStructBegin("test_struct");
59 protocol->writeFieldBegin("test_field", type, (int16_t)15);
60
61 GenericIO::write(protocol, val);
62
63 protocol->writeFieldEnd();
64 protocol->writeStructEnd();
65
66 std::string name;
67 TType fieldType;
68 int16_t fieldId;
69
70 protocol->readStructBegin(name);
71 protocol->readFieldBegin(name, fieldType, fieldId);
72
73 if (fieldId != 15) {
Jake Farrell5d02b802014-01-07 21:42:01 -050074 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid ID (type: %s)", typeid(val).name());
David Reisse4d4ea02009-04-02 21:37:17 +000075 throw TException(errorMessage);
76 }
77 if (fieldType != type) {
Jake Farrell5d02b802014-01-07 21:42:01 -050078 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid Field Type (type: %s)", typeid(val).name());
David Reisse4d4ea02009-04-02 21:37:17 +000079 throw TException(errorMessage);
80 }
81
82 Val out;
83 GenericIO::read(protocol, out);
84
85 if (out != val) {
Jake Farrell5d02b802014-01-07 21:42:01 -050086 THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid value read (type: %s)", typeid(val).name());
David Reisse4d4ea02009-04-02 21:37:17 +000087 throw TException(errorMessage);
88 }
89
90 protocol->readFieldEnd();
91 protocol->readStructEnd();
92}
93
94template <typename TProto>
95void testMessage() {
96 struct TMessage {
97 const char* name;
98 TMessageType type;
99 int32_t seqid;
Jens Geyera86886e2014-09-17 22:25:48 +0200100 } messages[] = {
David Reisse4d4ea02009-04-02 21:37:17 +0000101 {"short message name", T_CALL, 0},
102 {"1", T_REPLY, 12345},
103 {"loooooooooooooooooooooooooooooooooong", T_EXCEPTION, 1 << 16},
Jens Geyera86886e2014-09-17 22:25:48 +0200104 {"one way push", T_ONEWAY, 12},
David Reisse4d4ea02009-04-02 21:37:17 +0000105 {"Janky", T_CALL, 0}
106 };
Jens Geyera86886e2014-09-17 22:25:48 +0200107 const int messages_count = sizeof(messages) / sizeof(TMessage);
David Reisse4d4ea02009-04-02 21:37:17 +0000108
Jens Geyera86886e2014-09-17 22:25:48 +0200109 for (int i = 0; i < messages_count; i++) {
David Reisse4d4ea02009-04-02 21:37:17 +0000110 shared_ptr<TTransport> transport(new TMemoryBuffer());
111 shared_ptr<TProtocol> protocol(new TProto(transport));
112
113 protocol->writeMessageBegin(messages[i].name,
114 messages[i].type,
115 messages[i].seqid);
116 protocol->writeMessageEnd();
117
118 std::string name;
119 TMessageType type;
120 int32_t seqid;
121
122 protocol->readMessageBegin(name, type, seqid);
123 if (name != messages[i].name ||
124 type != messages[i].type ||
125 seqid != messages[i].seqid) {
126 throw TException("readMessageBegin failed.");
127 }
128 }
129}
130
131template <typename TProto>
132void testProtocol(const char* protoname) {
133 try {
134 testNaked<TProto, int8_t>((int8_t)123);
135
136 for (int32_t i = 0; i < 128; i++) {
137 testField<TProto, T_BYTE, int8_t>((int8_t)i);
138 testField<TProto, T_BYTE, int8_t>((int8_t)-i);
139 }
140
141 testNaked<TProto, int16_t>((int16_t)0);
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>((int16_t)-1);
146 testNaked<TProto, int16_t>((int16_t)-15000);
147 testNaked<TProto, int16_t>((int16_t)-0x7fff);
Jake Farrell5d02b802014-01-07 21:42:01 -0500148 testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::min)());
149 testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::max)());
David Reisse4d4ea02009-04-02 21:37:17 +0000150
151 testField<TProto, T_I16, int16_t>((int16_t)0);
152 testField<TProto, T_I16, int16_t>((int16_t)1);
153 testField<TProto, T_I16, int16_t>((int16_t)7);
154 testField<TProto, T_I16, int16_t>((int16_t)150);
155 testField<TProto, T_I16, int16_t>((int16_t)15000);
156 testField<TProto, T_I16, int16_t>((int16_t)0x7fff);
157 testField<TProto, T_I16, int16_t>((int16_t)-1);
158 testField<TProto, T_I16, int16_t>((int16_t)-7);
159 testField<TProto, T_I16, int16_t>((int16_t)-150);
160 testField<TProto, T_I16, int16_t>((int16_t)-15000);
161 testField<TProto, T_I16, int16_t>((int16_t)-0x7fff);
162
163 testNaked<TProto, int32_t>(0);
164 testNaked<TProto, int32_t>(1);
165 testNaked<TProto, int32_t>(15000);
166 testNaked<TProto, int32_t>(0xffff);
167 testNaked<TProto, int32_t>(-1);
168 testNaked<TProto, int32_t>(-15000);
169 testNaked<TProto, int32_t>(-0xffff);
Jake Farrell5d02b802014-01-07 21:42:01 -0500170 testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::min)());
171 testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::max)());
David Reisse4d4ea02009-04-02 21:37:17 +0000172
173 testField<TProto, T_I32, int32_t>(0);
174 testField<TProto, T_I32, int32_t>(1);
175 testField<TProto, T_I32, int32_t>(7);
176 testField<TProto, T_I32, int32_t>(150);
177 testField<TProto, T_I32, int32_t>(15000);
178 testField<TProto, T_I32, int32_t>(31337);
179 testField<TProto, T_I32, int32_t>(0xffff);
180 testField<TProto, T_I32, int32_t>(0xffffff);
181 testField<TProto, T_I32, int32_t>(-1);
182 testField<TProto, T_I32, int32_t>(-7);
183 testField<TProto, T_I32, int32_t>(-150);
184 testField<TProto, T_I32, int32_t>(-15000);
185 testField<TProto, T_I32, int32_t>(-0xffff);
186 testField<TProto, T_I32, int32_t>(-0xffffff);
Jake Farrell5d02b802014-01-07 21:42:01 -0500187 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)());
188 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)());
189 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)() + 10);
190 testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)() - 16);
191 testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::min)());
192 testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::max)());
David Reisse4d4ea02009-04-02 21:37:17 +0000193
194
195 testNaked<TProto, int64_t>(0);
196 for (int64_t i = 0; i < 62; i++) {
197 testNaked<TProto, int64_t>(1L << i);
198 testNaked<TProto, int64_t>(-(1L << i));
199 }
200
201 testField<TProto, T_I64, int64_t>(0);
202 for (int i = 0; i < 62; i++) {
203 testField<TProto, T_I64, int64_t>(1L << i);
204 testField<TProto, T_I64, int64_t>(-(1L << i));
205 }
206
207 testNaked<TProto, double>(123.456);
208
209 testNaked<TProto, std::string>("");
210 testNaked<TProto, std::string>("short");
211 testNaked<TProto, std::string>("borderlinetiny");
212 testNaked<TProto, std::string>("a bit longer than the smallest possible");
213 testNaked<TProto, std::string>("\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA"); //kinda binary test
214
215 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);
223 } catch (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