blob: d10f2c5c3720607e3ae411ef54f39357ab040ae9 [file] [log] [blame]
Craig Silversteinb9f23482007-03-22 00:15:41 +00001// Copyright (c) 2006, 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// Author: Marius Eriksen
32//
33// For now, this unit test does not cover all features of
Craig Silversteine0b71e52008-09-19 19:32:05 +000034// gflags.cc
Craig Silversteinb9f23482007-03-22 00:15:41 +000035
Craig Silversteinab3d7652009-11-10 16:33:51 +000036#include "config_for_unittests.h"
Craig Silversteinb9f23482007-03-22 00:15:41 +000037#include <stdio.h>
Craig Silverstein83911c12008-03-27 20:11:07 +000038#include <stdlib.h> // for &exit
Craig Silversteinab3d7652009-11-10 16:33:51 +000039#include <assert.h>
Craig Silversteinb9f23482007-03-22 00:15:41 +000040#include <string.h>
Craig Silversteinab3d7652009-11-10 16:33:51 +000041#ifdef HAVE_UNISTD_H
Craig Silversteinb9f23482007-03-22 00:15:41 +000042#include <unistd.h> // for unlink()
Craig Silversteinab3d7652009-11-10 16:33:51 +000043#endif
44#ifdef HAVE_SYS_STAT_H
Craig Silversteinb9f23482007-03-22 00:15:41 +000045#include <sys/stat.h> // for mkdir()
Craig Silversteinab3d7652009-11-10 16:33:51 +000046#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +000047#include <math.h> // for isinf() and isnan()
48#include <vector>
49#include <string>
Craig Silverstein31c8edc2010-01-05 02:25:45 +000050
Craig Silversteinab3d7652009-11-10 16:33:51 +000051#include <gflags/gflags.h>
Craig Silverstein67914682008-08-21 00:50:59 +000052// I don't actually use this header file, but #include it under the
53// old location to make sure that the include-header-forwarding
Craig Silversteinab3d7652009-11-10 16:33:51 +000054// works. But don't bother on windows; the windows port is so new
55// it never had the old location-names.
Craig Silverstein31c8edc2010-01-05 02:25:45 +000056#ifndef _MSC_VER
Craig Silversteinab3d7652009-11-10 16:33:51 +000057#include <google/gflags_completions.h>
Craig Silverstein67914682008-08-21 00:50:59 +000058void (*unused_fn)() = &GOOGLE_NAMESPACE::HandleCommandLineCompletions;
Craig Silversteinab3d7652009-11-10 16:33:51 +000059#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +000060
Craig Silversteine0b71e52008-09-19 19:32:05 +000061using GOOGLE_NAMESPACE::int32;
62using GOOGLE_NAMESPACE::FlagRegisterer;
Craig Silversteinab3d7652009-11-10 16:33:51 +000063using GOOGLE_NAMESPACE::StringFromEnv;
64using GOOGLE_NAMESPACE::RegisterFlagValidator;
65using GOOGLE_NAMESPACE::CommandLineFlagInfo;
66using GOOGLE_NAMESPACE::GetAllFlags;
Craig Silversteinb9f23482007-03-22 00:15:41 +000067
Craig Silverstein83911c12008-03-27 20:11:07 +000068// Returns the number of elements in an array.
Craig Silversteineb208392007-08-15 19:44:54 +000069#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
70
Craig Silverstein688ea022009-09-11 00:15:50 +000071#if !defined(HAVE_SETENV) && defined(HAVE_PUTENV) // mingw, at least
72void setenv(const char* name, const char* value, int) {
73 // In windows, it's impossible to set a variable to the empty string.
74 // We handle this by setting it to "0" and the NUL-ing out the \0.
75 // cf http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
76 static const char* const kFakeZero = "0";
77 if (*value == '\0')
78 value = kFakeZero;
79 // Apparently the semantics of putenv() is that the input
80 // must live forever, so we leak memory here. :-(
81 const int nameval_len = strlen(name) + 1 + strlen(value) + 1;
82 char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
83 snprintf(nameval, nameval_len, "%s=%s", name, value);
84 putenv(nameval);
85 if (value == kFakeZero) {
86 nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
87 if (*getenv(name) != '\0')
88 *getenv(name) = '\0'; // works when putenv() copies nameval
89 }
90}
91#endif
92
Craig Silversteine0b71e52008-09-19 19:32:05 +000093DECLARE_string(tryfromenv); // in gflags.cc
Craig Silversteinb9f23482007-03-22 00:15:41 +000094
95DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
Craig Silverstein31c8edc2010-01-05 02:25:45 +000096#ifdef _MSC_VER // in MSVC, we run from the vsprojects directory
97DEFINE_string(srcdir, "..\\..",
98 "Source-dir root, needed to find gflags_unittest_flagfile");
99#else
Craig Silversteinab3d7652009-11-10 16:33:51 +0000100DEFINE_string(srcdir, StringFromEnv("SRCDIR", "."),
Craig Silversteineb208392007-08-15 19:44:54 +0000101 "Source-dir root, needed to find gflags_unittest_flagfile");
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000102#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +0000103
104DEFINE_bool(test_bool, false, "tests bool-ness");
105DEFINE_int32(test_int32, -1, "");
106DEFINE_int64(test_int64, -2, "");
107DEFINE_uint64(test_uint64, 2, "");
108DEFINE_double(test_double, -1.0, "");
109DEFINE_string(test_string, "initial", "");
110
111//
112// The below ugliness gets some additional code coverage in the -helpxml
113// and -helpmatch test cases having to do with string lengths and formatting
114//
115DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name,
116 false,
117 "extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning");
118
119DEFINE_string(test_str1, "initial", "");
120DEFINE_string(test_str2, "initial", "");
121DEFINE_string(test_str3, "initial", "");
122
123// This is used to test setting tryfromenv manually
124DEFINE_string(test_tryfromenv, "initial", "");
125
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000126// Don't try this at home!
127static int changeable_var = 12;
128DEFINE_int32(changeable_var, ++changeable_var, "");
129
130static int changeable_bool_var = 8008;
131DEFINE_bool(changeable_bool_var, ++changeable_bool_var == 8009, "");
132
133static int changeable_string_var = 0;
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000134static std::string ChangeableString() {
135 char r[] = {static_cast<char>('0' + ++changeable_string_var), '\0'};
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000136 return r;
137}
138DEFINE_string(changeable_string_var, ChangeableString(), "");
139
Craig Silversteinb9f23482007-03-22 00:15:41 +0000140// These are never used in this unittest, but can be used by
Craig Silversteine0b71e52008-09-19 19:32:05 +0000141// gflags_unittest.sh when it needs to specify flags
142// that are legal for gflags_unittest but don't need to
Craig Silversteinb9f23482007-03-22 00:15:41 +0000143// be a particular value.
144DEFINE_bool(unused_bool, true, "unused bool-ness");
145DEFINE_int32(unused_int32, -1001, "");
146DEFINE_int64(unused_int64, -2001, "");
147DEFINE_uint64(unused_uint64, 2000, "");
148DEFINE_double(unused_double, -1000.0, "");
149DEFINE_string(unused_string, "unused", "");
150
Craig Silverstein585a44a2007-10-18 20:08:26 +0000151// These flags are used by gflags_unittest.sh
152DEFINE_bool(changed_bool1, false, "changed");
153DEFINE_bool(changed_bool2, false, "changed");
154
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000155static bool AlwaysFail(const char* flag, bool value) { return value == false; }
156DEFINE_bool(always_fail, false, "will fail to validate when you set it");
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000157static bool dummy = RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail);
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000158
Craig Silversteinab3d7652009-11-10 16:33:51 +0000159// See the comment by GetAllFlags in commandlineflags.h
160static bool DeadlockIfCantLockInValidators(const char* flag, bool value) {
161 if (!value) {
162 return true;
163 }
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000164 std::vector<CommandLineFlagInfo> dummy;
Craig Silversteinab3d7652009-11-10 16:33:51 +0000165 GetAllFlags(&dummy);
166 return true;
167}
168DEFINE_bool(deadlock_if_cant_lock,
169 false,
170 "will deadlock if set to true and "
171 "if locking of registry in validators fails.");
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000172static bool dummy1 = RegisterFlagValidator(&FLAGS_deadlock_if_cant_lock,
173 DeadlockIfCantLockInValidators);
Craig Silversteinab3d7652009-11-10 16:33:51 +0000174
175// This is a pseudo-flag -- we want to register a flag with a filename
Craig Silversteine0b71e52008-09-19 19:32:05 +0000176// at the top level, but there is no way to do this except by faking
177// the filename.
178namespace fLI {
179 static const int32 FLAGS_nonotldflag1 = 12;
180 int32 FLAGS_tldflag1 = FLAGS_nonotldflag1;
181 int32 FLAGS_notldflag1 = FLAGS_nonotldflag1;
182 static FlagRegisterer o_tldflag1(
183 "tldflag1", "int32",
184 "should show up in --helpshort", "gflags_unittest.cc",
185 &FLAGS_tldflag1, &FLAGS_notldflag1);
186}
187using fLI::FLAGS_tldflag1;
188
189namespace fLI {
190 static const int32 FLAGS_nonotldflag2 = 23;
191 int32 FLAGS_tldflag2 = FLAGS_nonotldflag2;
192 int32 FLAGS_notldflag2 = FLAGS_nonotldflag2;
193 static FlagRegisterer o_tldflag2(
194 "tldflag2", "int32",
195 "should show up in --helpshort", "gflags_unittest.",
196 &FLAGS_tldflag2, &FLAGS_notldflag2);
197}
198using fLI::FLAGS_tldflag2;
199
Craig Silversteinb9f23482007-03-22 00:15:41 +0000200_START_GOOGLE_NAMESPACE_
201
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000202using std::string;
203using std::vector;
204
Craig Silversteinb9f23482007-03-22 00:15:41 +0000205// The following is some bare-bones testing infrastructure
206
207#define EXPECT_TRUE(cond) \
208 do { \
209 if (!(cond)) { \
210 fprintf(stderr, "Check failed: %s\n", #cond); \
211 exit(1); \
212 } \
213 } while (0)
214
215#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
216
217#define EXPECT_OP(op, val1, val2) \
218 do { \
219 if (!((val1) op (val2))) { \
220 fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
221 exit(1); \
222 } \
223 } while (0)
224
225#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
226#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
227#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
228#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
229
Craig Silverstein67914682008-08-21 00:50:59 +0000230// C99 declares isnan and isinf should be macros, so the #ifdef test
231// should be reliable everywhere. Of course, it's not, but these
232// are testing pertty marginal functionality anyway, so it's ok to
233// not-run them even in situations they might, with effort, be made to work.
234#ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
Craig Silverstein2b66a842007-06-12 23:59:42 +0000235#define EXPECT_NAN(arg) \
Craig Silversteinb9f23482007-03-22 00:15:41 +0000236 do { \
Craig Silverstein2b66a842007-06-12 23:59:42 +0000237 if (!isnan(arg)) { \
238 fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
239 exit(1); \
240 } \
241 } while (0)
Craig Silverstein67914682008-08-21 00:50:59 +0000242#else
243#define EXPECT_NAN(arg)
244#endif
Craig Silverstein2b66a842007-06-12 23:59:42 +0000245
Craig Silverstein67914682008-08-21 00:50:59 +0000246#ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
Craig Silverstein2b66a842007-06-12 23:59:42 +0000247#define EXPECT_INF(arg) \
248 do { \
249 if (!isinf(arg)) { \
250 fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
Craig Silversteinb9f23482007-03-22 00:15:41 +0000251 exit(1); \
252 } \
253 } while (0)
Craig Silverstein67914682008-08-21 00:50:59 +0000254#else
255#define EXPECT_INF(arg)
256#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +0000257
258#define EXPECT_DOUBLE_EQ(val1, val2) \
259 do { \
260 if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
261 fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
262 exit(1); \
263 } \
264 } while (0)
265
266#define EXPECT_STREQ(val1, val2) \
267 do { \
268 if (strcmp((val1), (val2)) != 0) { \
269 fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
270 exit(1); \
271 } \
272 } while (0)
273
274static bool g_called_exit;
275static void CalledExit(int) { g_called_exit = true; }
Craig Silversteinab3d7652009-11-10 16:33:51 +0000276extern GFLAGS_DLL_DECL void (*commandlineflags_exitfunc)(int); // in gflags.cc
Craig Silversteinb9f23482007-03-22 00:15:41 +0000277
278#define EXPECT_DEATH(fn, msg) \
279 do { \
280 g_called_exit = false; \
Craig Silversteinb9f23482007-03-22 00:15:41 +0000281 commandlineflags_exitfunc = &CalledExit; \
282 fn; \
283 commandlineflags_exitfunc = &exit; /* set back to its default */ \
284 if (!g_called_exit) { \
285 fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
286 exit(1); \
287 } \
288 } while (0)
289
290
291vector<void (*)()> g_testlist; // the tests to run
292
293#define TEST(a, b) \
294 struct Test_##a##_##b { \
295 Test_##a##_##b() { g_testlist.push_back(&Run); } \
Craig Silverstein688ea022009-09-11 00:15:50 +0000296 static void Run() { \
297 FlagSaver fs; \
298 fprintf(stderr, "Running test %s/%s\n", #a, #b); \
299 RunTest(); \
300 } \
Craig Silversteinb9f23482007-03-22 00:15:41 +0000301 static void RunTest(); \
302 }; \
303 static Test_##a##_##b g_test_##a##_##b; \
304 void Test_##a##_##b::RunTest()
305
306
307static int RUN_ALL_TESTS() {
308 vector<void (*)()>::const_iterator it;
309 for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
310 (*it)();
311 }
312 fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
313 return 0;
314}
315
316
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000317static string TmpFile(const string& basename) {
318#ifdef _MSC_VER
319 return FLAGS_test_tmpdir + "\\" + basename;
320#else
321 return FLAGS_test_tmpdir + "/" + basename;
322#endif
323}
324
325// Returns the definition of the --flagfile flag to be used in the tests.
326static const char* GetFlagFileFlag() {
327#ifdef _MSC_VER
328 static const string flagfile = FLAGS_srcdir + "\\src\\gflags_unittest_flagfile";
329#else
330 static const string flagfile = FLAGS_srcdir + "/src/gflags_unittest_flagfile";
331#endif
332 static const string flagfile_flag = string("--flagfile=") + flagfile;
333 return flagfile_flag.c_str();
334}
335
336
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000337// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
338// compiler error iff T1 and T2 are different types.
339template <typename T1, typename T2>
340struct CompileAssertTypesEqual;
341
342template <typename T>
343struct CompileAssertTypesEqual<T, T> {
344};
345
346
347template <typename Expected, typename Actual>
348void AssertIsType(Actual& x) {
349 CompileAssertTypesEqual<Expected, Actual>();
350}
351
352// Verify all the flags are the right type.
353TEST(FlagTypes, FlagTypes) {
354 AssertIsType<bool>(FLAGS_test_bool);
355 AssertIsType<int32>(FLAGS_test_int32);
356 AssertIsType<int64>(FLAGS_test_int64);
357 AssertIsType<uint64>(FLAGS_test_uint64);
358 AssertIsType<double>(FLAGS_test_double);
359 AssertIsType<string>(FLAGS_test_string);
360}
361
Craig Silversteinb9f23482007-03-22 00:15:41 +0000362// Death tests for "help" options.
363//
364// The help system automatically calls exit(1) when you specify any of
365// the help-related flags ("-helpmatch", "-helpxml") so we can't test
366// those mainline.
367
368// Tests that "-helpmatch" causes the process to die.
369TEST(ReadFlagsFromStringDeathTest, HelpMatch) {
370 EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true),
371 "");
372}
373
374
375// Tests that "-helpxml" causes the process to die.
376TEST(ReadFlagsFromStringDeathTest, HelpXml) {
377 EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
378 "");
379}
380
381
382// A subroutine needed for testing reading flags from a string.
383void TestFlagString(const string& flags,
384 const string& expected_string,
385 bool expected_bool,
386 int32 expected_int32,
387 double expected_double) {
388 EXPECT_TRUE(ReadFlagsFromString(flags,
389 GetArgv0(),
390 // errors are fatal
391 true));
392
393 EXPECT_EQ(expected_string, FLAGS_test_string);
394 EXPECT_EQ(expected_bool, FLAGS_test_bool);
395 EXPECT_EQ(expected_int32, FLAGS_test_int32);
396 EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double);
397}
398
399
400// Tests reading flags from a string.
401TEST(FlagFileTest, ReadFlagsFromString) {
402 TestFlagString(
403 // Flag string
404 "-test_string=continued\n"
405 "# some comments are in order\n"
406 "# some\n"
407 " # comments\n"
408 "#are\n"
409 " #trickier\n"
410 "# than others\n"
411 "-test_bool=true\n"
412 " -test_int32=1\n"
413 "-test_double=0.0\n",
414 // Expected values
415 "continued",
416 true,
417 1,
418 0.0);
419
420 TestFlagString(
421 // Flag string
422 "# let's make sure it can update values\n"
423 "-test_string=initial\n"
424 "-test_bool=false\n"
425 "-test_int32=123\n"
426 "-test_double=123.0\n",
427 // Expected values
428 "initial",
429 false,
430 123,
431 123.0);
432}
433
434// Tests the filename part of the flagfile
435TEST(FlagFileTest, FilenamesOurfileLast) {
436 FLAGS_test_string = "initial";
437 FLAGS_test_bool = false;
438 FLAGS_test_int32 = -1;
439 FLAGS_test_double = -1.0;
440 TestFlagString(
441 // Flag string
442 "-test_string=continued\n"
443 "# some comments are in order\n"
444 "# some\n"
445 " # comments\n"
446 "#are\n"
447 " #trickier\n"
448 "# than others\n"
449 "not_our_filename\n"
450 "-test_bool=true\n"
451 " -test_int32=1\n"
452 "gflags_unittest\n"
453 "-test_double=1000.0\n",
454 // Expected values
455 "continued",
456 false,
457 -1,
458 1000.0);
459}
460
461TEST(FlagFileTest, FilenamesOurfileFirst) {
462 FLAGS_test_string = "initial";
463 FLAGS_test_bool = false;
464 FLAGS_test_int32 = -1;
465 FLAGS_test_double = -1.0;
466 TestFlagString(
467 // Flag string
468 "-test_string=continued\n"
469 "# some comments are in order\n"
470 "# some\n"
471 " # comments\n"
472 "#are\n"
473 " #trickier\n"
474 "# than others\n"
475 "gflags_unittest\n"
476 "-test_bool=true\n"
477 " -test_int32=1\n"
478 "not_our_filename\n"
479 "-test_double=1000.0\n",
480 // Expected values
481 "continued",
482 true,
483 1,
484 -1.0);
485}
486
Craig Silverstein688ea022009-09-11 00:15:50 +0000487#ifdef HAVE_FNMATCH_H // otherwise glob isn't supported
Craig Silversteinb9f23482007-03-22 00:15:41 +0000488TEST(FlagFileTest, FilenamesOurfileGlob) {
489 FLAGS_test_string = "initial";
490 FLAGS_test_bool = false;
491 FLAGS_test_int32 = -1;
492 FLAGS_test_double = -1.0;
493 TestFlagString(
494 // Flag string
495 "-test_string=continued\n"
496 "# some comments are in order\n"
497 "# some\n"
498 " # comments\n"
499 "#are\n"
500 " #trickier\n"
501 "# than others\n"
502 "*flags*\n"
503 "-test_bool=true\n"
504 " -test_int32=1\n"
505 "flags\n"
506 "-test_double=1000.0\n",
507 // Expected values
508 "continued",
509 true,
510 1,
511 -1.0);
512}
513
514TEST(FlagFileTest, FilenamesOurfileInBigList) {
515 FLAGS_test_string = "initial";
516 FLAGS_test_bool = false;
517 FLAGS_test_int32 = -1;
518 FLAGS_test_double = -1.0;
519 TestFlagString(
520 // Flag string
521 "-test_string=continued\n"
522 "# some comments are in order\n"
523 "# some\n"
524 " # comments\n"
525 "#are\n"
526 " #trickier\n"
527 "# than others\n"
528 "*first* *flags* *third*\n"
529 "-test_bool=true\n"
530 " -test_int32=1\n"
531 "flags\n"
532 "-test_double=1000.0\n",
533 // Expected values
534 "continued",
535 true,
536 1,
537 -1.0);
538}
Craig Silverstein688ea022009-09-11 00:15:50 +0000539#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +0000540
541// Tests that a failed flag-from-string read keeps flags at default values
542TEST(FlagFileTest, FailReadFlagsFromString) {
543 FLAGS_test_int32 = 119;
544 string flags("# let's make sure it can update values\n"
545 "-test_string=non_initial\n"
546 "-test_bool=false\n"
547 "-test_int32=123\n"
548 "-test_double=illegal\n");
549
550 EXPECT_FALSE(ReadFlagsFromString(flags,
551 GetArgv0(),
552 // errors are fatal
553 false));
554
555 EXPECT_EQ(119, FLAGS_test_int32);
556 EXPECT_EQ("initial", FLAGS_test_string);
557}
558
559// Tests that flags can be set to ordinary values.
560TEST(SetFlagValueTest, OrdinaryValues) {
561 EXPECT_EQ("initial", FLAGS_test_str1);
562
563 SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
564 EXPECT_EQ("second", FLAGS_test_str1); // set; was default
565
566 SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
567 EXPECT_EQ("second", FLAGS_test_str1); // already set once
568
569 FLAGS_test_str1 = "initial";
570 SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
571 EXPECT_EQ("initial", FLAGS_test_str1); // still already set before
572
573 SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE);
574 EXPECT_EQ("third", FLAGS_test_str1); // changed value
575
576 SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT);
577 EXPECT_EQ("third", FLAGS_test_str1);
578 // value not changed (already set before)
579
580 EXPECT_EQ("initial", FLAGS_test_str2);
581
582 SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT);
583 EXPECT_EQ("second", FLAGS_test_str2); // changed (was default)
584
585 FLAGS_test_str2 = "extra";
586 EXPECT_EQ("extra", FLAGS_test_str2);
587
588 FLAGS_test_str2 = "second";
589 SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
590 EXPECT_EQ("third", FLAGS_test_str2); // still changed (was equal to default)
591
592 SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
593 EXPECT_EQ("fourth", FLAGS_test_str2); // changed (was default)
594
595 EXPECT_EQ("initial", FLAGS_test_str3);
596
597 SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
598 EXPECT_EQ("second", FLAGS_test_str3); // changed
599
600 FLAGS_test_str3 = "third";
601 SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT);
602 EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
603
604 SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
605 EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
606
607 SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE);
608 EXPECT_EQ("fourth", FLAGS_test_str3); // changed value
609}
610
611
612// Tests that flags can be set to exceptional values.
Craig Silverstein688ea022009-09-11 00:15:50 +0000613// Note: apparently MINGW doesn't parse inf and nan correctly:
614// http://www.mail-archive.com/bug-gnulib@gnu.org/msg09573.html
615// This url says FreeBSD also has a problem, but I didn't see that.
Craig Silversteinb9f23482007-03-22 00:15:41 +0000616TEST(SetFlagValueTest, ExceptionalValues) {
Craig Silverstein688ea022009-09-11 00:15:50 +0000617#if defined(isinf) && !defined(__MINGW32__)
Craig Silversteinb9f23482007-03-22 00:15:41 +0000618 EXPECT_EQ("test_double set to inf\n",
619 SetCommandLineOption("test_double", "inf"));
Craig Silverstein2b66a842007-06-12 23:59:42 +0000620 EXPECT_INF(FLAGS_test_double);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000621
622 EXPECT_EQ("test_double set to inf\n",
623 SetCommandLineOption("test_double", "INF"));
Craig Silverstein2b66a842007-06-12 23:59:42 +0000624 EXPECT_INF(FLAGS_test_double);
Craig Silverstein67914682008-08-21 00:50:59 +0000625#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +0000626
627 // set some bad values
628 EXPECT_EQ("",
629 SetCommandLineOption("test_double", "0.1xxx"));
630 EXPECT_EQ("",
631 SetCommandLineOption("test_double", " "));
632 EXPECT_EQ("",
633 SetCommandLineOption("test_double", ""));
Craig Silverstein688ea022009-09-11 00:15:50 +0000634#if defined(isinf) && !defined(__MINGW32__)
Craig Silversteinb9f23482007-03-22 00:15:41 +0000635 EXPECT_EQ("test_double set to -inf\n",
636 SetCommandLineOption("test_double", "-inf"));
Craig Silverstein2b66a842007-06-12 23:59:42 +0000637 EXPECT_INF(FLAGS_test_double);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000638 EXPECT_GT(0, FLAGS_test_double);
Craig Silverstein67914682008-08-21 00:50:59 +0000639#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +0000640
Craig Silverstein688ea022009-09-11 00:15:50 +0000641#if defined(isnan) && !defined(__MINGW32__)
Craig Silversteinb9f23482007-03-22 00:15:41 +0000642 EXPECT_EQ("test_double set to nan\n",
643 SetCommandLineOption("test_double", "NaN"));
Craig Silverstein2b66a842007-06-12 23:59:42 +0000644 EXPECT_NAN(FLAGS_test_double);
Craig Silverstein67914682008-08-21 00:50:59 +0000645#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +0000646}
647
648// Tests that integer flags can be specified in many ways
649TEST(SetFlagValueTest, DifferentRadices) {
650 EXPECT_EQ("test_int32 set to 12\n",
651 SetCommandLineOption("test_int32", "12"));
652
653 EXPECT_EQ("test_int32 set to 16\n",
654 SetCommandLineOption("test_int32", "0x10"));
655
656 EXPECT_EQ("test_int32 set to 34\n",
657 SetCommandLineOption("test_int32", "0X22"));
658
659 // Leading 0 is *not* octal; it's still decimal
660 EXPECT_EQ("test_int32 set to 10\n",
661 SetCommandLineOption("test_int32", "010"));
662}
663
664// Tests what happens when you try to set a flag to an illegal value
665TEST(SetFlagValueTest, IllegalValues) {
666 FLAGS_test_bool = true;
667 FLAGS_test_int32 = 119;
668 FLAGS_test_int64 = 1191;
669 FLAGS_test_uint64 = 11911;
670
671 EXPECT_EQ("",
672 SetCommandLineOption("test_bool", "12"));
673
674 EXPECT_EQ("",
675 SetCommandLineOption("test_int32", "7000000000000"));
676
677 // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
678#if 0
679 EXPECT_EQ("",
680 SetCommandLineOption("test_uint64", "-1"));
681#endif
682
683 EXPECT_EQ("",
684 SetCommandLineOption("test_int64", "not a number!"));
685
686 // Test the empty string with each type of input
687 EXPECT_EQ("", SetCommandLineOption("test_bool", ""));
688 EXPECT_EQ("", SetCommandLineOption("test_int32", ""));
689 EXPECT_EQ("", SetCommandLineOption("test_int64", ""));
690 EXPECT_EQ("", SetCommandLineOption("test_uint64", ""));
691 EXPECT_EQ("", SetCommandLineOption("test_double", ""));
692 EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", ""));
693
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000694 EXPECT_TRUE(FLAGS_test_bool);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000695 EXPECT_EQ(119, FLAGS_test_int32);
696 EXPECT_EQ(1191, FLAGS_test_int64);
697 EXPECT_EQ(11911, FLAGS_test_uint64);
698}
699
700
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000701// Tests that we only evaluate macro args once
702TEST(MacroArgs, EvaluateOnce) {
703 EXPECT_EQ(13, FLAGS_changeable_var);
704 // Make sure we don't ++ the value somehow, when evaluating the flag.
705 EXPECT_EQ(13, FLAGS_changeable_var);
706 // Make sure the macro only evaluated this var once.
707 EXPECT_EQ(13, changeable_var);
708 // Make sure the actual value and default value are the same
709 SetCommandLineOptionWithMode("changeable_var", "21", SET_FLAG_IF_DEFAULT);
710 EXPECT_EQ(21, FLAGS_changeable_var);
711}
712
713TEST(MacroArgs, EvaluateOnceBool) {
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000714 EXPECT_TRUE(FLAGS_changeable_bool_var);
715 EXPECT_TRUE(FLAGS_changeable_bool_var);
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000716 EXPECT_EQ(8009, changeable_bool_var);
717 SetCommandLineOptionWithMode("changeable_bool_var", "false",
718 SET_FLAG_IF_DEFAULT);
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000719 EXPECT_FALSE(FLAGS_changeable_bool_var);
Craig Silversteinc79c32d2008-07-22 23:29:39 +0000720}
721
722TEST(MacroArgs, EvaluateOnceStrings) {
723 EXPECT_EQ("1", FLAGS_changeable_string_var);
724 EXPECT_EQ("1", FLAGS_changeable_string_var);
725 EXPECT_EQ(1, changeable_string_var);
726 SetCommandLineOptionWithMode("changeable_string_var", "different",
727 SET_FLAG_IF_DEFAULT);
728 EXPECT_EQ("different", FLAGS_changeable_string_var);
729}
730
Craig Silversteinb9f23482007-03-22 00:15:41 +0000731// Tests that the FooFromEnv does the right thing
732TEST(FromEnvTest, LegalValues) {
733 setenv("BOOL_VAL1", "true", 1);
734 setenv("BOOL_VAL2", "false", 1);
735 setenv("BOOL_VAL3", "1", 1);
736 setenv("BOOL_VAL4", "F", 1);
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000737 EXPECT_TRUE(BoolFromEnv("BOOL_VAL1", false));
738 EXPECT_FALSE(BoolFromEnv("BOOL_VAL2", true));
739 EXPECT_TRUE(BoolFromEnv("BOOL_VAL3", false));
740 EXPECT_FALSE(BoolFromEnv("BOOL_VAL4", true));
741 EXPECT_TRUE(BoolFromEnv("BOOL_VAL_UNKNOWN", true));
742 EXPECT_FALSE(BoolFromEnv("BOOL_VAL_UNKNOWN", false));
Craig Silversteinb9f23482007-03-22 00:15:41 +0000743
744 setenv("INT_VAL1", "1", 1);
745 setenv("INT_VAL2", "-1", 1);
746 EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10));
747 EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10));
748 EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10));
749
750 setenv("INT_VAL3", "1099511627776", 1);
751 EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20));
752 EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20));
753 EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL3", 20));
754 EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20));
755
756 EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30));
757 EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL3", 30));
758 EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30));
759
760 // I pick values here that can be easily represented exactly in floating-point
761 setenv("DOUBLE_VAL1", "0.0", 1);
762 setenv("DOUBLE_VAL2", "1.0", 1);
763 setenv("DOUBLE_VAL3", "-1.0", 1);
764 EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0));
765 EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0));
766 EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0));
767 EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0));
768
769 setenv("STRING_VAL1", "", 1);
770 setenv("STRING_VAL2", "my happy string!", 1);
771 EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown"));
772 EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown"));
773 EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
774}
775
776// Tests that the FooFromEnv dies on parse-error
Craig Silversteine0b71e52008-09-19 19:32:05 +0000777TEST(FromEnvDeathTest, IllegalValues) {
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000778 setenv("BOOL_BAD1", "so true!", 1);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000779 setenv("BOOL_BAD2", "", 1);
780 EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable");
781 EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable");
782
783 setenv("INT_BAD1", "one", 1);
784 setenv("INT_BAD2", "100000000000000000", 1);
785 setenv("INT_BAD3", "0xx10", 1);
786 setenv("INT_BAD4", "", 1);
787 EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable");
788 EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable");
789 EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable");
790 EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable");
791
792 setenv("BIGINT_BAD1", "18446744073709551616000", 1);
793 EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable");
794 EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable");
795 EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable");
796 EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable");
797
798 setenv("BIGINT_BAD2", "-1", 1);
799 EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable");
800 EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable");
801 EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable");
802 EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable");
803 // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
804#if 0
805 EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable");
806#endif
807
808 setenv("DOUBLE_BAD1", "0.0.0", 1);
809 setenv("DOUBLE_BAD2", "", 1);
810 EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
811 EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
812}
813
814// Tests that FlagSaver can save the states of string flags.
815TEST(FlagSaverTest, CanSaveStringFlagStates) {
816 // 1. Initializes the flags.
817
818 // State of flag test_str1:
819 // default value - "initial"
820 // current value - "initial"
821 // not set - true
822
823 SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE);
824 // State of flag test_str2:
825 // default value - "initial"
826 // current value - "second"
827 // not set - false
828
829 SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
830 // State of flag test_str3:
831 // default value - "second"
832 // current value - "second"
833 // not set - true
834
835 // 2. Saves the flag states.
836
837 {
838 FlagSaver fs;
839
840 // 3. Modifies the flag states.
841
842 SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE);
843 EXPECT_EQ("second", FLAGS_test_str1);
844 // State of flag test_str1:
845 // default value - "second"
846 // current value - "second"
847 // not set - true
848
849 SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
850 EXPECT_EQ("second", FLAGS_test_str2);
851 // State of flag test_str2:
852 // default value - "third"
853 // current value - "second"
854 // not set - false
855
856 SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE);
857 EXPECT_EQ("third", FLAGS_test_str3);
858 // State of flag test_str1:
859 // default value - "second"
860 // current value - "third"
861 // not set - false
862
863 // 4. Restores the flag states.
864 }
865
866 // 5. Verifies that the states were restored.
867
868 // Verifies that the value of test_str1 was restored.
869 EXPECT_EQ("initial", FLAGS_test_str1);
870 // Verifies that the "not set" attribute of test_str1 was restored to true.
871 SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
872 EXPECT_EQ("second", FLAGS_test_str1);
873
874 // Verifies that the value of test_str2 was restored.
875 EXPECT_EQ("second", FLAGS_test_str2);
876 // Verifies that the "not set" attribute of test_str2 was restored to false.
877 SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
878 EXPECT_EQ("second", FLAGS_test_str2);
879
880 // Verifies that the value of test_str3 was restored.
881 EXPECT_EQ("second", FLAGS_test_str3);
882 // Verifies that the "not set" attribute of test_str3 was restored to true.
883 SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
884 EXPECT_EQ("fourth", FLAGS_test_str3);
885}
886
887
888// Tests that FlagSaver can save the values of various-typed flags.
889TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) {
890 // Initializes the flags.
891 FLAGS_test_bool = false;
892 FLAGS_test_int32 = -1;
893 FLAGS_test_int64 = -2;
894 FLAGS_test_uint64 = 3;
895 FLAGS_test_double = 4.0;
896 FLAGS_test_string = "good";
897
898 // Saves the flag states.
899 {
900 FlagSaver fs;
901
902 // Modifies the flags.
903 FLAGS_test_bool = true;
904 FLAGS_test_int32 = -5;
905 FLAGS_test_int64 = -6;
906 FLAGS_test_uint64 = 7;
907 FLAGS_test_double = 8.0;
908 FLAGS_test_string = "bad";
909
910 // Restores the flag states.
911 }
912
913 // Verifies the flag values were restored.
914 EXPECT_FALSE(FLAGS_test_bool);
915 EXPECT_EQ(-1, FLAGS_test_int32);
916 EXPECT_EQ(-2, FLAGS_test_int64);
917 EXPECT_EQ(3, FLAGS_test_uint64);
918 EXPECT_DOUBLE_EQ(4.0, FLAGS_test_double);
919 EXPECT_EQ("good", FLAGS_test_string);
920}
921
922TEST(GetAllFlagsTest, BaseTest) {
923 vector<CommandLineFlagInfo> flags;
924 GetAllFlags(&flags);
925 bool found_test_bool = false;
926 vector<CommandLineFlagInfo>::const_iterator i;
927 for (i = flags.begin(); i != flags.end(); ++i) {
928 if (i->name == "test_bool") {
929 found_test_bool = true;
930 EXPECT_EQ(i->type, "bool");
931 EXPECT_EQ(i->default_value, "false");
932 break;
933 }
934 }
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000935 EXPECT_TRUE(found_test_bool);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000936}
937
938TEST(ShowUsageWithFlagsTest, BaseTest) {
939 // TODO(csilvers): test this by allowing output other than to stdout.
940 // Not urgent since this functionality is tested via
941 // gflags_unittest.sh, though only through use of --help.
942}
943
944TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
945 // TODO(csilvers): test this by allowing output other than to stdout.
946 // Not urgent since this functionality is tested via
947 // gflags_unittest.sh, though only through use of --helpmatch.
948}
949
950// Note: all these argv-based tests depend on SetArgv being called
Craig Silverstein0baf4ab2011-01-14 21:58:28 +0000951// before ParseCommandLineFlags() in Main(), below.
Craig Silversteinb9f23482007-03-22 00:15:41 +0000952TEST(GetArgvsTest, BaseTest) {
953 vector<string> argvs = GetArgvs();
954 EXPECT_EQ(4, argvs.size());
955 EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]);
956 EXPECT_EQ("argv 2", argvs[1]);
957 EXPECT_EQ("3rd argv", argvs[2]);
958 EXPECT_EQ("argv #4", argvs[3]);
959}
960
961TEST(GetArgvTest, BaseTest) {
962 EXPECT_STREQ("/test/argv/for/gflags_unittest "
963 "argv 2 3rd argv argv #4", GetArgv());
964}
965
966TEST(GetArgv0Test, BaseTest) {
967 EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0());
968}
969
970TEST(GetArgvSumTest, BaseTest) {
971 // This number is just the sum of the ASCII values of all the chars
972 // in GetArgv().
973 EXPECT_EQ(4904, GetArgvSum());
974}
975
976TEST(ProgramInvocationNameTest, BaseTest) {
977 EXPECT_STREQ("/test/argv/for/gflags_unittest",
978 ProgramInvocationName());
979}
980
981TEST(ProgramInvocationShortNameTest, BaseTest) {
982 EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
983}
984
Craig Silverstein0baf4ab2011-01-14 21:58:28 +0000985TEST(ProgramUsageTest, BaseTest) { // Depends on arg to SetUsageMessage()
Craig Silversteinb9f23482007-03-22 00:15:41 +0000986 EXPECT_STREQ("/test/argv/for/gflags_unittest: "
987 "<useless flag> [...]\nDoes something useless.\n",
988 ProgramUsage());
989}
990
991TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) {
992 string value("will be changed");
Craig Silverstein690172b2007-04-20 21:16:33 +0000993 bool r = GetCommandLineOption("test_bool", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000994 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000995 EXPECT_EQ("false", value);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000996
Craig Silverstein690172b2007-04-20 21:16:33 +0000997 r = GetCommandLineOption("test_int32", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +0000998 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +0000999 EXPECT_EQ("-1", value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001000}
1001
1002TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) {
1003 FLAGS_test_int32 = 400;
1004 string value("will be changed");
Craig Silverstein690172b2007-04-20 21:16:33 +00001005 const bool r = GetCommandLineOption("test_int32", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001006 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001007 EXPECT_EQ("400", value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001008}
1009
1010TEST(GetCommandLineOptionTest, NameExistsAndWasSet) {
1011 SetCommandLineOption("test_int32", "700");
1012 string value("will be changed");
Craig Silverstein690172b2007-04-20 21:16:33 +00001013 const bool r = GetCommandLineOption("test_int32", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001014 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001015 EXPECT_EQ("700", value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001016}
1017
1018TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) {
1019 // This doesn't set the flag's value, but rather its default value.
1020 // is_default is still true, but the 'default' value returned has changed!
1021 SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT);
1022 string value("will be changed");
Craig Silverstein690172b2007-04-20 21:16:33 +00001023 const bool r = GetCommandLineOption("test_int32", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001024 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001025 EXPECT_EQ("800", value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001026 EXPECT_TRUE(GetCommandLineFlagInfoOrDie("test_int32").is_default);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001027}
1028
1029TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) {
1030 SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT);
1031 string value("will be changed");
Craig Silverstein690172b2007-04-20 21:16:33 +00001032 const bool r = GetCommandLineOption("test_int32", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001033 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001034 EXPECT_EQ("900", value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001035}
1036
1037TEST(GetCommandLineOptionTest, NameDoesNotExist) {
1038 string value("will not be changed");
Craig Silverstein690172b2007-04-20 21:16:33 +00001039 const bool r = GetCommandLineOption("test_int3210", &value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001040 EXPECT_FALSE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001041 EXPECT_EQ("will not be changed", value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001042}
1043
1044TEST(GetCommandLineFlagInfoTest, FlagExists) {
1045 CommandLineFlagInfo info;
1046 bool r = GetCommandLineFlagInfo("test_int32", &info);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001047 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001048 EXPECT_EQ("test_int32", info.name);
1049 EXPECT_EQ("int32", info.type);
1050 EXPECT_EQ("", info.description);
Craig Silverstein690172b2007-04-20 21:16:33 +00001051 EXPECT_EQ("-1", info.current_value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001052 EXPECT_EQ("-1", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001053 EXPECT_TRUE(info.is_default);
1054 EXPECT_FALSE(info.has_validator_fn);
Craig Silverstein690172b2007-04-20 21:16:33 +00001055
1056 FLAGS_test_bool = true;
Craig Silversteinb9f23482007-03-22 00:15:41 +00001057 r = GetCommandLineFlagInfo("test_bool", &info);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001058 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001059 EXPECT_EQ("test_bool", info.name);
1060 EXPECT_EQ("bool", info.type);
1061 EXPECT_EQ("tests bool-ness", info.description);
Craig Silverstein690172b2007-04-20 21:16:33 +00001062 EXPECT_EQ("true", info.current_value);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001063 EXPECT_EQ("false", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001064 EXPECT_FALSE(info.is_default);
1065 EXPECT_FALSE(info.has_validator_fn);
Craig Silverstein690172b2007-04-20 21:16:33 +00001066
1067 FLAGS_test_bool = false;
1068 r = GetCommandLineFlagInfo("test_bool", &info);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001069 EXPECT_TRUE(r);
Craig Silverstein690172b2007-04-20 21:16:33 +00001070 EXPECT_EQ("test_bool", info.name);
1071 EXPECT_EQ("bool", info.type);
1072 EXPECT_EQ("tests bool-ness", info.description);
1073 EXPECT_EQ("false", info.current_value);
1074 EXPECT_EQ("false", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001075 EXPECT_FALSE(info.is_default); // value is same, but flag *was* modified
1076 EXPECT_FALSE(info.has_validator_fn);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001077}
1078
1079TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) {
1080 CommandLineFlagInfo info;
Craig Silverstein690172b2007-04-20 21:16:33 +00001081 // Set to some random values that GetCommandLineFlagInfo should not change
1082 info.name = "name";
1083 info.type = "type";
1084 info.current_value = "curr";
1085 info.default_value = "def";
1086 info.filename = "/";
1087 info.is_default = false;
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001088 info.has_validator_fn = true;
Craig Silversteinb9f23482007-03-22 00:15:41 +00001089 bool r = GetCommandLineFlagInfo("test_int3210", &info);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001090 EXPECT_FALSE(r);
Craig Silverstein690172b2007-04-20 21:16:33 +00001091 EXPECT_EQ("name", info.name);
1092 EXPECT_EQ("type", info.type);
1093 EXPECT_EQ("", info.description);
1094 EXPECT_EQ("curr", info.current_value);
1095 EXPECT_EQ("def", info.default_value);
1096 EXPECT_EQ("/", info.filename);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001097 EXPECT_FALSE(info.is_default);
1098 EXPECT_TRUE(info.has_validator_fn);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001099}
1100
Craig Silverstein290da382007-03-28 21:54:07 +00001101TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) {
1102 CommandLineFlagInfo info;
1103 info = GetCommandLineFlagInfoOrDie("test_int32");
1104 EXPECT_EQ("test_int32", info.name);
1105 EXPECT_EQ("int32", info.type);
1106 EXPECT_EQ("", info.description);
Craig Silverstein690172b2007-04-20 21:16:33 +00001107 EXPECT_EQ("-1", info.current_value);
Craig Silverstein290da382007-03-28 21:54:07 +00001108 EXPECT_EQ("-1", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001109 EXPECT_TRUE(info.is_default);
Craig Silverstein290da382007-03-28 21:54:07 +00001110 info = GetCommandLineFlagInfoOrDie("test_bool");
1111 EXPECT_EQ("test_bool", info.name);
1112 EXPECT_EQ("bool", info.type);
1113 EXPECT_EQ("tests bool-ness", info.description);
Craig Silverstein690172b2007-04-20 21:16:33 +00001114 EXPECT_EQ("false", info.current_value);
Craig Silverstein290da382007-03-28 21:54:07 +00001115 EXPECT_EQ("false", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001116 EXPECT_TRUE(info.is_default);
1117 EXPECT_FALSE(info.has_validator_fn);
Craig Silverstein290da382007-03-28 21:54:07 +00001118}
1119
1120TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) {
1121 FLAGS_test_int32 = 400;
1122 CommandLineFlagInfo info;
1123 info = GetCommandLineFlagInfoOrDie("test_int32");
1124 EXPECT_EQ("test_int32", info.name);
1125 EXPECT_EQ("int32", info.type);
1126 EXPECT_EQ("", info.description);
Craig Silverstein690172b2007-04-20 21:16:33 +00001127 EXPECT_EQ("400", info.current_value);
Craig Silverstein290da382007-03-28 21:54:07 +00001128 EXPECT_EQ("-1", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001129 EXPECT_FALSE(info.is_default);
Craig Silverstein290da382007-03-28 21:54:07 +00001130 FLAGS_test_bool = true;
1131 info = GetCommandLineFlagInfoOrDie("test_bool");
1132 EXPECT_EQ("test_bool", info.name);
1133 EXPECT_EQ("bool", info.type);
1134 EXPECT_EQ("tests bool-ness", info.description);
Craig Silverstein690172b2007-04-20 21:16:33 +00001135 EXPECT_EQ("true", info.current_value);
Craig Silverstein290da382007-03-28 21:54:07 +00001136 EXPECT_EQ("false", info.default_value);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001137 EXPECT_FALSE(info.is_default);
1138 EXPECT_FALSE(info.has_validator_fn);
Craig Silverstein290da382007-03-28 21:54:07 +00001139}
1140
Craig Silversteine0b71e52008-09-19 19:32:05 +00001141TEST(GetCommandLineFlagInfoOrDieDeathTest, FlagDoesNotExist) {
Craig Silverstein290da382007-03-28 21:54:07 +00001142 EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"),
1143 ".*: flag test_int3210 does not exist");
1144}
1145
Craig Silversteinb9f23482007-03-22 00:15:41 +00001146
1147// These are lightly tested because they're deprecated. Basically,
1148// the tests are meant to cover how existing users use these functions,
1149// but not necessarily how new users could use them.
1150TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) {
1151 string s = CommandlineFlagsIntoString();
1152 EXPECT_NE(string::npos, s.find("--test_bool="));
1153}
1154
1155TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) {
1156 FLAGS_test_int32 = 10; // just to make the test more interesting
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001157 string filename(TmpFile("flagfile"));
Craig Silversteinb9f23482007-03-22 00:15:41 +00001158 unlink(filename.c_str()); // just to be safe
1159 const bool r = AppendFlagsIntoFile(filename, "not the real argv0");
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001160 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001161
1162 FILE* fp = fopen(filename.c_str(), "r");
1163 EXPECT_TRUE(fp != NULL);
1164 char line[8192];
Craig Silverstein24b4c592011-01-25 00:36:41 +00001165 EXPECT_TRUE(fgets(line, sizeof(line)-1, fp) != NULL); // get the first line
1166 // First line should be progname.
Craig Silversteinb9f23482007-03-22 00:15:41 +00001167 EXPECT_STREQ("not the real argv0\n", line);
1168
1169 bool found_bool = false, found_int32 = false;
1170 while (fgets(line, sizeof(line)-1, fp)) {
1171 line[sizeof(line)-1] = '\0'; // just to be safe
1172 if (strcmp(line, "--test_bool=false\n") == 0)
1173 found_bool = true;
1174 if (strcmp(line, "--test_int32=10\n") == 0)
1175 found_int32 = true;
1176 }
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001177 EXPECT_TRUE(found_int32);
1178 EXPECT_TRUE(found_bool);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001179 fclose(fp);
1180}
1181
1182TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
1183 FLAGS_test_int32 = -10; // just to make the test more interesting
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001184 string filename(TmpFile("flagfile2"));
Craig Silversteinb9f23482007-03-22 00:15:41 +00001185 unlink(filename.c_str()); // just to be safe
1186 bool r = AppendFlagsIntoFile(filename, GetArgv0());
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001187 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001188
1189 FLAGS_test_int32 = -11;
1190 r = ReadFromFlagsFile(filename, GetArgv0(), true);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001191 EXPECT_TRUE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001192 EXPECT_EQ(-10, FLAGS_test_int32);
Craig Silversteineb208392007-08-15 19:44:54 +00001193}
Craig Silversteinb9f23482007-03-22 00:15:41 +00001194
1195TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
1196 FLAGS_test_int32 = -20;
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001197 string filename(TmpFile("flagfile3"));
Craig Silversteinb9f23482007-03-22 00:15:41 +00001198 FILE* fp = fopen(filename.c_str(), "w");
1199 EXPECT_TRUE(fp != NULL);
1200 // Note the error in the bool assignment below...
1201 fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0());
1202 fclose(fp);
1203
1204 FLAGS_test_int32 = -22;
1205 const bool r = ReadFromFlagsFile(filename, GetArgv0(), false);
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001206 EXPECT_FALSE(r);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001207 EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take
1208}
1209
Craig Silverstein0baf4ab2011-01-14 21:58:28 +00001210TEST(FlagsSetBeforeInitTest, TryFromEnv) {
Craig Silversteinb9f23482007-03-22 00:15:41 +00001211 EXPECT_EQ("pre-set", FLAGS_test_tryfromenv);
1212}
1213
Craig Silversteineb208392007-08-15 19:44:54 +00001214// The following test case verifies that ParseCommandLineFlags() and
1215// ParseCommandLineNonHelpFlags() uses the last definition of a flag
1216// in case it's defined more than once.
1217
1218DEFINE_int32(test_flag, -1, "used for testing commandlineflags.cc");
1219
Craig Silversteineb208392007-08-15 19:44:54 +00001220// Parses and returns the --test_flag flag.
1221// If with_help is true, calls ParseCommandLineFlags; otherwise calls
1222// ParseCommandLineNonHelpFlags.
1223int32 ParseTestFlag(bool with_help, int argc, const char** const_argv) {
1224 FlagSaver fs; // Restores the flags before returning.
1225
1226 // Makes a copy of the input array s.t. it can be reused
1227 // (ParseCommandLineFlags() will alter the array).
1228 char** const argv_save = new char*[argc + 1];
1229 char** argv = argv_save;
1230 memcpy(argv, const_argv, sizeof(*argv)*(argc + 1));
1231
1232 if (with_help) {
1233 ParseCommandLineFlags(&argc, &argv, true);
1234 } else {
1235 ParseCommandLineNonHelpFlags(&argc, &argv, true);
1236 }
1237
1238 delete[] argv_save;
1239 return FLAGS_test_flag;
1240}
1241
1242TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
1243 WhenFlagIsDefinedTwiceOnCommandLine) {
1244 const char* argv[] = {
1245 "my_test",
1246 "--test_flag=1",
1247 "--test_flag=2",
1248 NULL,
1249 };
1250
1251 EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1252 EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1253}
1254
1255TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
1256 WhenFlagIsDefinedTwiceInFlagFile) {
1257 const char* argv[] = {
1258 "my_test",
1259 GetFlagFileFlag(),
1260 NULL,
1261 };
1262
1263 EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1264 EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1265}
1266
1267TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
1268 WhenFlagIsDefinedInCommandLineAndThenFlagFile) {
1269 const char* argv[] = {
1270 "my_test",
1271 "--test_flag=0",
1272 GetFlagFileFlag(),
1273 NULL,
1274 };
1275
1276 EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1277 EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1278}
1279
1280TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
1281 WhenFlagIsDefinedInFlagFileAndThenCommandLine) {
1282 const char* argv[] = {
1283 "my_test",
1284 GetFlagFileFlag(),
1285 "--test_flag=3",
1286 NULL,
1287 };
1288
1289 EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1290 EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1291}
1292
1293TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
1294 WhenFlagIsDefinedInCommandLineAndFlagFileAndThenCommandLine) {
1295 const char* argv[] = {
1296 "my_test",
1297 "--test_flag=0",
1298 GetFlagFileFlag(),
1299 "--test_flag=3",
1300 NULL,
1301 };
1302
1303 EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1304 EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1305}
1306
Craig Silverstein83911c12008-03-27 20:11:07 +00001307TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) {
1308 const char* argv[] = {
1309 "my_test",
1310 "--",
1311 "--test_flag=0",
1312 NULL,
1313 };
1314
1315 EXPECT_EQ(-1, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1316 EXPECT_EQ(-1, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1317}
1318
1319TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) {
1320 const char* argv[] = {
1321 "my_test",
1322 "--test_flag=7",
1323 "--",
1324 "--test_flag=0",
1325 NULL,
1326 };
1327
1328 EXPECT_EQ(7, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1329 EXPECT_EQ(7, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1330}
1331
1332TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) {
1333 const char* argv[] = {
1334 "my_test",
1335 "-",
1336 "--test_flag=0",
1337 NULL,
1338 };
1339
1340 EXPECT_EQ(0, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1341 EXPECT_EQ(0, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
1342}
1343
Craig Silversteine0b71e52008-09-19 19:32:05 +00001344TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001345 FlagIsCompletelyUnknown) {
1346 const char* argv[] = {
1347 "my_test",
1348 "--this_flag_does_not_exist",
1349 NULL,
1350 };
1351
1352 EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
1353 "unknown command line flag.*");
1354 EXPECT_DEATH(ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv),
1355 "unknown command line flag.*");
1356}
1357
Craig Silversteine0b71e52008-09-19 19:32:05 +00001358TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001359 BoolFlagIsCompletelyUnknown) {
1360 const char* argv[] = {
1361 "my_test",
1362 "--nothis_flag_does_not_exist",
1363 NULL,
1364 };
1365
1366 EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
1367 "unknown command line flag.*");
1368 EXPECT_DEATH(ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv),
1369 "unknown command line flag.*");
1370}
1371
Craig Silversteine0b71e52008-09-19 19:32:05 +00001372TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001373 FlagIsNotABool) {
1374 const char* argv[] = {
1375 "my_test",
1376 "--notest_string",
1377 NULL,
1378 };
1379
1380 EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
1381 "boolean value .* specified for .* command line flag");
1382 EXPECT_DEATH(ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv),
1383 "boolean value .* specified for .* command line flag");
1384}
1385
1386TEST(ParseCommandLineFlagsWrongFields,
1387 DescriptionIsInvalid) {
1388 // These must not be automatic variables, since command line flags
1389 // aren't unregistered and gUnit uses FlagSaver to save and restore
1390 // command line flags' values. If these are on the stack, then when
1391 // later tests attempt to save and restore their values, the stack
1392 // addresses of these variables will be overwritten... Stack smash!
1393 static bool current_storage;
1394 static bool defvalue_storage;
1395 FlagRegisterer fr("flag_name", "bool", 0, "filename",
1396 &current_storage, &defvalue_storage);
1397 CommandLineFlagInfo fi;
1398 EXPECT_TRUE(GetCommandLineFlagInfo("flag_name", &fi));
1399 EXPECT_EQ("", fi.description);
1400}
1401
1402static bool ValidateTestFlagIs5(const char* flagname, int32 flagval) {
1403 if (flagval == 5)
1404 return true;
1405 printf("%s isn't 5!\n", flagname);
1406 return false;
1407}
1408
1409static bool ValidateTestFlagIs10(const char* flagname, int32 flagval) {
1410 return flagval == 10;
1411}
1412
1413
1414TEST(FlagsValidator, ValidFlagViaArgv) {
1415 const char* argv[] = {
1416 "my_test",
1417 "--test_flag=5",
1418 NULL,
1419 };
1420 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1421 EXPECT_EQ(5, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
1422 // Undo the flag validator setting
1423 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1424}
1425
1426TEST(FlagsValidator, ValidFlagViaSetDefault) {
1427 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1428 // SetCommandLineOptionWithMode returns the empty string on error.
1429 EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5",
1430 SET_FLAG_IF_DEFAULT));
1431 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1432}
1433
1434TEST(FlagsValidator, ValidFlagViaSetValue) {
1435 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1436 FLAGS_test_flag = 100; // doesn't trigger the validator
1437 // SetCommandLineOptionWithMode returns the empty string on error.
1438 EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5",
1439 SET_FLAGS_VALUE));
1440 EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5",
1441 SET_FLAGS_DEFAULT));
1442 EXPECT_NE("", SetCommandLineOption("test_flag", "5"));
1443 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1444}
1445
Craig Silversteine0b71e52008-09-19 19:32:05 +00001446TEST(FlagsValidatorDeathTest, InvalidFlagViaArgv) {
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001447 const char* argv[] = {
1448 "my_test",
1449 "--test_flag=50",
1450 NULL,
1451 };
1452 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1453 EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
1454 "ERROR: failed validation of new value '50' for flag 'test_flag'");
1455 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1456}
1457
1458TEST(FlagsValidator, InvalidFlagViaSetDefault) {
1459 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1460 // SetCommandLineOptionWithMode returns the empty string on error.
1461 EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50",
1462 SET_FLAG_IF_DEFAULT));
1463 EXPECT_EQ(-1, FLAGS_test_flag); // the setting-to-50 should have failed
1464 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1465}
1466
1467TEST(FlagsValidator, InvalidFlagViaSetValue) {
1468 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1469 FLAGS_test_flag = 100; // doesn't trigger the validator
1470 // SetCommandLineOptionWithMode returns the empty string on error.
1471 EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50",
1472 SET_FLAGS_VALUE));
1473 EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50",
1474 SET_FLAGS_DEFAULT));
1475 EXPECT_EQ("", SetCommandLineOption("test_flag", "50"));
1476 EXPECT_EQ(100, FLAGS_test_flag); // the setting-to-50 should have failed
1477 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1478}
1479
Craig Silversteine0b71e52008-09-19 19:32:05 +00001480TEST(FlagsValidatorDeathTest, InvalidFlagNeverSet) {
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001481 // If a flag keeps its default value, and that default value is
1482 // invalid, we should die at argv-parse time.
1483 const char* argv[] = {
1484 "my_test",
1485 NULL,
1486 };
1487 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1488 EXPECT_DEATH(ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv),
1489 "ERROR: --test_flag must be set on the commandline");
1490}
1491
1492TEST(FlagsValidator, InvalidFlagPtr) {
1493 int32 dummy;
1494 EXPECT_FALSE(RegisterFlagValidator(NULL, &ValidateTestFlagIs5));
1495 EXPECT_FALSE(RegisterFlagValidator(&dummy, &ValidateTestFlagIs5));
1496}
1497
1498TEST(FlagsValidator, RegisterValidatorTwice) {
1499 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1500 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1501 EXPECT_FALSE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10));
1502 EXPECT_FALSE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10));
1503 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1504 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1505 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10));
1506 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1507}
1508
1509TEST(FlagsValidator, CommandLineFlagInfo) {
1510 CommandLineFlagInfo info;
1511 info = GetCommandLineFlagInfoOrDie("test_flag");
1512 EXPECT_FALSE(info.has_validator_fn);
1513
1514 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1515 info = GetCommandLineFlagInfoOrDie("test_flag");
1516 EXPECT_TRUE(info.has_validator_fn);
1517
1518 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1519 info = GetCommandLineFlagInfoOrDie("test_flag");
1520 EXPECT_FALSE(info.has_validator_fn);
1521}
1522
1523TEST(FlagsValidator, FlagSaver) {
1524 {
1525 FlagSaver fs;
1526 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001527 EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); // fails validation
Craig Silversteinc79c32d2008-07-22 23:29:39 +00001528 }
1529 EXPECT_NE("", SetCommandLineOption("test_flag", "50")); // validator is gone
1530
1531 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
1532 {
1533 FlagSaver fs;
1534 EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
1535 EXPECT_NE("", SetCommandLineOption("test_flag", "50")); // no validator
1536 }
1537 EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); // validator is back
1538}
1539
1540
Craig Silversteinb9f23482007-03-22 00:15:41 +00001541static int Main(int argc, char **argv) {
Craig Silverstein0baf4ab2011-01-14 21:58:28 +00001542 // We need to call SetArgv before SetUsage, so our "test" argv will
Craig Silversteinb9f23482007-03-22 00:15:41 +00001543 // win out over this executable's real argv. That makes running this
1544 // test with a real --help flag kinda annoying, unfortunately.
1545 const char* test_argv[] = { "/test/argv/for/gflags_unittest",
1546 "argv 2", "3rd argv", "argv #4" };
Craig Silversteineb208392007-08-15 19:44:54 +00001547 SetArgv(GET_ARRAY_SIZE(test_argv), test_argv);
Craig Silversteinb9f23482007-03-22 00:15:41 +00001548
1549 // The first arg is the usage message, also important for testing.
1550 string usage_message = (string(GetArgv0()) +
1551 ": <useless flag> [...]\nDoes something useless.\n");
1552
Craig Silverstein0baf4ab2011-01-14 21:58:28 +00001553 // We test setting tryfromenv manually, and making sure
1554 // ParseCommandLineFlags still evaluates it.
Craig Silversteinb9f23482007-03-22 00:15:41 +00001555 FLAGS_tryfromenv = "test_tryfromenv";
1556 setenv("FLAGS_test_tryfromenv", "pre-set", 1);
1557
Craig Silverstein585a44a2007-10-18 20:08:26 +00001558 // Modify flag values from declared default value in two ways.
1559 // The recommended way:
1560 SetCommandLineOptionWithMode("changed_bool1", "true", SET_FLAGS_DEFAULT);
1561 // The non-recommended way:
1562 FLAGS_changed_bool2 = true;
1563
Craig Silversteinb9f23482007-03-22 00:15:41 +00001564 SetUsageMessage(usage_message.c_str());
1565 ParseCommandLineFlags(&argc, &argv, true);
1566
Craig Silversteinab3d7652009-11-10 16:33:51 +00001567#if defined(__MINGW32__)
Craig Silverstein688ea022009-09-11 00:15:50 +00001568 // I had trouble creating a directory in /tmp from mingw
1569 FLAGS_test_tmpdir = "./gflags_unittest_testdir";
1570 mkdir(FLAGS_test_tmpdir.c_str()); // mingw has a weird one-arg mkdir
Craig Silverstein31c8edc2010-01-05 02:25:45 +00001571#elif defined(_MSC_VER)
Craig Silversteinab3d7652009-11-10 16:33:51 +00001572 char tmppath_buffer[1024];
1573 int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
1574 assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
1575 assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
1576 FLAGS_test_tmpdir = string(tmppath_buffer) + "gflags_unittest_testdir";
1577 _mkdir(FLAGS_test_tmpdir.c_str());
Craig Silverstein688ea022009-09-11 00:15:50 +00001578#else
Craig Silversteinb9f23482007-03-22 00:15:41 +00001579 mkdir(FLAGS_test_tmpdir.c_str(), 0755);
Craig Silverstein688ea022009-09-11 00:15:50 +00001580#endif
Craig Silversteinb9f23482007-03-22 00:15:41 +00001581
1582 return RUN_ALL_TESTS();
1583}
1584
1585_END_GOOGLE_NAMESPACE_
1586
1587int main(int argc, char** argv) {
Craig Silverstein0baf4ab2011-01-14 21:58:28 +00001588 const int exit_status = GOOGLE_NAMESPACE::Main(argc, argv);
1589 GOOGLE_NAMESPACE::ShutDownCommandLineFlags();
1590 return exit_status;
Craig Silversteinb9f23482007-03-22 00:15:41 +00001591}