Subversion Repositories SmartDukaan

Rev

Rev 30 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 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
/*
21
../compiler/cpp/thrift --gen cpp:dense DebugProtoTest.thrift
22
../compiler/cpp/thrift --gen cpp:dense OptionalRequiredTest.thrift
23
g++ -Wall -g -I../lib/cpp/src -I/usr/local/include/boost-1_33_1 \
24
  gen-cpp/OptionalRequiredTest_types.cpp \
25
  gen-cpp/DebugProtoTest_types.cpp \
26
  DenseProtoTest.cpp ../lib/cpp/.libs/libthrift.a -o DenseProtoTest
27
./DenseProtoTest
28
*/
29
 
30
// I do this to reach into the guts of TDenseProtocol.  Sorry.
31
#define private public
32
#define inline
33
 
34
#undef NDEBUG
35
#include <cstdlib>
36
#include <cassert>
37
#include <iostream>
38
#include <cmath>
39
#include <string>
40
#include "gen-cpp/DebugProtoTest_types.h"
41
#include "gen-cpp/OptionalRequiredTest_types.h"
42
#include <protocol/TDenseProtocol.h>
43
#include <transport/TBufferTransports.h>
44
 
45
 
46
// Can't use memcmp here.  GCC is too smart.
47
bool my_memeq(const char* str1, const char* str2, int len) {
48
  for (int i = 0; i < len; i++) {
49
    if (str1[i] != str2[i]) {
50
      return false;
51
    }
52
  }
53
  return true;
54
}
55
 
56
 
57
int main() {
58
  using std::string;
59
  using std::cout;
60
  using std::endl;
61
  using boost::shared_ptr;
62
  using namespace thrift::test::debug;
63
  using namespace apache::thrift::transport;
64
  using namespace apache::thrift::protocol;
65
 
66
 
67
  OneOfEach ooe;
68
  ooe.im_true   = true;
69
  ooe.im_false  = false;
70
  ooe.a_bite    = 0xd6;
71
  ooe.integer16 = 27000;
72
  ooe.integer32 = 1<<24;
73
  ooe.integer64 = (uint64_t)6000 * 1000 * 1000;
74
  ooe.double_precision = M_PI;
75
  ooe.some_characters  = "Debug THIS!";
76
  ooe.zomg_unicode     = "\xd7\n\a\t";
77
 
78
  //cout << apache::thrift::ThriftDebugString(ooe) << endl << endl;
79
 
80
 
81
  Nesting n;
82
  n.my_ooe = ooe;
83
  n.my_ooe.integer16 = 16;
84
  n.my_ooe.integer32 = 32;
85
  n.my_ooe.integer64 = 64;
86
  n.my_ooe.double_precision = (std::sqrt(5)+1)/2;
87
  n.my_ooe.some_characters  = ":R (me going \"rrrr\")";
88
  n.my_ooe.zomg_unicode     = "\xd3\x80\xe2\x85\xae\xce\x9d\x20"
89
                              "\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"
90
                              "\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80\xbc";
91
  n.my_bonk.type    = 31337;
92
  n.my_bonk.message = "I am a bonk... xor!";
93
 
94
  //cout << apache::thrift::ThriftDebugString(n) << endl << endl;
95
 
96
 
97
  HolyMoley hm;
98
 
99
  hm.big.push_back(ooe);
100
  hm.big.push_back(n.my_ooe);
101
  hm.big[0].a_bite = 0x22;
102
  hm.big[1].a_bite = 0x33;
103
 
104
  std::vector<std::string> stage1;
105
  stage1.push_back("and a one");
106
  stage1.push_back("and a two");
107
  hm.contain.insert(stage1);
108
  stage1.clear();
109
  stage1.push_back("then a one, two");
110
  stage1.push_back("three!");
111
  stage1.push_back("FOUR!!");
112
  hm.contain.insert(stage1);
113
  stage1.clear();
114
  hm.contain.insert(stage1);
115
 
116
  std::vector<Bonk> stage2;
117
  hm.bonks["nothing"] = stage2;
118
  stage2.resize(stage2.size()+1);
119
  stage2.back().type = 1;
120
  stage2.back().message = "Wait.";
121
  stage2.resize(stage2.size()+1);
122
  stage2.back().type = 2;
123
  stage2.back().message = "What?";
124
  hm.bonks["something"] = stage2;
125
  stage2.clear();
126
  stage2.resize(stage2.size()+1);
127
  stage2.back().type = 3;
128
  stage2.back().message = "quoth";
129
  stage2.resize(stage2.size()+1);
130
  stage2.back().type = 4;
131
  stage2.back().message = "the raven";
132
  stage2.resize(stage2.size()+1);
133
  stage2.back().type = 5;
134
  stage2.back().message = "nevermore";
135
  hm.bonks["poe"] = stage2;
136
 
137
  //cout << apache::thrift::ThriftDebugString(hm) << endl << endl;
138
 
139
  shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
140
  shared_ptr<TDenseProtocol> proto(new TDenseProtocol(buffer));
141
  proto->setTypeSpec(HolyMoley::local_reflection);
142
 
143
  hm.write(proto.get());
144
  HolyMoley hm2;
145
  hm2.read(proto.get());
146
 
147
  assert(hm == hm2);
148
 
149
 
150
  // Let's test out the variable-length ints, shall we?
151
  uint64_t vlq;
152
  #define checkout(i, c) { \
153
    buffer->resetBuffer(); \
154
    proto->vlqWrite(i); \
155
    proto->getTransport()->flush(); \
156
    assert(my_memeq(buffer->getBufferAsString().data(), c, sizeof(c)-1)); \
157
    proto->vlqRead(vlq); \
158
    assert(vlq == i); \
159
  }
