| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 1 | /* | 
| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 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 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 20 | #ifndef _GNU_SOURCE | 
 | 21 | #define _GNU_SOURCE // needed for getopt_long | 
 | 22 | #endif | 
 | 23 |  | 
| James E. King, III | 07f5997 | 2017-03-10 06:18:33 -0500 | [diff] [blame] | 24 | #if defined(_MSC_VER) && (_MSC_VER <= 1700) | 
| James E. King, III | 7edc8fa | 2017-01-20 10:11:41 -0500 | [diff] [blame] | 25 | // 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 Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 31 | #include <stdint.h> | 
| James E. King, III | 7edc8fa | 2017-01-20 10:11:41 -0500 | [diff] [blame] | 32 | #endif | 
| Jim King | 9de9b1f | 2015-04-30 16:03:34 -0400 | [diff] [blame] | 33 | #ifdef HAVE_INTTYPES_H | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 34 | #include <inttypes.h> | 
| Jim King | 9de9b1f | 2015-04-30 16:03:34 -0400 | [diff] [blame] | 35 | #endif | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 36 | #include <cstddef> | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 37 | #include <fstream> | 
 | 38 | #include <iostream> | 
| cyy | 316723a | 2019-01-05 16:35:14 +0800 | [diff] [blame] | 39 | #include <memory> | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 40 |  | 
 | 41 | #include <boost/random.hpp> | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 42 | #include <boost/shared_array.hpp> | 
 | 43 | #include <boost/test/unit_test.hpp> | 
| Konrad Grochowski | e9bdb41 | 2015-09-25 20:17:36 +0200 | [diff] [blame] | 44 | #include <boost/version.hpp> | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 45 |  | 
| Roger Meier | 49ff8b1 | 2012-04-13 09:12:31 +0000 | [diff] [blame] | 46 | #include <thrift/transport/TBufferTransports.h> | 
 | 47 | #include <thrift/transport/TZlibTransport.h> | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 48 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 49 | using namespace apache::thrift::transport; | 
| cyy | 316723a | 2019-01-05 16:35:14 +0800 | [diff] [blame] | 50 | using std::shared_ptr; | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 51 | using std::string; | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 52 |  | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 53 | boost::mt19937 rng; | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 54 |  | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 55 | /* | 
 | 56 |  * Utility code | 
 | 57 |  */ | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 58 |  | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 59 | class SizeGenerator { | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 60 | public: | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 61 |   virtual ~SizeGenerator() = default; | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 62 |   virtual unsigned int getSize() = 0; | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 63 | }; | 
 | 64 |  | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 65 | class ConstantSizeGenerator : public SizeGenerator { | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 66 | public: | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 67 |   ConstantSizeGenerator(unsigned int value) : value_(value) {} | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 68 |   unsigned int getSize() override { return value_; } | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 69 |  | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 70 | private: | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 71 |   unsigned int value_; | 
 | 72 | }; | 
 | 73 |  | 
 | 74 | class LogNormalSizeGenerator : public SizeGenerator { | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 75 | public: | 
 | 76 |   LogNormalSizeGenerator(double mean, double std_dev) | 
 | 77 |     : gen_(rng, boost::lognormal_distribution<double>(mean, std_dev)) {} | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 78 |  | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 79 |   unsigned int getSize() override { | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 80 |     // Loop until we get a size of 1 or more | 
 | 81 |     while (true) { | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 82 |       auto value = static_cast<unsigned int>(gen_()); | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 83 |       if (value >= 1) { | 
 | 84 |         return value; | 
 | 85 |       } | 
 | 86 |     } | 
 | 87 |   } | 
 | 88 |  | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 89 | private: | 
 | 90 |   boost::variate_generator<boost::mt19937, boost::lognormal_distribution<double> > gen_; | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 91 | }; | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 92 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 93 | boost::shared_array<uint8_t> gen_uniform_buffer(uint32_t buf_len, uint8_t c) { | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 94 |   auto* buf = new uint8_t[buf_len]; | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 95 |   memset(buf, c, buf_len); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 96 |   return boost::shared_array<uint8_t>(buf); | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 97 | } | 
 | 98 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 99 | boost::shared_array<uint8_t> gen_compressible_buffer(uint32_t buf_len) { | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 100 |   auto* buf = new uint8_t[buf_len]; | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 101 |  | 
 | 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 Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 105 |   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 Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 109 |  | 
 | 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 King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 128 |   return boost::shared_array<uint8_t>(buf); | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 129 | } | 
 | 130 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 131 | boost::shared_array<uint8_t> gen_random_buffer(uint32_t buf_len) { | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 132 |   auto* buf = new uint8_t[buf_len]; | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 133 |  | 
 | 134 |   boost::uniform_smallint<uint8_t> distribution(0, UINT8_MAX); | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 135 |   boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint8_t> > | 
 | 136 |       generator(rng, distribution); | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 137 |  | 
 | 138 |   for (uint32_t n = 0; n < buf_len; ++n) { | 
 | 139 |     buf[n] = generator(); | 
 | 140 |   } | 
 | 141 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 142 |   return boost::shared_array<uint8_t>(buf); | 
| David Reiss | 3cc9dab | 2010-10-06 17:10:21 +0000 | [diff] [blame] | 143 | } | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 144 |  | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 145 | /* | 
 | 146 |  * Test functions | 
 | 147 |  */ | 
 | 148 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 149 | void test_write_then_read(const boost::shared_array<uint8_t> buf, uint32_t buf_len) { | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 150 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
 | 151 |   shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf)); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 152 |   zlib_trans->write(buf.get(), buf_len); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 153 |   zlib_trans->finish(); | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 154 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 155 |   boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]); | 
