blob: a5a31156faf047c063dc676f5a282eb41a7c2bf1 [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
23#include <limits>
24
25#include <protocol/TBinaryProtocol.h>
26#include <transport/TBufferTransports.h>
27#include <Thrift.h>
28
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) {
48 snprintf(errorMessage, ERR_LEN, "Invalid naked test (type: %s)", ClassNames::getName<Val>());
49 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) {
74 snprintf(errorMessage, ERR_LEN, "Invalid ID (type: %s)", typeid(val).name());
75 throw TException(errorMessage);
76 }
77 if (fieldType != type) {
78 snprintf(errorMessage, ERR_LEN, "Invalid Field Type (type: %s)", typeid(val).name());
79 throw TException(errorMessage);
80 }
81
82 Val out;
83 GenericIO::read(protocol, out);
84
85 if (out != val) {
86 snprintf(errorMessage, ERR_LEN, "Invalid value read (type: %s)", typeid(val).name());
87 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;
100 } messages[4] = {
101 {"short message name", T_CALL, 0},
102 {"1", T_REPLY, 12345},
103 {"loooooooooooooooooooooooooooooooooong", T_EXCEPTION, 1 << 16},
104 {"Janky", T_CALL, 0}
105 };
106
107 for (int i = 0; i < 4; i++) {
108 shared_ptr<TTransport> transport(new TMemoryBuffer());
109 shared_ptr<TProtocol> protocol(new TProto(transport));
110
111 protocol->writeMessageBegin(messages[i].name,
112 messages[i].type,
113 messages[i].seqid);
114 protocol->writeMessageEnd();
115
116 std::string name;
117 TMessageType type;
118 int32_t seqid;
119
120 protocol->readMessageBegin(name, type, seqid);
121 if (name != messages[i].name ||
122 type != messages[i].type ||
123 seqid != messages[i].seqid) {
124 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);
146 testNaked<TProto, int16_t>(std::numeric_limits<int16_t>::min());
147 testNaked<TProto, int16_t>(std::numeric_limits<int16_t>::max());
148
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);
168 testNaked<TProto, int32_t>(std::numeric_limits<int32_t>::min());
169 testNaked<TProto, int32_t>(std::numeric_limits<int32_t>::max());
170
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);
185 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());
191
192
193 testNaked<TProto, int64_t>(0);
194 for (int64_t i = 0; i < 62; i++) {
195 testNaked<TProto, int64_t>(1L << i);
196 testNaked<TProto, int64_t>(-(1L << i));
197 }
198
199 testField<TProto, T_I64, int64_t>(0);
200 for (int i = 0; i < 62; i++) {
201 testField<TProto, T_I64, int64_t>(1L << i);
202 testField<TProto, T_I64, int64_t>(-(1L << i));
203 }
204
205 testNaked<TProto, double>(123.456);
206
207 testNaked<TProto, std::string>("");
208 testNaked<TProto, std::string>("short");
209 testNaked<TProto, std::string>("borderlinetiny");
210 testNaked<TProto, std::string>("a bit longer than the smallest possible");
211 testNaked<TProto, std::string>("\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA"); //kinda binary test
212
213 testField<TProto, T_STRING, std::string>("");
214 testField<TProto, T_STRING, std::string>("short");
215 testField<TProto, T_STRING, std::string>("borderlinetiny");
216 testField<TProto, T_STRING, std::string>("a bit longer than the smallest possible");
217
218 testMessage<TProto>();
219
220 printf("%s => OK\n", protoname);
221 } catch (TException e) {
222 snprintf(errorMessage, ERR_LEN, "%s => Test FAILED: %s", protoname, e.what());
223 throw TException(errorMessage);
224 }
225}
226
227#endif