160
 
161
  checkout(0x00000000, "\x00");
162
  checkout(0x00000040, "\x40");
163
  checkout(0x0000007F, "\x7F");
164
  checkout(0x00000080, "\x81\x00");
165
  checkout(0x00002000, "\xC0\x00");
166
  checkout(0x00003FFF, "\xFF\x7F");
167
  checkout(0x00004000, "\x81\x80\x00");
168
  checkout(0x00100000, "\xC0\x80\x00");
169
  checkout(0x001FFFFF, "\xFF\xFF\x7F");
170
  checkout(0x00200000, "\x81\x80\x80\x00");
171
  checkout(0x08000000, "\xC0\x80\x80\x00");
172
  checkout(0x0FFFFFFF, "\xFF\xFF\xFF\x7F");
173
  checkout(0x10000000, "\x81\x80\x80\x80\x00");
174
  checkout(0x20000000, "\x82\x80\x80\x80\x00");
175
  checkout(0x1FFFFFFF, "\x81\xFF\xFF\xFF\x7F");
176
  checkout(0xFFFFFFFF, "\x8F\xFF\xFF\xFF\x7F");
177
 
178
  checkout(0x0000000100000000ull, "\x90\x80\x80\x80\x00");
179
  checkout(0x0000000200000000ull, "\xA0\x80\x80\x80\x00");
180
  checkout(0x0000000300000000ull, "\xB0\x80\x80\x80\x00");
181
  checkout(0x0000000700000000ull, "\xF0\x80\x80\x80\x00");
182
  checkout(0x00000007F0000000ull, "\xFF\x80\x80\x80\x00");
183
  checkout(0x00000007FFFFFFFFull, "\xFF\xFF\xFF\xFF\x7F");
184
  checkout(0x0000000800000000ull, "\x81\x80\x80\x80\x80\x00");
185
  checkout(0x1FFFFFFFFFFFFFFFull, "\x9F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F");