| David Reiss | 0a2d81e | 2010-10-06 17:10:40 +0000 | [diff] [blame] | 156 |   uint32_t got = zlib_trans->readAll(mirror.get(), buf_len); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 157 |   BOOST_REQUIRE_EQUAL(got, buf_len); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 158 |   BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 159 |   zlib_trans->verifyChecksum(); | 
 | 160 | } | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 161 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 162 | void test_separate_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) { | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 163 |   // 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, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 169 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
 | 170 |   shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf)); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 171 |   zlib_trans->write(buf.get(), buf_len); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 172 |   zlib_trans->finish(); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 173 |   string tmp_buf; | 
 | 174 |   membuf->appendBufferToString(tmp_buf); | 
| David Reiss | a0e1159 | 2010-10-06 17:10:27 +0000 | [diff] [blame] | 175 |   zlib_trans.reset(new TZlibTransport(membuf, | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 176 |                                       TZlibTransport::DEFAULT_URBUF_SIZE, | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 177 |                                       static_cast<uint32_t>(tmp_buf.length() - 1))); | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 178 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 179 |   boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]); | 
| David Reiss | 0a2d81e | 2010-10-06 17:10:40 +0000 | [diff] [blame] | 180 |   uint32_t got = zlib_trans->readAll(mirror.get(), buf_len); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 181 |   BOOST_REQUIRE_EQUAL(got, buf_len); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 182 |   BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 183 |   zlib_trans->verifyChecksum(); | 
 | 184 | } | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 185 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 186 | void test_incomplete_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) { | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 187 |   // Make sure we still get that "not complete" error if | 
 | 188 |   // it really isn't complete. | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 189 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
 | 190 |   shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf)); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 191 |   zlib_trans->write(buf.get(), buf_len); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 192 |   zlib_trans->finish(); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 193 |   string tmp_buf; | 
 | 194 |   membuf->appendBufferToString(tmp_buf); | 
 | 195 |   tmp_buf.erase(tmp_buf.length() - 1); | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 196 |   membuf->resetBuffer(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(tmp_buf.data())), | 
| Jake Farrell | 5d02b80 | 2014-01-07 21:42:01 -0500 | [diff] [blame] | 197 |                       static_cast<uint32_t>(tmp_buf.length())); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 198 |  | 
 | 199 |   boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]); | 
| David Reiss | 0a2d81e | 2010-10-06 17:10:40 +0000 | [diff] [blame] | 200 |   uint32_t got = zlib_trans->readAll(mirror.get(), buf_len); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 201 |   BOOST_REQUIRE_EQUAL(got, buf_len); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 202 |   BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 203 |   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 King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 211 | void test_read_write_mix(const boost::shared_array<uint8_t> buf, | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 212 |                          uint32_t buf_len, | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 213 |                          const shared_ptr<SizeGenerator>& write_gen, | 
 | 214 |                          const shared_ptr<SizeGenerator>& read_gen) { | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 215 |   // Try it with a mix of read/write sizes. | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 216 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
 | 217 |   shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf)); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 218 |   unsigned int tot; | 
 | 219 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 220 |   tot = 0; | 
 | 221 |   while (tot < buf_len) { | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 222 |     uint32_t write_len = write_gen->getSize(); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 223 |     if (tot + write_len > buf_len) { | 
 | 224 |       write_len = buf_len - tot; | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 225 |     } | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 226 |     zlib_trans->write(buf.get() + tot, write_len); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 227 |     tot += write_len; | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 228 |   } | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 229 |  | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 230 |   zlib_trans->finish(); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 231 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 232 |   tot = 0; | 
 | 233 |   boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]); | 
 | 234 |   while (tot < buf_len) { | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 235 |     uint32_t read_len = read_gen->getSize(); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 236 |     uint32_t expected_read_len = read_len; | 
 | 237 |     if (tot + read_len > buf_len) { | 
 | 238 |       expected_read_len = buf_len - tot; | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 239 |     } | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 240 |     uint32_t got = zlib_trans->read(mirror.get() + tot, read_len); | 
| David Reiss | 0a2d81e | 2010-10-06 17:10:40 +0000 | [diff] [blame] | 241 |     BOOST_REQUIRE_LE(got, expected_read_len); | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 242 |     BOOST_REQUIRE_NE(got, (uint32_t)0); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 243 |     tot += got; | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 244 |   } | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 245 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 246 |   BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 247 |   zlib_trans->verifyChecksum(); | 
 | 248 | } | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 249 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 250 | void test_invalid_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) { | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 251 |   // Verify checksum checking. | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 252 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
 | 253 |   shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf)); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 254 |   zlib_trans->write(buf.get(), buf_len); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 255 |   zlib_trans->finish(); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 256 |   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 Farrell | 5d02b80 | 2014-01-07 21:42:01 -0500 | [diff] [blame] | 272 |   int index = static_cast<int>(tmp_buf.size() - 1); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 273 |   tmp_buf[index]++; | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 274 |   membuf->resetBuffer(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(tmp_buf.data())), | 
