other-licenses/snappy/src/snappy-test.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 // Copyright 2011 Google Inc. All Rights Reserved.
     2 //
     3 // Redistribution and use in source and binary forms, with or without
     4 // modification, are permitted provided that the following conditions are
     5 // met:
     6 //
     7 //     * Redistributions of source code must retain the above copyright
     8 // notice, this list of conditions and the following disclaimer.
     9 //     * Redistributions in binary form must reproduce the above
    10 // copyright notice, this list of conditions and the following disclaimer
    11 // in the documentation and/or other materials provided with the
    12 // distribution.
    13 //     * Neither the name of Google Inc. nor the names of its
    14 // contributors may be used to endorse or promote products derived from
    15 // this software without specific prior written permission.
    16 //
    17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    28 //
    29 // Various stubs for the unit tests for the open-source version of Snappy.
    31 #ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_
    32 #define UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_
    34 #include "snappy-stubs-internal.h"
    36 #include <stdio.h>
    37 #include <stdarg.h>
    39 #ifdef HAVE_SYS_MMAN_H
    40 #include <sys/mman.h>
    41 #endif
    43 #ifdef HAVE_SYS_RESOURCE_H
    44 #include <sys/resource.h>
    45 #endif
    47 #include <sys/time.h>
    49 #ifdef HAVE_WINDOWS_H
    50 #define WIN32_LEAN_AND_MEAN
    51 #include <windows.h>
    52 #endif
    54 #include <string>
    56 #ifdef HAVE_GTEST
    58 #include <gtest/gtest.h>
    59 #undef TYPED_TEST
    60 #define TYPED_TEST TEST
    61 #define INIT_GTEST(argc, argv) ::testing::InitGoogleTest(argc, *argv)
    63 #else
    65 // Stubs for if the user doesn't have Google Test installed.
    67 #define TEST(test_case, test_subcase) \
    68   void Test_ ## test_case ## _ ## test_subcase()
    69 #define INIT_GTEST(argc, argv)
    71 #define TYPED_TEST TEST
    72 #define EXPECT_EQ CHECK_EQ
    73 #define EXPECT_NE CHECK_NE
    74 #define EXPECT_FALSE(cond) CHECK(!(cond))
    76 #endif
    78 #ifdef HAVE_GFLAGS
    80 #include <gflags/gflags.h>
    82 // This is tricky; both gflags and Google Test want to look at the command line
    83 // arguments. Google Test seems to be the most happy with unknown arguments,
    84 // though, so we call it first and hope for the best.
    85 #define InitGoogle(argv0, argc, argv, remove_flags) \
    86   INIT_GTEST(argc, argv); \
    87   google::ParseCommandLineFlags(argc, argv, remove_flags);
    89 #else
    91 // If we don't have the gflags package installed, these can only be
    92 // changed at compile time.
    93 #define DEFINE_int32(flag_name, default_value, description) \
    94   static int FLAGS_ ## flag_name = default_value;
    96 #define InitGoogle(argv0, argc, argv, remove_flags) \
    97   INIT_GTEST(argc, argv)
    99 #endif
   101 #ifdef HAVE_LIBZ
   102 #include "zlib.h"
   103 #endif
   105 #ifdef HAVE_LIBLZO2
   106 #include "lzo/lzo1x.h"
   107 #endif
   109 #ifdef HAVE_LIBLZF
   110 extern "C" {
   111 #include "lzf.h"
   112 }
   113 #endif
   115 #ifdef HAVE_LIBFASTLZ
   116 #include "fastlz.h"
   117 #endif
   119 #ifdef HAVE_LIBQUICKLZ
   120 #include "quicklz.h"
   121 #endif
   123 namespace {
   124 namespace File {
   125   void Init() { }
   127   void ReadFileToStringOrDie(const char* filename, string* data) {
   128     FILE* fp = fopen(filename, "rb");
   129     if (fp == NULL) {
   130       perror(filename);
   131       exit(1);
   132     }
   134     data->clear();
   135     while (!feof(fp)) {
   136       char buf[4096];
   137       size_t ret = fread(buf, 1, 4096, fp);
   138       if (ret == 0 && ferror(fp)) {
   139         perror("fread");
   140         exit(1);
   141       }
   142       data->append(string(buf, ret));
   143     }
   145     fclose(fp);
   146   }
   148   void ReadFileToStringOrDie(const string& filename, string* data) {
   149     ReadFileToStringOrDie(filename.c_str(), data);
   150   }
   152   void WriteStringToFileOrDie(const string& str, const char* filename) {
   153     FILE* fp = fopen(filename, "wb");
   154     if (fp == NULL) {
   155       perror(filename);
   156       exit(1);
   157     }
   159     int ret = fwrite(str.data(), str.size(), 1, fp);
   160     if (ret != 1) {
   161       perror("fwrite");
   162       exit(1);
   163     }
   165     fclose(fp);
   166   }
   167 }  // namespace File
   168 }  // namespace
   170 namespace snappy {
   172 #define FLAGS_test_random_seed 301
   173 typedef string TypeParam;
   175 void Test_CorruptedTest_VerifyCorrupted();
   176 void Test_Snappy_SimpleTests();
   177 void Test_Snappy_MaxBlowup();
   178 void Test_Snappy_RandomData();
   179 void Test_Snappy_FourByteOffset();
   180 void Test_SnappyCorruption_TruncatedVarint();
   181 void Test_SnappyCorruption_UnterminatedVarint();
   182 void Test_Snappy_ReadPastEndOfBuffer();
   183 void Test_Snappy_FindMatchLength();
   184 void Test_Snappy_FindMatchLengthRandom();
   186 string ReadTestDataFile(const string& base);
   188 // A sprintf() variant that returns a std::string.
   189 // Not safe for general use due to truncation issues.
   190 string StringPrintf(const char* format, ...);
   192 // A simple, non-cryptographically-secure random generator.
   193 class ACMRandom {
   194  public:
   195   explicit ACMRandom(uint32 seed) : seed_(seed) {}
   197   int32 Next();
   199   int32 Uniform(int32 n) {
   200     return Next() % n;
   201   }
   202   uint8 Rand8() {
   203     return static_cast<uint8>((Next() >> 1) & 0x000000ff);
   204   }
   205   bool OneIn(int X) { return Uniform(X) == 0; }
   207   // Skewed: pick "base" uniformly from range [0,max_log] and then
   208   // return "base" random bits.  The effect is to pick a number in the
   209   // range [0,2^max_log-1] with bias towards smaller numbers.
   210   int32 Skewed(int max_log);
   212  private:
   213   static const uint32 M = 2147483647L;   // 2^31-1
   214   uint32 seed_;
   215 };
   217 inline int32 ACMRandom::Next() {
   218   static const uint64 A = 16807;  // bits 14, 8, 7, 5, 2, 1, 0
   219   // We are computing
   220   //       seed_ = (seed_ * A) % M,    where M = 2^31-1
   221   //
   222   // seed_ must not be zero or M, or else all subsequent computed values
   223   // will be zero or M respectively.  For all other values, seed_ will end
   224   // up cycling through every number in [1,M-1]
   225   uint64 product = seed_ * A;
   227   // Compute (product % M) using the fact that ((x << 31) % M) == x.
   228   seed_ = (product >> 31) + (product & M);
   229   // The first reduction may overflow by 1 bit, so we may need to repeat.
   230   // mod == M is not possible; using > allows the faster sign-bit-based test.
   231   if (seed_ > M) {
   232     seed_ -= M;
   233   }
   234   return seed_;
   235 }
   237 inline int32 ACMRandom::Skewed(int max_log) {
   238   const int32 base = (Next() - 1) % (max_log+1);
   239   return (Next() - 1) & ((1u << base)-1);
   240 }
   242 // A wall-time clock. This stub is not super-accurate, nor resistant to the
   243 // system time changing.
   244 class CycleTimer {
   245  public:
   246   CycleTimer() : real_time_us_(0) {}
   248   void Start() {
   249 #ifdef WIN32
   250     QueryPerformanceCounter(&start_);
   251 #else
   252     gettimeofday(&start_, NULL);
   253 #endif
   254   }
   256   void Stop() {
   257 #ifdef WIN32
   258     LARGE_INTEGER stop;
   259     LARGE_INTEGER frequency;
   260     QueryPerformanceCounter(&stop);
   261     QueryPerformanceFrequency(&frequency);
   263     double elapsed = static_cast<double>(stop.QuadPart - start_.QuadPart) /
   264         frequency.QuadPart;
   265     real_time_us_ += elapsed * 1e6 + 0.5;
   266 #else
   267     struct timeval stop;
   268     gettimeofday(&stop, NULL);
   270     real_time_us_ += 1000000 * (stop.tv_sec - start_.tv_sec);
   271     real_time_us_ += (stop.tv_usec - start_.tv_usec);
   272 #endif
   273   }
   275   double Get() {
   276     return real_time_us_ * 1e-6;
   277   }
   279  private:
   280   int64 real_time_us_;
   281 #ifdef WIN32
   282   LARGE_INTEGER start_;
   283 #else
   284   struct timeval start_;
   285 #endif
   286 };
   288 // Minimalistic microbenchmark framework.
   290 typedef void (*BenchmarkFunction)(int, int);
   292 class Benchmark {
   293  public:
   294   Benchmark(const string& name, BenchmarkFunction function) :
   295       name_(name), function_(function) {}
   297   Benchmark* DenseRange(int start, int stop) {
   298     start_ = start;
   299     stop_ = stop;
   300     return this;
   301   }
   303   void Run();
   305  private:
   306   const string name_;
   307   const BenchmarkFunction function_;
   308   int start_, stop_;
   309 };
   310 #define BENCHMARK(benchmark_name) \
   311   Benchmark* Benchmark_ ## benchmark_name = \
   312           (new Benchmark(#benchmark_name, benchmark_name))
   314 extern Benchmark* Benchmark_BM_UFlat;
   315 extern Benchmark* Benchmark_BM_UValidate;
   316 extern Benchmark* Benchmark_BM_ZFlat;
   318 void ResetBenchmarkTiming();
   319 void StartBenchmarkTiming();
   320 void StopBenchmarkTiming();
   321 void SetBenchmarkLabel(const string& str);
   322 void SetBenchmarkBytesProcessed(int64 bytes);
   324 #ifdef HAVE_LIBZ
   326 // Object-oriented wrapper around zlib.
   327 class ZLib {
   328  public:
   329   ZLib();
   330   ~ZLib();
   332   // Wipe a ZLib object to a virgin state.  This differs from Reset()
   333   // in that it also breaks any state.
   334   void Reinit();
   336   // Call this to make a zlib buffer as good as new.  Here's the only
   337   // case where they differ:
   338   //    CompressChunk(a); CompressChunk(b); CompressChunkDone();   vs
   339   //    CompressChunk(a); Reset(); CompressChunk(b); CompressChunkDone();
   340   // You'll want to use Reset(), then, when you interrupt a compress
   341   // (or uncompress) in the middle of a chunk and want to start over.
   342   void Reset();
   344   // According to the zlib manual, when you Compress, the destination
   345   // buffer must have size at least src + .1%*src + 12.  This function
   346   // helps you calculate that.  Augment this to account for a potential
   347   // gzip header and footer, plus a few bytes of slack.
   348   static int MinCompressbufSize(int uncompress_size) {
   349     return uncompress_size + uncompress_size/1000 + 40;
   350   }
   352   // Compresses the source buffer into the destination buffer.
   353   // sourceLen is the byte length of the source buffer.
   354   // Upon entry, destLen is the total size of the destination buffer,
   355   // which must be of size at least MinCompressbufSize(sourceLen).
   356   // Upon exit, destLen is the actual size of the compressed buffer.
   357   //
   358   // This function can be used to compress a whole file at once if the
   359   // input file is mmap'ed.
   360   //
   361   // Returns Z_OK if success, Z_MEM_ERROR if there was not
   362   // enough memory, Z_BUF_ERROR if there was not enough room in the
   363   // output buffer. Note that if the output buffer is exactly the same
   364   // size as the compressed result, we still return Z_BUF_ERROR.
   365   // (check CL#1936076)
   366   int Compress(Bytef *dest, uLongf *destLen,
   367                const Bytef *source, uLong sourceLen);
   369   // Uncompresses the source buffer into the destination buffer.
   370   // The destination buffer must be long enough to hold the entire
   371   // decompressed contents.
   372   //
   373   // Returns Z_OK on success, otherwise, it returns a zlib error code.
   374   int Uncompress(Bytef *dest, uLongf *destLen,
   375                  const Bytef *source, uLong sourceLen);
   377   // Uncompress data one chunk at a time -- ie you can call this
   378   // more than once.  To get this to work you need to call per-chunk
   379   // and "done" routines.
   380   //
   381   // Returns Z_OK if success, Z_MEM_ERROR if there was not
   382   // enough memory, Z_BUF_ERROR if there was not enough room in the
   383   // output buffer.
   385   int UncompressAtMost(Bytef *dest, uLongf *destLen,
   386                        const Bytef *source, uLong *sourceLen);
   388   // Checks gzip footer information, as needed.  Mostly this just
   389   // makes sure the checksums match.  Whenever you call this, it
   390   // will assume the last 8 bytes from the previous UncompressChunk
   391   // call are the footer.  Returns true iff everything looks ok.
   392   bool UncompressChunkDone();
   394  private:
   395   int InflateInit();       // sets up the zlib inflate structure
   396   int DeflateInit();       // sets up the zlib deflate structure
   398   // These init the zlib data structures for compressing/uncompressing
   399   int CompressInit(Bytef *dest, uLongf *destLen,
   400                    const Bytef *source, uLong *sourceLen);
   401   int UncompressInit(Bytef *dest, uLongf *destLen,
   402                      const Bytef *source, uLong *sourceLen);
   403   // Initialization method to be called if we hit an error while
   404   // uncompressing. On hitting an error, call this method before
   405   // returning the error.
   406   void UncompressErrorInit();
   408   // Helper function for Compress
   409   int CompressChunkOrAll(Bytef *dest, uLongf *destLen,
   410                          const Bytef *source, uLong sourceLen,
   411                          int flush_mode);
   412   int CompressAtMostOrAll(Bytef *dest, uLongf *destLen,
   413                           const Bytef *source, uLong *sourceLen,
   414                           int flush_mode);
   416   // Likewise for UncompressAndUncompressChunk
   417   int UncompressChunkOrAll(Bytef *dest, uLongf *destLen,
   418                            const Bytef *source, uLong sourceLen,
   419                            int flush_mode);
   421   int UncompressAtMostOrAll(Bytef *dest, uLongf *destLen,
   422                             const Bytef *source, uLong *sourceLen,
   423                             int flush_mode);
   425   // Initialization method to be called if we hit an error while
   426   // compressing. On hitting an error, call this method before
   427   // returning the error.
   428   void CompressErrorInit();
   430   int compression_level_;   // compression level
   431   int window_bits_;         // log base 2 of the window size used in compression
   432   int mem_level_;           // specifies the amount of memory to be used by
   433                             // compressor (1-9)
   434   z_stream comp_stream_;    // Zlib stream data structure
   435   bool comp_init_;          // True if we have initialized comp_stream_
   436   z_stream uncomp_stream_;  // Zlib stream data structure
   437   bool uncomp_init_;        // True if we have initialized uncomp_stream_
   439   // These are used only with chunked compression.
   440   bool first_chunk_;       // true if we need to emit headers with this chunk
   441 };
   443 #endif  // HAVE_LIBZ
   445 }  // namespace snappy
   447 DECLARE_bool(run_microbenchmarks);
   449 static void RunSpecifiedBenchmarks() {
   450   if (!FLAGS_run_microbenchmarks) {
   451     return;
   452   }
   454   fprintf(stderr, "Running microbenchmarks.\n");
   455 #ifndef NDEBUG
   456   fprintf(stderr, "WARNING: Compiled with assertions enabled, will be slow.\n");
   457 #endif
   458 #ifndef __OPTIMIZE__
   459   fprintf(stderr, "WARNING: Compiled without optimization, will be slow.\n");
   460 #endif
   461   fprintf(stderr, "Benchmark            Time(ns)    CPU(ns) Iterations\n");
   462   fprintf(stderr, "---------------------------------------------------\n");
   464   snappy::Benchmark_BM_UFlat->Run();
   465   snappy::Benchmark_BM_UValidate->Run();
   466   snappy::Benchmark_BM_ZFlat->Run();
   468   fprintf(stderr, "\n");
   469 }
   471 #ifndef HAVE_GTEST
   473 static inline int RUN_ALL_TESTS() {
   474   fprintf(stderr, "Running correctness tests.\n");
   475   snappy::Test_CorruptedTest_VerifyCorrupted();
   476   snappy::Test_Snappy_SimpleTests();
   477   snappy::Test_Snappy_MaxBlowup();
   478   snappy::Test_Snappy_RandomData();
   479   snappy::Test_Snappy_FourByteOffset();
   480   snappy::Test_SnappyCorruption_TruncatedVarint();
   481   snappy::Test_SnappyCorruption_UnterminatedVarint();
   482   snappy::Test_Snappy_ReadPastEndOfBuffer();
   483   snappy::Test_Snappy_FindMatchLength();
   484   snappy::Test_Snappy_FindMatchLengthRandom();
   485   fprintf(stderr, "All tests passed.\n");
   487   return 0;
   488 }
   490 #endif  // HAVE_GTEST
   492 // For main().
   493 namespace snappy {
   495 static void CompressFile(const char* fname);
   496 static void UncompressFile(const char* fname);
   497 static void MeasureFile(const char* fname);
   499 }  // namespace
   501 using snappy::CompressFile;
   502 using snappy::UncompressFile;
   503 using snappy::MeasureFile;
   505 #endif  // UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_

mercurial