186
  checkout(0x7FFFFFFFFFFFFFFFull, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F");
187
  checkout(0xFFFFFFFFFFFFFFFFull, "\x81\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F");
188
 
189
  // Test out the slow path with a TBufferedTransport.
190
  shared_ptr<TBufferedTransport> buff_trans(new TBufferedTransport(buffer, 3));
191
  proto.reset(new TDenseProtocol(buff_trans));
192
  checkout(0x0000000100000000ull, "\x90\x80\x80\x80\x00");
193
  checkout(0x0000000200000000ull, "\xA0\x80\x80\x80\x00");
194
  checkout(0x0000000300000000ull, "\xB0\x80\x80\x80\x00");
195
  checkout(0x0000000700000000ull, "\xF0\x80\x80\x80\x00");
196
  checkout(0x00000007F0000000ull, "\xFF\x80\x80\x80\x00");
197
  checkout(0x00000007FFFFFFFFull, "\xFF\xFF\xFF\xFF\x7F");
198
  checkout(0x0000000800000000ull, "\x81\x80\x80\x80\x80\x00");
199
  checkout(0x1FFFFFFFFFFFFFFFull, "\x9F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F");
200
  checkout(0x7FFFFFFFFFFFFFFFull, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F");
201
  checkout(0xFFFFFFFFFFFFFFFFull, "\x81\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F");
202
 
203
  // Test optional stuff.
204
  proto.reset(new TDenseProtocol(buffer));
205
  proto->setTypeSpec(ManyOpt::local_reflection);
206
  ManyOpt mo1, mo2, mo3, mo4, mo5, mo6;
207
  mo1.opt1 = 923759347;
208
  mo1.opt2 = 392749274;
209
  mo1.opt3 = 395739402;
210
  mo1.def4 = 294730928;
211
  mo1.opt5 = 394309218;
212
  mo1.opt6 = 832194723;
213
  mo1.__isset.opt1 = true;
214
  mo1.__isset.opt2 = true;
215
  mo1.__isset.opt3 = true;
216
  mo1.__isset.def4 = true;
217
  mo1.__isset.opt5 = true;
218
  mo1.__isset.opt6 = true;
219
 
220
  mo1.write(proto.get());
221
  mo2.read(proto.get());
222
 
223
  assert(mo2.__isset.opt1 == true);
224
  assert(mo2.__isset.opt2 == true);
225
  assert(mo2.__isset.opt3 == true);
226
  assert(mo2.__isset.def4 == true);
227
  assert(mo2.__isset.opt5 == true);
228
  assert(mo2.__isset.opt6 == true);
229
 
230
  assert(mo1 == mo2);
231
 
232
  mo1.__isset.opt1 = false;
233
  mo1.__isset.opt3 = false;
234
  mo1.__isset.opt5 = false;
235
 
236
  mo1.write(proto.get());
237
  mo3.read(proto.get());
238
 
239
  assert(mo3.__isset.opt1 == false);
240
  assert(mo3.__isset.opt2 == true);
241
  assert(mo3.__isset.opt3 == false);
242
  assert(mo3.__isset.def4 == true);
243
  assert(mo3.__isset.opt5 == false);
244
  assert(mo3.__isset.opt6 == true);
245
 
246
  assert(mo1 == mo3);
247
 
248
  mo1.__isset.opt1 = true;
249
  mo1.__isset.opt3 = true;
250
  mo1.__isset.opt5 = true;
251
  mo1.__isset.opt2 = false;
252
  mo1.__isset.opt6 = false;
253
 
254
  mo1.write(proto.get());
255
  mo4.read(proto.get());
256
 
257
  assert(mo4.__isset.opt1 == true);
258
  assert(mo4.__isset.opt2 == false);
259
  assert(mo4.__isset.opt3 == true);
260
  assert(mo4.__isset.def4 == true);
261
  assert(mo4.__isset.opt5 == true);
262
  assert(mo4.__isset.opt6 == false);
263
 
264
  assert(mo1 == mo4);
265
 
266
  mo1.__isset.opt1 = false;
267
  mo1.__isset.opt5 = false;
268
 
269
  mo1.write(proto.get());
270
  mo5.read(proto.get());
271
 
272
  assert(mo5.__isset.opt1 == false);
273
  assert(mo5.__isset.opt2 == false);
274
  assert(mo5.__isset.opt3 == true);
275
  assert(mo5.__isset.def4 == true);
276
  assert(mo5.__isset.opt5 == false);
277
  assert(mo5.__isset.opt6 == false);
278
 
279
  assert(mo1 == mo5);
280
 
281
  mo1.__isset.opt3 = false;
282
 
283
  mo1.write(proto.get());
284
  mo6.read(proto.get());
285
 
286
  assert(mo6.__isset.opt1 == false);
287
  assert(mo6.__isset.opt2 == false);
288
  assert(mo6.__isset.opt3 == false);
289
  assert(mo6.__isset.def4 == true);
290
  assert(mo6.__isset.opt5 == false);
291
  assert(mo6.__isset.opt6 == false);
292
 
293
  assert(mo1 == mo6);
294
 
295
 
296
  // Test fingerprint checking stuff.
297
 
298
  {
299
    // Default and required have the same fingerprint.
300
    Tricky1 t1;
301
    Tricky3 t3;
302
    assert(string(Tricky1::ascii_fingerprint) == Tricky3::ascii_fingerprint);
303
    proto->setTypeSpec(Tricky1::local_reflection);
304
    t1.im_default = 227;
305
    t1.write(proto.get());
306
    proto->setTypeSpec(Tricky3::local_reflection);
307
    t3.read(proto.get());
308
    assert(t3.im_required == 227);
309
  }
310
 
311
  {
312
    // Optional changes things.
313
    Tricky1 t1;
314
    Tricky2 t2;
315
    assert(string(Tricky1::ascii_fingerprint) != Tricky2::ascii_fingerprint);
316
    proto->setTypeSpec(Tricky1::local_reflection);
317
    t1.im_default = 227;
318
    t1.write(proto.get());
319
    try {
320
      proto->setTypeSpec(Tricky2::local_reflection);
321
      t2.read(proto.get());
322
      assert(false);
323
    } catch (TProtocolException& ex) {
324
      buffer->resetBuffer();
325
    }
326
  }
327
 
328
  {
329
    // Holy cow.  We can use the Tricky1 typespec with the Tricky2 structure.
330
    Tricky1 t1;
331
    Tricky2 t2;
332
    proto->setTypeSpec(Tricky1::local_reflection);
333
    t1.im_default = 227;
334
    t1.write(proto.get());
335
    t2.read(proto.get());
336
    assert(t2.__isset.im_optional == true);
337
    assert(t2.im_optional == 227);
338
  }
339
 
340
  {
341
    // And totally off the wall.
342
    Tricky1 t1;
343
    OneOfEach ooe2;
344
    assert(string(Tricky1::ascii_fingerprint) != OneOfEach::ascii_fingerprint);
345
    proto->setTypeSpec(Tricky1::local_reflection);
346
    t1.im_default = 227;
347
    t1.write(proto.get());
348
    try {
349
      proto->setTypeSpec(OneOfEach::local_reflection);
350
      ooe2.read(proto.get());
351
      assert(false);
352
    } catch (TProtocolException& ex) {
353
      buffer->resetBuffer();
354
    }
355
  }
356
 
357
  // Okay, this is really off the wall.
358
  // Just don't crash.
359
  cout << "Starting fuzz test.  This takes a while.  (20 dots.)" << endl;
360
  std::srand(12345);
361
  for (int i = 0; i < 2000; i++) {
362
    if (i % 100 == 0) {
363
      cout << ".";
364
      cout.flush();
365
    }
366
    buffer->resetBuffer();
367
    // Make sure the fingerprint prefix is right.
368
    buffer->write(Nesting::binary_fingerprint, 4);
369
    for (int j = 0; j < 1024*1024; j++) {
370
      uint8_t r = std::rand();
371
      buffer->write(&r, 1);
372
    }
373
    Nesting n;
374
    proto->setTypeSpec(OneOfEach::local_reflection);
375
    try {
376
      n.read(proto.get());
377
    } catch (TProtocolException& ex) {
378
    } catch (TTransportException& ex) {
379
    }
380
  }
381
  cout << endl;
382
 
383
  return 0;
384
}