| Jake Farrell | 5d02b80 | 2014-01-07 21:42:01 -0500 | [diff] [blame] | 275 |                       static_cast<uint32_t>(tmp_buf.length())); | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 276 |  | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 277 |   boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]); | 
 | 278 |   try { | 
| David Reiss | 0a2d81e | 2010-10-06 17:10:40 +0000 | [diff] [blame] | 279 |     zlib_trans->readAll(mirror.get(), buf_len); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 280 |     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 Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 286 |  | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 287 | void test_write_after_flush(const boost::shared_array<uint8_t> buf, uint32_t buf_len) { | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 288 |   // write some data | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 289 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
 | 290 |   shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf)); | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 291 |   zlib_trans->write(buf.get(), buf_len); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 292 |  | 
 | 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 |  | 
 | 322 | void 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, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 325 |   shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer()); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 326 |   { | 
 | 327 |     // Create a TZlibTransport object, and immediately destroy it | 
 | 328 |     // when it goes out of scope. | 
| David Reiss | a0e1159 | 2010-10-06 17:10:27 +0000 | [diff] [blame] | 329 |     TZlibTransport w_zlib_trans(membuf); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 330 |   } | 
 | 331 |  | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 332 |   BOOST_CHECK_EQUAL(membuf->available_read(), (uint32_t)0); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 333 | } | 
 | 334 |  | 
| James E. King, III | d3013f3 | 2017-09-22 11:41:10 -0700 | [diff] [blame] | 335 | void 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 Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 341 | /* | 
 | 342 |  * Initialization | 
 | 343 |  */ | 
 | 344 |  | 
| Konrad Grochowski | e9bdb41 | 2015-09-25 20:17:36 +0200 | [diff] [blame] | 345 | #if (BOOST_VERSION >= 105900) | 
 | 346 | #define ADD_TEST_CASE(suite, name, _FUNC, ...)                                                     \ | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 347 |   do {                                                                                             \ | 
 | 348 |     ::std::ostringstream name_ss;                                                                  \ | 
