Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2011, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 // ---
     30 //
     31 // Some generically useful utility routines that in google-land would
     32 // be their own projects.  We make a shortened version here.
     33 
     34 #ifndef GFLAGS_UTIL_H_
     35 #define GFLAGS_UTIL_H_
     36 
     37 #include "config.h"
     38 
     39 #include <assert.h>
     40 #ifdef HAVE_INTTYPES_H
     41 #  include <inttypes.h>
     42 #endif
     43 #include <stdarg.h>     // for va_*
     44 #include <stdlib.h>
     45 #include <stdio.h>
     46 #include <iostream>
     47 #include <string>
     48 #include <errno.h>
     49 #ifdef HAVE_SYS_STAT_H
     50 #  include <sys/stat.h> // for mkdir
     51 #endif
     52 
     53 
     54 namespace GFLAGS_NAMESPACE {
     55 
     56 
     57 // This is used for unittests for death-testing.  It is defined in gflags.cc.
     58 extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
     59 
     60 // Work properly if either strtoll or strtoq is on this system.
     61 #if defined(strtoll) || defined(HAVE_STRTOLL)
     62 #  define strto64  strtoll
     63 #  define strtou64 strtoull
     64 #elif defined(HAVE_STRTOQ)
     65 #  define strto64  strtoq
     66 #  define strtou64 strtouq
     67 // Neither strtoll nor strtoq are defined.  I hope strtol works!
     68 #else
     69 #  define strto64  strtol
     70 #  define strtou64 strtoul
     71 #endif
     72 
     73 // If we have inttypes.h, it will have defined PRId32/etc for us.
     74 // If not, take our best guess.
     75 #ifndef PRId32
     76 #  define PRId32 "d"
     77 #endif
     78 #ifndef PRId64
     79 #  define PRId64 "lld"
     80 #endif
     81 #ifndef PRIu64
     82 #  define PRIu64 "llu"
     83 #endif
     84 
     85 typedef signed char int8;
     86 typedef unsigned char uint8;
     87 
     88 // -- utility macros ---------------------------------------------------------
     89 
     90 template <bool b> struct CompileAssert;
     91 template <> struct CompileAssert<true> {};
     92 #define COMPILE_ASSERT(expr, msg) \
     93   enum { assert_##msg = sizeof(CompileAssert<bool(expr)>) }
     94 
     95 // Returns the number of elements in an array.
     96 #define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
     97 
     98 
     99 // -- logging and testing ---------------------------------------------------
    100 
    101 // For now, we ignore the level for logging, and don't show *VLOG's at
    102 // all, except by hand-editing the lines below
    103 #define LOG(level)    std::cerr
    104 #define VLOG(level)   if (true) {} else std::cerr
    105 #define DVLOG(level)  if (true) {} else std::cerr
    106 
    107 // CHECK dies with a fatal error if condition is not true.  It is *not*
    108 // controlled by NDEBUG, so the check will be executed regardless of
    109 // compilation mode.  Therefore, it is safe to do things like:
    110 //    CHECK(fp->Write(x) == 4)
    111 // We allow stream-like objects after this for debugging, but they're ignored.
    112 #define EXPECT_TRUE(condition)                                  \
    113   if (true) {                                                   \
    114     if (!(condition)) {                                         \
    115       fprintf(stderr, "Check failed: %s\n", #condition);        \
    116       exit(1);                                                  \
    117     }                                                           \
    118   } else std::cerr << ""
    119 
    120 #define EXPECT_OP(op, val1, val2)                                       \
    121   if (true) {                                                           \
    122     if (!((val1) op (val2))) {                                          \
    123       fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2);   \
    124       exit(1);                                                          \
    125     }                                                                   \
    126   } else std::cerr << ""
    127 
    128 #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
    129 #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
    130 #define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
    131 #define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
    132 #define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
    133 #define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
    134 #define EXPECT_FALSE(cond)    EXPECT_TRUE(!(cond))
    135 
    136 // C99 declares isnan and isinf should be macros, so the #ifdef test
    137 // should be reliable everywhere.  Of course, it's not, but these
    138 // are testing pertty marginal functionality anyway, so it's ok to
    139 // not-run them even in situations they might, with effort, be made to work.
    140 #ifdef isnan  // Some compilers, like sun's for Solaris 10, don't define this
    141 #define EXPECT_NAN(arg)                                         \
    142   do {                                                          \
    143     if (!isnan(arg)) {                                          \
    144       fprintf(stderr, "Check failed: isnan(%s)\n", #arg);       \
    145       exit(1);                                                  \
    146     }                                                           \
    147   } while (0)
    148 #else
    149 #define EXPECT_NAN(arg)
    150 #endif
    151 
    152 #ifdef isinf  // Some compilers, like sun's for Solaris 10, don't define this
    153 #define EXPECT_INF(arg)                                         \
    154   do {                                                          \
    155     if (!isinf(arg)) {                                          \
    156       fprintf(stderr, "Check failed: isinf(%s)\n", #arg);       \
    157       exit(1);                                                  \
    158     }                                                           \
    159   } while (0)
    160 #else
    161 #define EXPECT_INF(arg)
    162 #endif
    163 
    164 #define EXPECT_DOUBLE_EQ(val1, val2)                                    \
    165   do {                                                                  \
    166     if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) {         \
    167       fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2);        \
    168       exit(1);                                                          \
    169     }                                                                   \
    170   } while (0)
    171 
    172 #define EXPECT_STREQ(val1, val2)                                        \
    173   do {                                                                  \
    174     if (strcmp((val1), (val2)) != 0) {                                  \
    175       fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2);   \
    176       exit(1);                                                          \
    177     }                                                                   \
    178   } while (0)
    179 
    180 // Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
    181 #define TEST_INIT                                                       \
    182   static std::vector<void (*)()> g_testlist;  /* the tests to run */    \
    183   static int RUN_ALL_TESTS() {                                          \
    184     std::vector<void (*)()>::const_iterator it;                         \
    185     for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {       \
    186       (*it)();   /* The test will error-exit if there's a problem. */   \
    187     }                                                                   \
    188     fprintf(stderr, "\nPassed %d tests\n\nPASS\n",                      \
    189             static_cast<int>(g_testlist.size()));                       \
    190     return 0;                                                           \
    191   }
    192 
    193 // Note that this macro uses a FlagSaver to keep tests isolated.
    194 #define TEST(a, b)                                      \
    195   struct Test_##a##_##b {                               \
    196     Test_##a##_##b() { g_testlist.push_back(&Run); }    \
    197     static void Run() {                                 \
    198       FlagSaver fs;                                     \
    199       fprintf(stderr, "Running test %s/%s\n", #a, #b);  \
    200       RunTest();                                        \
    201     }                                                   \
    202     static void RunTest();                              \
    203   };                                                    \
    204   static Test_##a##_##b g_test_##a##_##b;               \
    205   void Test_##a##_##b::RunTest()
    206 
    207 // This is a dummy class that eases the google->opensource transition.
    208 namespace testing {
    209 class Test {};
    210 }
    211 
    212 // Call this in a .cc file where you will later call EXPECT_DEATH
    213 #define EXPECT_DEATH_INIT                               \
    214   static bool g_called_exit;                            \
    215   static void CalledExit(int) { g_called_exit = true; }
    216 
    217 #define EXPECT_DEATH(fn, msg)                                           \
    218   do {                                                                  \
    219     g_called_exit = false;                                              \
    220     gflags_exitfunc = &CalledExit;                            \
    221     fn;                                                                 \
    222     gflags_exitfunc = &exit;    /* set back to its default */ \
    223     if (!g_called_exit) {                                               \
    224       fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn);      \
    225       exit(1);                                                          \
    226     }                                                                   \
    227   } while (0)
    228 
    229 #define GTEST_HAS_DEATH_TEST 1
    230 
    231 // -- path routines ----------------------------------------------------------
    232 
    233 // Tries to create the directory path as a temp-dir.  If it fails,
    234 // changes path to some directory it *can* create.
    235 #if defined(__MINGW32__)
    236 #include <io.h>
    237 inline void MakeTmpdir(std::string* path) {
    238   if (!path->empty()) {
    239 	path->append("/gflags_unittest_testdir");
    240 	int err = mkdir(path->c_str());
    241 	if (err == 0 || errno == EEXIST) return;
    242   }
    243   // I had trouble creating a directory in /tmp from mingw
    244   *path = "./gflags_unittest";
    245   mkdir(path->c_str());
    246 }
    247 #elif defined(_MSC_VER)
    248 #include <direct.h>
    249 inline void MakeTmpdir(std::string* path) {
    250   if (!path->empty()) {
    251 	int err = _mkdir(path->c_str());
    252 	if (err == 0 || errno == EEXIST) return;
    253   }
    254   char tmppath_buffer[1024];
    255   int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
    256   assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
    257   assert(tmppath_buffer[tmppath_len - 1] == '\\');   // API guarantees it
    258   *path = std::string(tmppath_buffer) + "gflags_unittest";
    259   _mkdir(path->c_str());
    260 }
    261 #else
    262 inline void MakeTmpdir(std::string* path) {
    263   if (!path->empty()) {
    264 	int err = mkdir(path->c_str(), 0755);
    265 	if (err == 0 || errno == EEXIST) return;
    266   }
    267   mkdir("/tmp/gflags_unittest", 0755);
    268 }
    269 #endif
    270 
    271 // -- string routines --------------------------------------------------------
    272 
    273 inline void InternalStringPrintf(std::string* output, const char* format,
    274                                  va_list ap) {
    275   char space[128];    // try a small buffer and hope it fits
    276 
    277   // It's possible for methods that use a va_list to invalidate
    278   // the data in it upon use.  The fix is to make a copy
    279   // of the structure before using it and use that copy instead.
    280   va_list backup_ap;
    281   va_copy(backup_ap, ap);
    282   int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
    283   va_end(backup_ap);
    284 
    285   if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
    286     output->append(space, bytes_written);
    287     return;
    288   }
    289 
    290   // Repeatedly increase buffer size until it fits.
    291   int length = sizeof(space);
    292   while (true) {
    293     if (bytes_written < 0) {
    294       // Older snprintf() behavior. :-(  Just try doubling the buffer size
    295       length *= 2;
    296     } else {
    297       // We need exactly "bytes_written+1" characters
    298       length = bytes_written+1;
    299     }
    300     char* buf = new char[length];
    301 
    302     // Restore the va_list before we use it again
    303     va_copy(backup_ap, ap);
    304     bytes_written = vsnprintf(buf, length, format, backup_ap);
    305     va_end(backup_ap);
    306 
    307     if ((bytes_written >= 0) && (bytes_written < length)) {
    308       output->append(buf, bytes_written);
    309       delete[] buf;
    310       return;
    311     }
    312     delete[] buf;
    313   }
    314 }
    315 
    316 // Clears output before writing to it.
    317 inline void SStringPrintf(std::string* output, const char* format, ...) {
    318   va_list ap;
    319   va_start(ap, format);
    320   output->clear();
    321   InternalStringPrintf(output, format, ap);
    322   va_end(ap);
    323 }
    324 
    325 inline void StringAppendF(std::string* output, const char* format, ...) {
    326   va_list ap;
    327   va_start(ap, format);
    328   InternalStringPrintf(output, format, ap);
    329   va_end(ap);
    330 }
    331 
    332 inline std::string StringPrintf(const char* format, ...) {
    333   va_list ap;
    334   va_start(ap, format);
    335   std::string output;
    336   InternalStringPrintf(&output, format, ap);
    337   va_end(ap);
    338   return output;
    339 }
    340 
    341 inline bool SafeGetEnv(const char *varname, std::string &valstr)
    342 {
    343 #if defined(_MSC_VER) && _MSC_VER >= 1400
    344 	char  *val;
    345 	size_t sz;
    346 	if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
    347 	valstr = val;
    348 	free(val);
    349 #else
    350 	const char * const val = getenv(varname);
    351 	if (!val) return false;
    352 	valstr = val;
    353 #endif
    354 	return true;
    355 }
    356 
    357 inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
    358 {
    359 #if defined(_MSC_VER) && _MSC_VER >= 1400
    360 	return fopen_s(fp, fname, mode);
    361 #else
    362 	assert(fp != NULL);
    363 	*fp = fopen(fname, mode);
    364     // errno only guaranteed to be set on failure
    365 	return ((*fp == NULL) ? errno : 0);
    366 #endif
    367 }
    368 
    369 
    370 } // namespace GFLAGS_NAMESPACE
    371 
    372 
    373 #endif  // GFLAGS_UTIL_H_
    374