blob: 274a243913cf29a0954a8a42faa7d2e358ba755f [file] [log] [blame]
David Reissfaebedd2007-09-17 23:20:38 +00001/*
David Reissea2cba82009-03-30 21:35:00 +00002 * 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
David Reiss9a961e72010-10-06 17:10:23 +000020#ifndef _GNU_SOURCE
21#define _GNU_SOURCE // needed for getopt_long
22#endif
23
James E. King, III07f59972017-03-10 06:18:33 -050024#if defined(_MSC_VER) && (_MSC_VER <= 1700)
James E. King, III7edc8fa2017-01-20 10:11:41 -050025// polynomial and std::fill_t warning happens in MSVC 2010, 2013, maybe others
26// https://svn.boost.org/trac/boost/ticket/11426
27#pragma warning(disable:4996)
28#endif
29
30#ifdef HAVE_STDINT_H
David Reiss3cc9dab2010-10-06 17:10:21 +000031#include <stdint.h>
James E. King, III7edc8fa2017-01-20 10:11:41 -050032#endif
Jim King9de9b1f2015-04-30 16:03:34 -040033#ifdef HAVE_INTTYPES_H
David Reiss3cc9dab2010-10-06 17:10:21 +000034#include <inttypes.h>
Jim King9de9b1f2015-04-30 16:03:34 -040035#endif
David Reissfaebedd2007-09-17 23:20:38 +000036#include <cstddef>
David Reissfaebedd2007-09-17 23:20:38 +000037#include <fstream>
38#include <iostream>
cyy316723a2019-01-05 16:35:14 +080039#include <memory>
David Reiss3cc9dab2010-10-06 17:10:21 +000040
41#include <boost/random.hpp>
David Reiss9a961e72010-10-06 17:10:23 +000042#include <boost/shared_array.hpp>
43#include <boost/test/unit_test.hpp>
Konrad Grochowskie9bdb412015-09-25 20:17:36 +020044#include <boost/version.hpp>
David Reiss3cc9dab2010-10-06 17:10:21 +000045
Roger Meier49ff8b12012-04-13 09:12:31 +000046#include <thrift/transport/TBufferTransports.h>
47#include <thrift/transport/TZlibTransport.h>
David Reissfaebedd2007-09-17 23:20:38 +000048
David Reiss9a961e72010-10-06 17:10:23 +000049using namespace apache::thrift::transport;
cyy316723a2019-01-05 16:35:14 +080050using std::shared_ptr;
James E. King, III82ae9572017-08-05 12:23:54 -040051using std::string;
David Reiss9a961e72010-10-06 17:10:23 +000052
David Reissf2abcf92010-10-06 17:10:24 +000053boost::mt19937 rng;
David Reissfaebedd2007-09-17 23:20:38 +000054
David Reissf2abcf92010-10-06 17:10:24 +000055/*
56 * Utility code
57 */
David Reissfaebedd2007-09-17 23:20:38 +000058
David Reissf2abcf92010-10-06 17:10:24 +000059class SizeGenerator {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010060public:
Sebastian Zenker042580f2019-01-29 15:48:12 +010061 virtual ~SizeGenerator() = default;
David Reissf2abcf92010-10-06 17:10:24 +000062 virtual unsigned int getSize() = 0;
David Reissfaebedd2007-09-17 23:20:38 +000063};
64
David Reissf2abcf92010-10-06 17:10:24 +000065class ConstantSizeGenerator : public SizeGenerator {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010066public:
David Reissf2abcf92010-10-06 17:10:24 +000067 ConstantSizeGenerator(unsigned int value) : value_(value) {}
Sebastian Zenker042580f2019-01-29 15:48:12 +010068 unsigned int getSize() override { return value_; }
David Reissf2abcf92010-10-06 17:10:24 +000069
Konrad Grochowski16a23a62014-11-13 15:33:38 +010070private:
David Reissf2abcf92010-10-06 17:10:24 +000071 unsigned int value_;
72};
73
74class LogNormalSizeGenerator : public SizeGenerator {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010075public:
76 LogNormalSizeGenerator(double mean, double std_dev)
77 : gen_(rng, boost::lognormal_distribution<double>(mean, std_dev)) {}
David Reissf2abcf92010-10-06 17:10:24 +000078
Sebastian Zenker042580f2019-01-29 15:48:12 +010079 unsigned int getSize() override {
David Reissf2abcf92010-10-06 17:10:24 +000080 // Loop until we get a size of 1 or more
81 while (true) {
Sebastian Zenker042580f2019-01-29 15:48:12 +010082 auto value = static_cast<unsigned int>(gen_());
David Reissf2abcf92010-10-06 17:10:24 +000083 if (value >= 1) {
84 return value;
85 }
86 }
87 }
88
Konrad Grochowski16a23a62014-11-13 15:33:38 +010089private:
90 boost::variate_generator<boost::mt19937, boost::lognormal_distribution<double> > gen_;
David Reissf2abcf92010-10-06 17:10:24 +000091};
David Reiss3cc9dab2010-10-06 17:10:21 +000092
Jim King7848d882015-04-06 21:38:06 -040093boost::shared_array<uint8_t> gen_uniform_buffer(uint32_t buf_len, uint8_t c) {
Sebastian Zenker042580f2019-01-29 15:48:12 +010094 auto* buf = new uint8_t[buf_len];
David Reiss3cc9dab2010-10-06 17:10:21 +000095 memset(buf, c, buf_len);
Jim King7848d882015-04-06 21:38:06 -040096 return boost::shared_array<uint8_t>(buf);
David Reiss3cc9dab2010-10-06 17:10:21 +000097}
98
Jim King7848d882015-04-06 21:38:06 -040099boost::shared_array<uint8_t> gen_compressible_buffer(uint32_t buf_len) {
Sebastian Zenker042580f2019-01-29 15:48:12 +0100100 auto* buf = new uint8_t[buf_len];
David Reiss3cc9dab2010-10-06 17:10:21 +0000101
102 // Generate small runs of alternately increasing and decreasing bytes
103 boost::uniform_smallint<uint32_t> run_length_distribution(1, 64);
104 boost::uniform_smallint<uint8_t> byte_distribution(0, UINT8_MAX);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100105 boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint8_t> >
106 byte_generator(rng, byte_distribution);
107 boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint32_t> >
108 run_len_generator(rng, run_length_distribution);
David Reiss3cc9dab2010-10-06 17:10:21 +0000109
110 uint32_t idx = 0;
111 int8_t step = 1;
112 while (idx < buf_len) {
113 uint32_t run_length = run_len_generator();
114 if (idx + run_length > buf_len) {
115 run_length = buf_len - idx;
116 }
117
118 uint8_t byte = byte_generator();
119 for (uint32_t n = 0; n < run_length; ++n) {
120 buf[idx] = byte;
121 ++idx;
122 byte += step;
123 }
124
125 step *= -1;
126 }
127
Jim King7848d882015-04-06 21:38:06 -0400128 return boost::shared_array<uint8_t>(buf);
David Reiss3cc9dab2010-10-06 17:10:21 +0000129}
130
Jim King7848d882015-04-06 21:38:06 -0400131boost::shared_array<uint8_t> gen_random_buffer(uint32_t buf_len) {
Sebastian Zenker042580f2019-01-29 15:48:12 +0100132 auto* buf = new uint8_t[buf_len];
David Reiss3cc9dab2010-10-06 17:10:21 +0000133
134 boost::uniform_smallint<uint8_t> distribution(0, UINT8_MAX);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100135 boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint8_t> >
136 generator(rng, distribution);
David Reiss3cc9dab2010-10-06 17:10:21 +0000137
138 for (uint32_t n = 0; n < buf_len; ++n) {
139 buf[n] = generator();
140 }
141
Jim King7848d882015-04-06 21:38:06 -0400142 return boost::shared_array<uint8_t>(buf);
David Reiss3cc9dab2010-10-06 17:10:21 +0000143}
David Reissfaebedd2007-09-17 23:20:38 +0000144
David Reissf2abcf92010-10-06 17:10:24 +0000145/*
146 * Test functions
147 */
148
Jim King7848d882015-04-06 21:38:06 -0400149void test_write_then_read(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
James E. King, III82ae9572017-08-05 12:23:54 -0400150 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
151 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
Jim King7848d882015-04-06 21:38:06 -0400152 zlib_trans->write(buf.get(), buf_len);
David Reisse94fa332010-10-06 17:10:26 +0000153 zlib_trans->finish();
David Reissfaebedd2007-09-17 23:20:38 +0000154
David Reiss9a961e72010-10-06 17:10:23 +0000155 boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
David Reiss0a2d81e2010-10-06 17:10:40 +0000156 uint32_t got = zlib_trans->readAll(mirror.get(), buf_len);
David Reiss9a961e72010-10-06 17:10:23 +0000157 BOOST_REQUIRE_EQUAL(got, buf_len);
Jim King7848d882015-04-06 21:38:06 -0400158 BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
David Reiss9a961e72010-10-06 17:10:23 +0000159 zlib_trans->verifyChecksum();
160}
David Reissfaebedd2007-09-17 23:20:38 +0000161
Jim King7848d882015-04-06 21:38:06 -0400162void test_separate_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
David Reiss9a961e72010-10-06 17:10:23 +0000163 // This one is tricky. I separate the last byte of the stream out
164 // into a separate crbuf_. The last byte is part of the checksum,
165 // so the entire read goes fine, but when I go to verify the checksum
166 // it isn't there. The original implementation complained that
167 // the stream was not complete. I'm about to go fix that.
168 // It worked. Awesome.
James E. King, III82ae9572017-08-05 12:23:54 -0400169 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
170 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
Jim King7848d882015-04-06 21:38:06 -0400171 zlib_trans->write(buf.get(), buf_len);
David Reisse94fa332010-10-06 17:10:26 +0000172 zlib_trans->finish();
David Reiss9a961e72010-10-06 17:10:23 +0000173 string tmp_buf;
174 membuf->appendBufferToString(tmp_buf);
David Reissa0e11592010-10-06 17:10:27 +0000175 zlib_trans.reset(new TZlibTransport(membuf,
David Reiss9a961e72010-10-06 17:10:23 +0000176 TZlibTransport::DEFAULT_URBUF_SIZE,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100177 static_cast<uint32_t>(tmp_buf.length() - 1)));
David Reissfaebedd2007-09-17 23:20:38 +0000178
David Reiss9a961e72010-10-06 17:10:23 +0000179 boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
David Reiss0a2d81e2010-10-06 17:10:40 +0000180 uint32_t got = zlib_trans->readAll(mirror.get(), buf_len);
David Reiss9a961e72010-10-06 17:10:23 +0000181 BOOST_REQUIRE_EQUAL(got, buf_len);
Jim King7848d882015-04-06 21:38:06 -0400182 BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
David Reiss9a961e72010-10-06 17:10:23 +0000183 zlib_trans->verifyChecksum();
184}
David Reissfaebedd2007-09-17 23:20:38 +0000185
Jim King7848d882015-04-06 21:38:06 -0400186void test_incomplete_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
David Reiss9a961e72010-10-06 17:10:23 +0000187 // Make sure we still get that "not complete" error if
188 // it really isn't complete.
James E. King, III82ae9572017-08-05 12:23:54 -0400189 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
190 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
Jim King7848d882015-04-06 21:38:06 -0400191 zlib_trans->write(buf.get(), buf_len);
David Reisse94fa332010-10-06 17:10:26 +0000192 zlib_trans->finish();
David Reiss9a961e72010-10-06 17:10:23 +0000193 string tmp_buf;
194 membuf->appendBufferToString(tmp_buf);
195 tmp_buf.erase(tmp_buf.length() - 1);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100196 membuf->resetBuffer(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(tmp_buf.data())),
Jake Farrell5d02b802014-01-07 21:42:01 -0500197 static_cast<uint32_t>(tmp_buf.length()));
David Reiss9a961e72010-10-06 17:10:23 +0000198
199 boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
David Reiss0a2d81e2010-10-06 17:10:40 +0000200 uint32_t got = zlib_trans->readAll(mirror.get(), buf_len);
David Reiss9a961e72010-10-06 17:10:23 +0000201 BOOST_REQUIRE_EQUAL(got, buf_len);
Jim King7848d882015-04-06 21:38:06 -0400202 BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
David Reiss9a961e72010-10-06 17:10:23 +0000203 try {
204 zlib_trans->verifyChecksum();
205 BOOST_ERROR("verifyChecksum() did not report an error");
206 } catch (TTransportException& ex) {
207 BOOST_CHECK_EQUAL(ex.getType(), TTransportException::CORRUPTED_DATA);
208 }
209}
210
Jim King7848d882015-04-06 21:38:06 -0400211void test_read_write_mix(const boost::shared_array<uint8_t> buf,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100212 uint32_t buf_len,
James E. King, III82ae9572017-08-05 12:23:54 -0400213 const shared_ptr<SizeGenerator>& write_gen,
214 const shared_ptr<SizeGenerator>& read_gen) {
David Reiss9a961e72010-10-06 17:10:23 +0000215 // Try it with a mix of read/write sizes.
James E. King, III82ae9572017-08-05 12:23:54 -0400216 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
217 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
David Reiss9a961e72010-10-06 17:10:23 +0000218 unsigned int tot;
219
David Reiss9a961e72010-10-06 17:10:23 +0000220 tot = 0;
221 while (tot < buf_len) {
David Reissf2abcf92010-10-06 17:10:24 +0000222 uint32_t write_len = write_gen->getSize();
David Reiss9a961e72010-10-06 17:10:23 +0000223 if (tot + write_len > buf_len) {
224 write_len = buf_len - tot;
David Reissfaebedd2007-09-17 23:20:38 +0000225 }
Jim King7848d882015-04-06 21:38:06 -0400226 zlib_trans->write(buf.get() + tot, write_len);
David Reiss9a961e72010-10-06 17:10:23 +0000227 tot += write_len;
David Reiss9a961e72010-10-06 17:10:23 +0000228 }
David Reissfaebedd2007-09-17 23:20:38 +0000229
David Reisse94fa332010-10-06 17:10:26 +0000230 zlib_trans->finish();
David Reiss9a961e72010-10-06 17:10:23 +0000231
David Reiss9a961e72010-10-06 17:10:23 +0000232 tot = 0;
233 boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
234 while (tot < buf_len) {
David Reissf2abcf92010-10-06 17:10:24 +0000235 uint32_t read_len = read_gen->getSize();
David Reiss9a961e72010-10-06 17:10:23 +0000236 uint32_t expected_read_len = read_len;
237 if (tot + read_len > buf_len) {
238 expected_read_len = buf_len - tot;
David Reissfaebedd2007-09-17 23:20:38 +0000239 }
David Reiss9a961e72010-10-06 17:10:23 +0000240 uint32_t got = zlib_trans->read(mirror.get() + tot, read_len);
David Reiss0a2d81e2010-10-06 17:10:40 +0000241 BOOST_REQUIRE_LE(got, expected_read_len);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100242 BOOST_REQUIRE_NE(got, (uint32_t)0);
David Reiss9a961e72010-10-06 17:10:23 +0000243 tot += got;
David Reiss9a961e72010-10-06 17:10:23 +0000244 }
David Reissfaebedd2007-09-17 23:20:38 +0000245
Jim King7848d882015-04-06 21:38:06 -0400246 BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
David Reiss9a961e72010-10-06 17:10:23 +0000247 zlib_trans->verifyChecksum();
248}
David Reissfaebedd2007-09-17 23:20:38 +0000249
Jim King7848d882015-04-06 21:38:06 -0400250void test_invalid_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
David Reiss9a961e72010-10-06 17:10:23 +0000251 // Verify checksum checking.
James E. King, III82ae9572017-08-05 12:23:54 -0400252 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
253 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
Jim King7848d882015-04-06 21:38:06 -0400254 zlib_trans->write(buf.get(), buf_len);
David Reisse94fa332010-10-06 17:10:26 +0000255 zlib_trans->finish();
David Reiss9a961e72010-10-06 17:10:23 +0000256 string tmp_buf;
257 membuf->appendBufferToString(tmp_buf);
258 // Modify a byte at the end of the buffer (part of the checksum).
259 // On rare occasions, modifying a byte in the middle of the buffer
260 // isn't caught by the checksum.
261 //
262 // (This happens especially often for the uniform buffer. The
263 // re-inflated data is correct, however. I suspect in this case that
264 // we're more likely to modify bytes that are part of zlib metadata
265 // instead of the actual compressed data.)
266 //
267 // I've also seen some failure scenarios where a checksum failure isn't
268 // reported, but zlib keeps trying to decode past the end of the data.
269 // (When this occurs, verifyChecksum() throws an exception indicating
270 // that the end of the data hasn't been reached.) I haven't seen this
271 // error when only modifying checksum bytes.
Jake Farrell5d02b802014-01-07 21:42:01 -0500272 int index = static_cast<int>(tmp_buf.size() - 1);
David Reiss9a961e72010-10-06 17:10:23 +0000273 tmp_buf[index]++;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100274 membuf->resetBuffer(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(tmp_buf.data())),
Jake Farrell5d02b802014-01-07 21:42:01 -0500275 static_cast<uint32_t>(tmp_buf.length()));
David Reissfaebedd2007-09-17 23:20:38 +0000276
David Reiss9a961e72010-10-06 17:10:23 +0000277 boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
278 try {
David Reiss0a2d81e2010-10-06 17:10:40 +0000279 zlib_trans->readAll(mirror.get(), buf_len);
David Reiss9a961e72010-10-06 17:10:23 +0000280 zlib_trans->verifyChecksum();
281 BOOST_ERROR("verifyChecksum() did not report an error");
282 } catch (TZlibTransportException& ex) {
283 BOOST_CHECK_EQUAL(ex.getType(), TTransportException::INTERNAL_ERROR);
284 }
285}
David Reissfaebedd2007-09-17 23:20:38 +0000286
Jim King7848d882015-04-06 21:38:06 -0400287void test_write_after_flush(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
David Reisse94fa332010-10-06 17:10:26 +0000288 // write some data
James E. King, III82ae9572017-08-05 12:23:54 -0400289 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
290 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
Jim King7848d882015-04-06 21:38:06 -0400291 zlib_trans->write(buf.get(), buf_len);
David Reisse94fa332010-10-06 17:10:26 +0000292
293 // call finish()
294 zlib_trans->finish();
295
296 // make sure write() throws an error
297 try {
298 uint8_t write_buf[] = "a";
299 zlib_trans->write(write_buf, 1);
300 BOOST_ERROR("write() after finish() did not raise an exception");
301 } catch (TTransportException& ex) {
302 BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS);
303 }
304
305 // make sure flush() throws an error
306 try {
307 zlib_trans->flush();
308 BOOST_ERROR("flush() after finish() did not raise an exception");
309 } catch (TTransportException& ex) {
310 BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS);
311 }
312
313 // make sure finish() throws an error
314 try {
315 zlib_trans->finish();
316 BOOST_ERROR("finish() after finish() did not raise an exception");
317 } catch (TTransportException& ex) {
318 BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS);
319 }
320}
321
322void test_no_write() {
323 // Verify that no data is written to the underlying transport if we
324 // never write data to the TZlibTransport.
James E. King, III82ae9572017-08-05 12:23:54 -0400325 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
David Reisse94fa332010-10-06 17:10:26 +0000326 {
327 // Create a TZlibTransport object, and immediately destroy it
328 // when it goes out of scope.
David Reissa0e11592010-10-06 17:10:27 +0000329 TZlibTransport w_zlib_trans(membuf);
David Reisse94fa332010-10-06 17:10:26 +0000330 }
331
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100332 BOOST_CHECK_EQUAL(membuf->available_read(), (uint32_t)0);
David Reisse94fa332010-10-06 17:10:26 +0000333}
334
James E. King, IIId3013f32017-09-22 11:41:10 -0700335void test_get_underlying_transport() {
336 shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
337 shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
338 BOOST_CHECK_EQUAL(membuf.get(), zlib_trans->getUnderlyingTransport().get());
339}
340
David Reissf2abcf92010-10-06 17:10:24 +0000341/*
342 * Initialization
343 */
344
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200345#if (BOOST_VERSION >= 105900)
346#define ADD_TEST_CASE(suite, name, _FUNC, ...) \
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100347 do { \
348 ::std::ostringstream name_ss; \
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200349 name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \
cyy316723a2019-01-05 16:35:14 +0800350 ::std::function<void ()> test_func = \
351 ::std::bind(_FUNC, ##__VA_ARGS__); \
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100352 ::boost::unit_test::test_case* tc \
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200353 = ::boost::unit_test::make_test_case(test_func, name_ss.str(), __FILE__, __LINE__); \
354 (suite)->add(tc); \
355 } while (0)
356#else
357#define ADD_TEST_CASE(suite, name, _FUNC, ...) \
358 do { \
359 ::std::ostringstream name_ss; \
360 name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \
361 ::boost::unit_test::test_case* tc \
cyy316723a2019-01-05 16:35:14 +0800362 = ::boost::unit_test::make_test_case(::std::bind(_FUNC, \
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100363 ##__VA_ARGS__), \
364 name_ss.str()); \
365 (suite)->add(tc); \
David Reiss9a961e72010-10-06 17:10:23 +0000366 } while (0)
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200367#endif
David Reissfaebedd2007-09-17 23:20:38 +0000368
Jake Farrell5d02b802014-01-07 21:42:01 -0500369void add_tests(boost::unit_test::test_suite* suite,
Jim King7848d882015-04-06 21:38:06 -0400370 const boost::shared_array<uint8_t>& buf,
David Reiss9a961e72010-10-06 17:10:23 +0000371 uint32_t buf_len,
372 const char* name) {
373 ADD_TEST_CASE(suite, name, test_write_then_read, buf, buf_len);
374 ADD_TEST_CASE(suite, name, test_separate_checksum, buf, buf_len);
375 ADD_TEST_CASE(suite, name, test_incomplete_checksum, buf, buf_len);
David Reiss9a961e72010-10-06 17:10:23 +0000376 ADD_TEST_CASE(suite, name, test_invalid_checksum, buf, buf_len);
David Reisse94fa332010-10-06 17:10:26 +0000377 ADD_TEST_CASE(suite, name, test_write_after_flush, buf, buf_len);
David Reissf2abcf92010-10-06 17:10:24 +0000378
James E. King, III82ae9572017-08-05 12:23:54 -0400379 shared_ptr<SizeGenerator> size_32k(new ConstantSizeGenerator(1 << 15));
380 shared_ptr<SizeGenerator> size_lognormal(new LogNormalSizeGenerator(20, 30));
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100381 ADD_TEST_CASE(suite, name << "-constant", test_read_write_mix, buf, buf_len, size_32k, size_32k);
382 ADD_TEST_CASE(suite,
383 name << "-lognormal-write",
384 test_read_write_mix,
385 buf,
386 buf_len,
387 size_lognormal,
388 size_32k);
389 ADD_TEST_CASE(suite,
390 name << "-lognormal-read",
391 test_read_write_mix,
392 buf,
393 buf_len,
394 size_32k,
395 size_lognormal);
396 ADD_TEST_CASE(suite,
397 name << "-lognormal-both",
398 test_read_write_mix,
399 buf,
400 buf_len,
401 size_lognormal,
402 size_lognormal);
David Reissf2abcf92010-10-06 17:10:24 +0000403
404 // Test with a random size distribution,
405 // but use the exact same distribution for reading as for writing.
406 //
407 // Because the SizeGenerator makes a copy of the random number generator,
408 // both SizeGenerators should return the exact same set of values, since they
409 // both start with random number generators in the same state.
James E. King, III82ae9572017-08-05 12:23:54 -0400410 shared_ptr<SizeGenerator> write_size_gen(new LogNormalSizeGenerator(20, 30));
411 shared_ptr<SizeGenerator> read_size_gen(new LogNormalSizeGenerator(20, 30));
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100412 ADD_TEST_CASE(suite,
413 name << "-lognormal-same-distribution",
414 test_read_write_mix,
415 buf,
416 buf_len,
417 write_size_gen,
418 read_size_gen);
David Reiss9a961e72010-10-06 17:10:23 +0000419}
420
421void print_usage(FILE* f, const char* argv0) {
422 fprintf(f, "Usage: %s [boost_options] [options]\n", argv0);
423 fprintf(f, "Options:\n");
424 fprintf(f, " --seed=<N>, -s <N>\n");
425 fprintf(f, " --help\n");
426}
427
Antonio Di Monaco796667b2016-01-04 23:05:19 +0100428#ifdef BOOST_TEST_DYN_LINK
429bool init_unit_test_suite() {
Sebastian Zenker042580f2019-01-29 15:48:12 +0100430 auto seed = static_cast<uint32_t>(time(nullptr));
Antonio Di Monaco796667b2016-01-04 23:05:19 +0100431#ifdef HAVE_INTTYPES_H
432 printf("seed: %" PRIu32 "\n", seed);
433#endif
434 rng.seed(seed);
435
436 boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
437 suite->p_name.value = "ZlibTest";
438
439 uint32_t buf_len = 1024 * 32;
440 add_tests(suite, gen_uniform_buffer(buf_len, 'a'), buf_len, "uniform");
441 add_tests(suite, gen_compressible_buffer(buf_len), buf_len, "compressible");
442 add_tests(suite, gen_random_buffer(buf_len), buf_len, "random");
443
444 suite->add(BOOST_TEST_CASE(test_no_write));
James E. King, IIId3013f32017-09-22 11:41:10 -0700445 suite->add(BOOST_TEST_CASE(test_get_underlying_transport));
Antonio Di Monaco796667b2016-01-04 23:05:19 +0100446
447 return true;
448}
449
450int main( int argc, char* argv[] ) {
451 return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
452}
453#else
Jake Farrell5d02b802014-01-07 21:42:01 -0500454boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
Konrad Grochowskib3f5ffc2014-11-06 19:32:59 +0100455 THRIFT_UNUSED_VARIABLE(argc);
456 THRIFT_UNUSED_VARIABLE(argv);
zeshuai00726681fb2020-06-03 17:24:38 +0800457 uint32_t seed = static_cast<uint32_t>(time(nullptr));
Jim King9de9b1f2015-04-30 16:03:34 -0400458#ifdef HAVE_INTTYPES_H
David Reiss9a961e72010-10-06 17:10:23 +0000459 printf("seed: %" PRIu32 "\n", seed);
Jim King9de9b1f2015-04-30 16:03:34 -0400460#endif
David Reiss9a961e72010-10-06 17:10:23 +0000461 rng.seed(seed);
David Reiss9a961e72010-10-06 17:10:23 +0000462
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100463 boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
David Reiss109693c2010-10-06 17:10:42 +0000464 suite->p_name.value = "ZlibTest";
David Reiss9a961e72010-10-06 17:10:23 +0000465
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100466 uint32_t buf_len = 1024 * 32;
David Reiss9a961e72010-10-06 17:10:23 +0000467 add_tests(suite, gen_uniform_buffer(buf_len, 'a'), buf_len, "uniform");
468 add_tests(suite, gen_compressible_buffer(buf_len), buf_len, "compressible");
469 add_tests(suite, gen_random_buffer(buf_len), buf_len, "random");
470
David Reisse94fa332010-10-06 17:10:26 +0000471 suite->add(BOOST_TEST_CASE(test_no_write));
472
zeshuai00726681fb2020-06-03 17:24:38 +0800473 return nullptr;
David Reissfaebedd2007-09-17 23:20:38 +0000474}
Antonio Di Monaco796667b2016-01-04 23:05:19 +0100475#endif