| Konrad Grochowski | e9bdb41 | 2015-09-25 20:17:36 +0200 | [diff] [blame] | 349 |     name_ss << name << "-" << BOOST_STRINGIZE(_FUNC);                                              \ | 
| cyy | 316723a | 2019-01-05 16:35:14 +0800 | [diff] [blame] | 350 |     ::std::function<void ()> test_func =                                        \ | 
 | 351 |         ::std::bind(_FUNC, ##__VA_ARGS__);                                      \ | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 352 |     ::boost::unit_test::test_case* tc                                                              \ | 
| Konrad Grochowski | e9bdb41 | 2015-09-25 20:17:36 +0200 | [diff] [blame] | 353 |         = ::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                                                              \ | 
| cyy | 316723a | 2019-01-05 16:35:14 +0800 | [diff] [blame] | 362 |         = ::boost::unit_test::make_test_case(::std::bind(_FUNC,                 \ | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 363 |                                                                             ##__VA_ARGS__),        \ | 
 | 364 |                                              name_ss.str());                                       \ | 
 | 365 |     (suite)->add(tc);                                                                              \ | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 366 |   } while (0) | 
| Konrad Grochowski | e9bdb41 | 2015-09-25 20:17:36 +0200 | [diff] [blame] | 367 | #endif | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 368 |  | 
| Jake Farrell | 5d02b80 | 2014-01-07 21:42:01 -0500 | [diff] [blame] | 369 | void add_tests(boost::unit_test::test_suite* suite, | 
| Jim King | 7848d88 | 2015-04-06 21:38:06 -0400 | [diff] [blame] | 370 |                const boost::shared_array<uint8_t>& buf, | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 371 |                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 Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 376 |   ADD_TEST_CASE(suite, name, test_invalid_checksum, buf, buf_len); | 
| David Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 377 |   ADD_TEST_CASE(suite, name, test_write_after_flush, buf, buf_len); | 
| David Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 378 |  | 
| James E. King, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 379 |   shared_ptr<SizeGenerator> size_32k(new ConstantSizeGenerator(1 << 15)); | 
 | 380 |   shared_ptr<SizeGenerator> size_lognormal(new LogNormalSizeGenerator(20, 30)); | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 381 |   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 Reiss | f2abcf9 | 2010-10-06 17:10:24 +0000 | [diff] [blame] | 403 |  | 
 | 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, III | 82ae957 | 2017-08-05 12:23:54 -0400 | [diff] [blame] | 410 |   shared_ptr<SizeGenerator> write_size_gen(new LogNormalSizeGenerator(20, 30)); | 
 | 411 |   shared_ptr<SizeGenerator> read_size_gen(new LogNormalSizeGenerator(20, 30)); | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 412 |   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 Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 419 | } | 
 | 420 |  | 
 | 421 | void 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 Monaco | 796667b | 2016-01-04 23:05:19 +0100 | [diff] [blame] | 428 | #ifdef BOOST_TEST_DYN_LINK | 
 | 429 | bool init_unit_test_suite() { | 
| Sebastian Zenker | 042580f | 2019-01-29 15:48:12 +0100 | [diff] [blame] | 430 |   auto seed = static_cast<uint32_t>(time(nullptr)); | 
| Antonio Di Monaco | 796667b | 2016-01-04 23:05:19 +0100 | [diff] [blame] | 431 | #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, III | d3013f3 | 2017-09-22 11:41:10 -0700 | [diff] [blame] | 445 |   suite->add(BOOST_TEST_CASE(test_get_underlying_transport)); | 
| Antonio Di Monaco | 796667b | 2016-01-04 23:05:19 +0100 | [diff] [blame] | 446 |  | 
 | 447 |   return true; | 
 | 448 | } | 
 | 449 |  | 
 | 450 | int main( int argc, char* argv[] ) { | 
 | 451 |   return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv); | 
 | 452 | } | 
 | 453 | #else | 
| Jake Farrell | 5d02b80 | 2014-01-07 21:42:01 -0500 | [diff] [blame] | 454 | boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { | 
| Konrad Grochowski | b3f5ffc | 2014-11-06 19:32:59 +0100 | [diff] [blame] | 455 |   THRIFT_UNUSED_VARIABLE(argc); | 
 | 456 |   THRIFT_UNUSED_VARIABLE(argv); | 
| zeshuai007 | 26681fb | 2020-06-03 17:24:38 +0800 | [diff] [blame] | 457 |   uint32_t seed = static_cast<uint32_t>(time(nullptr)); | 
| Jim King | 9de9b1f | 2015-04-30 16:03:34 -0400 | [diff] [blame] | 458 | #ifdef HAVE_INTTYPES_H | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 459 |   printf("seed: %" PRIu32 "\n", seed); | 
| Jim King | 9de9b1f | 2015-04-30 16:03:34 -0400 | [diff] [blame] | 460 | #endif | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 461 |   rng.seed(seed); | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 462 |  | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 463 |   boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); | 
| David Reiss | 109693c | 2010-10-06 17:10:42 +0000 | [diff] [blame] | 464 |   suite->p_name.value = "ZlibTest"; | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 465 |  | 
| Konrad Grochowski | 16a23a6 | 2014-11-13 15:33:38 +0100 | [diff] [blame] | 466 |   uint32_t buf_len = 1024 * 32; | 
| David Reiss | 9a961e7 | 2010-10-06 17:10:23 +0000 | [diff] [blame] | 467 |   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 Reiss | e94fa33 | 2010-10-06 17:10:26 +0000 | [diff] [blame] | 471 |   suite->add(BOOST_TEST_CASE(test_no_write)); | 
 | 472 |  | 
| zeshuai007 | 26681fb | 2020-06-03 17:24:38 +0800 | [diff] [blame] | 473 |   return nullptr; | 
| David Reiss | faebedd | 2007-09-17 23:20:38 +0000 | [diff] [blame] | 474 | } | 
| Antonio Di Monaco | 796667b | 2016-01-04 23:05:19 +0100 | [diff] [blame] | 475 | #endif |