+Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
+
+ * google-gflags: version 0.7
+ * Deal even more correctly with libpthread not linked in (csilvers)
+ * Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
+ * Be more accurate printing default flag values in --help (dsturtevant)
+ * Reduce .o file size a bit by using shorter namespace names (jeff)
+ * Use relative install path, so 'setup.py --home' works (csilvers)
+ * Notice when a boolean flag has a non-boolean default (bnmouli)
+ * Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
+ * Fix "no modules match" message for --helpshort, etc (hendrie)
+
Wed Aug 15 07:35:51 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.6
check_SCRIPTS =
# Every time you add a unittest to check_SCRIPTS, add it here too
noinst_SCRIPTS =
-
+# Used for auto-generated source files
+CLEANFILES =
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
lib_LTLIBRARIES += libgflags.la
libgflags_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
- src/gflags.cc src/gflags_reporting.cc
+ src/gflags.cc src/gflags_reporting.cc
libgflags_la_CXXFLAGS = $(PTRHEAD_CFLAGS) -DNDEBUG
libgflags_la_LDFLAGS = $(PTRHEAD_CFLAGS)
libgflags_la_LIBADD = $(PTHREAD_LIBS)
TESTS += gflags_unittest
gflags_unittest_SOURCES = $(googleinclude_HEADERS) src/config.h \
- src/gflags_unittest.cc
+ src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDADD = libgflags.la $(PTHREAD_LIBS)
gflags_nothreads_unittest_SOURCES = $(gflags_unittest_SOURCES)
gflags_nothreads_unittest_LDADD = libgflags.la
+# We also want to test that things work properly when the file that
+# holds main() has a name ending with -main or _main. To keep the
+# Makefile small :-), we test the no-threads version of these.
+TESTS += gflags_unittest2
+gflags_unittest2_SOURCES = $(googleinclude_HEADERS) src/config.h \
+ src/gflags_unittest-main.cc
+gflags_unittest2_LDADD = libgflags.la
+src/gflags_unittest-main.cc: src/gflags_unittest.cc
+ rm -f src/gflags_unittest-main.cc
+ cp -p src/gflags_unittest.cc src/gflags_unittest-main.cc
+CLEANFILES += src/gflags_unittest-main.cc
+
+TESTS += gflags_unittest3
+gflags_unittest3_SOURCES = $(googleinclude_HEADERS) src/config.h \
+ src/gflags_unittest_main.cc
+gflags_unittest3_LDADD = libgflags.la
+src/gflags_unittest_main.cc: src/gflags_unittest.cc
+ rm -f src/gflags_unittest_main.cc
+ cp -p src/gflags_unittest.cc src/gflags_unittest_main.cc
+CLEANFILES += src/gflags_unittest_main.cc
+
+
check_SCRIPTS += gflags_unittest_sh
noinst_SCRIPTS += src/gflags_unittest.sh
dist_noinst_DATA = $(top_srcdir)/src/gflags_unittest_flagfile
-gflags_unittest_sh: gflags_unittest
+gflags_unittest_sh: gflags_unittest gflags_unittest2 gflags_unittest3
$(top_srcdir)/src/gflags_unittest.sh $(PWD)/$< $(top_srcdir)
# These aren't part of the c++ source, but we want them to be distributed
libgflags_la-gflags_reporting.lo
libgflags_la_OBJECTS = $(am_libgflags_la_OBJECTS)
am__EXEEXT_1 = gflags_unittest$(EXEEXT) \
- gflags_nothreads_unittest$(EXEEXT)
+ gflags_nothreads_unittest$(EXEEXT) gflags_unittest2$(EXEEXT) \
+ gflags_unittest3$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
am__objects_2 = $(am__objects_1) gflags_unittest.$(OBJEXT)
am_gflags_nothreads_unittest_OBJECTS = $(am__objects_2)
gflags_unittest-gflags_unittest.$(OBJEXT)
gflags_unittest_OBJECTS = $(am_gflags_unittest_OBJECTS)
gflags_unittest_DEPENDENCIES = libgflags.la $(am__DEPENDENCIES_1)
+am_gflags_unittest2_OBJECTS = $(am__objects_1) \
+ gflags_unittest-main.$(OBJEXT)
+gflags_unittest2_OBJECTS = $(am_gflags_unittest2_OBJECTS)
+gflags_unittest2_DEPENDENCIES = libgflags.la
+am_gflags_unittest3_OBJECTS = $(am__objects_1) \
+ gflags_unittest_main.$(OBJEXT)
+gflags_unittest3_OBJECTS = $(am_gflags_unittest3_OBJECTS)
+gflags_unittest3_DEPENDENCIES = libgflags.la
SCRIPTS = $(noinst_SCRIPTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src
depcomp = $(SHELL) $(top_srcdir)/depcomp
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libgflags_la_SOURCES) $(gflags_nothreads_unittest_SOURCES) \
- $(gflags_unittest_SOURCES)
+ $(gflags_unittest_SOURCES) $(gflags_unittest2_SOURCES) \
+ $(gflags_unittest3_SOURCES)
DIST_SOURCES = $(libgflags_la_SOURCES) \
$(gflags_nothreads_unittest_SOURCES) \
- $(gflags_unittest_SOURCES)
+ $(gflags_unittest_SOURCES) $(gflags_unittest2_SOURCES) \
+ $(gflags_unittest3_SOURCES)
dist_docDATA_INSTALL = $(INSTALL_DATA)
DATA = $(dist_doc_DATA) $(dist_noinst_DATA)
googleincludeHEADERS_INSTALL = $(INSTALL_HEADER)
lib_LTLIBRARIES = libgflags.la
# Also make sure this works when we don't link in pthreads
-TESTS = gflags_unittest gflags_nothreads_unittest
+
+# We also want to test that things work properly when the file that
+# holds main() has a name ending with -main or _main. To keep the
+# Makefile small :-), we test the no-threads version of these.
+TESTS = gflags_unittest gflags_nothreads_unittest gflags_unittest2 \
+ gflags_unittest3
TESTS_ENVIRONMENT = SRCDIR="$(top_srcdir)"
check_SCRIPTS = gflags_unittest_sh
# Every time you add a unittest to check_SCRIPTS, add it here too
noinst_SCRIPTS = src/gflags_unittest.sh
+# Used for auto-generated source files
+CLEANFILES = src/gflags_unittest-main.cc src/gflags_unittest_main.cc
libgflags_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
- src/gflags.cc src/gflags_reporting.cc
+ src/gflags.cc src/gflags_reporting.cc
libgflags_la_CXXFLAGS = $(PTRHEAD_CFLAGS) -DNDEBUG
libgflags_la_LDFLAGS = $(PTRHEAD_CFLAGS)
libgflags_la_LIBADD = $(PTHREAD_LIBS)
gflags_unittest_SOURCES = $(googleinclude_HEADERS) src/config.h \
- src/gflags_unittest.cc
+ src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDADD = libgflags.la $(PTHREAD_LIBS)
gflags_nothreads_unittest_SOURCES = $(gflags_unittest_SOURCES)
gflags_nothreads_unittest_LDADD = libgflags.la
+gflags_unittest2_SOURCES = $(googleinclude_HEADERS) src/config.h \
+ src/gflags_unittest-main.cc
+
+gflags_unittest2_LDADD = libgflags.la
+gflags_unittest3_SOURCES = $(googleinclude_HEADERS) src/config.h \
+ src/gflags_unittest_main.cc
+
+gflags_unittest3_LDADD = libgflags.la
dist_noinst_DATA = $(top_srcdir)/src/gflags_unittest_flagfile
# These aren't part of the c++ source, but we want them to be distributed
gflags_unittest$(EXEEXT): $(gflags_unittest_OBJECTS) $(gflags_unittest_DEPENDENCIES)
@rm -f gflags_unittest$(EXEEXT)
$(CXXLINK) $(gflags_unittest_LDFLAGS) $(gflags_unittest_OBJECTS) $(gflags_unittest_LDADD) $(LIBS)
+gflags_unittest2$(EXEEXT): $(gflags_unittest2_OBJECTS) $(gflags_unittest2_DEPENDENCIES)
+ @rm -f gflags_unittest2$(EXEEXT)
+ $(CXXLINK) $(gflags_unittest2_LDFLAGS) $(gflags_unittest2_OBJECTS) $(gflags_unittest2_LDADD) $(LIBS)
+gflags_unittest3$(EXEEXT): $(gflags_unittest3_OBJECTS) $(gflags_unittest3_DEPENDENCIES)
+ @rm -f gflags_unittest3$(EXEEXT)
+ $(CXXLINK) $(gflags_unittest3_LDFLAGS) $(gflags_unittest3_OBJECTS) $(gflags_unittest3_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gflags_unittest-gflags_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gflags_unittest-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gflags_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gflags_unittest_main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgflags_la-gflags.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgflags_la-gflags_reporting.Plo@am__quote@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gflags_unittest_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest-gflags_unittest.obj `if test -f 'src/gflags_unittest.cc'; then $(CYGPATH_W) 'src/gflags_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest.cc'; fi`
+gflags_unittest-main.o: src/gflags_unittest-main.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gflags_unittest-main.o -MD -MP -MF "$(DEPDIR)/gflags_unittest-main.Tpo" -c -o gflags_unittest-main.o `test -f 'src/gflags_unittest-main.cc' || echo '$(srcdir)/'`src/gflags_unittest-main.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/gflags_unittest-main.Tpo" "$(DEPDIR)/gflags_unittest-main.Po"; else rm -f "$(DEPDIR)/gflags_unittest-main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_unittest-main.cc' object='gflags_unittest-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest-main.o `test -f 'src/gflags_unittest-main.cc' || echo '$(srcdir)/'`src/gflags_unittest-main.cc
+
+gflags_unittest-main.obj: src/gflags_unittest-main.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gflags_unittest-main.obj -MD -MP -MF "$(DEPDIR)/gflags_unittest-main.Tpo" -c -o gflags_unittest-main.obj `if test -f 'src/gflags_unittest-main.cc'; then $(CYGPATH_W) 'src/gflags_unittest-main.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest-main.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/gflags_unittest-main.Tpo" "$(DEPDIR)/gflags_unittest-main.Po"; else rm -f "$(DEPDIR)/gflags_unittest-main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_unittest-main.cc' object='gflags_unittest-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest-main.obj `if test -f 'src/gflags_unittest-main.cc'; then $(CYGPATH_W) 'src/gflags_unittest-main.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest-main.cc'; fi`
+
+gflags_unittest_main.o: src/gflags_unittest_main.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gflags_unittest_main.o -MD -MP -MF "$(DEPDIR)/gflags_unittest_main.Tpo" -c -o gflags_unittest_main.o `test -f 'src/gflags_unittest_main.cc' || echo '$(srcdir)/'`src/gflags_unittest_main.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/gflags_unittest_main.Tpo" "$(DEPDIR)/gflags_unittest_main.Po"; else rm -f "$(DEPDIR)/gflags_unittest_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_unittest_main.cc' object='gflags_unittest_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest_main.o `test -f 'src/gflags_unittest_main.cc' || echo '$(srcdir)/'`src/gflags_unittest_main.cc
+
+gflags_unittest_main.obj: src/gflags_unittest_main.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gflags_unittest_main.obj -MD -MP -MF "$(DEPDIR)/gflags_unittest_main.Tpo" -c -o gflags_unittest_main.obj `if test -f 'src/gflags_unittest_main.cc'; then $(CYGPATH_W) 'src/gflags_unittest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest_main.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/gflags_unittest_main.Tpo" "$(DEPDIR)/gflags_unittest_main.Po"; else rm -f "$(DEPDIR)/gflags_unittest_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_unittest_main.cc' object='gflags_unittest_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest_main.obj `if test -f 'src/gflags_unittest_main.cc'; then $(CYGPATH_W) 'src/gflags_unittest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest_main.cc'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
uninstall-googleincludeHEADERS uninstall-info-am \
uninstall-libLTLIBRARIES
-gflags_unittest_sh: gflags_unittest
+src/gflags_unittest-main.cc: src/gflags_unittest.cc
+ rm -f src/gflags_unittest-main.cc
+ cp -p src/gflags_unittest.cc src/gflags_unittest-main.cc
+src/gflags_unittest_main.cc: src/gflags_unittest.cc
+ rm -f src/gflags_unittest_main.cc
+ cp -p src/gflags_unittest.cc src/gflags_unittest_main.cc
+gflags_unittest_sh: gflags_unittest gflags_unittest2 gflags_unittest3
$(top_srcdir)/src/gflags_unittest.sh $(PWD)/$< $(top_srcdir)
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for gflags 0.6.
+# Generated by GNU Autoconf 2.59 for gflags 0.7.
#
# Report bugs to <opensource@google.com>.
#
# Identity of this package.
PACKAGE_NAME='gflags'
PACKAGE_TARNAME='gflags'
-PACKAGE_VERSION='0.6'
-PACKAGE_STRING='gflags 0.6'
+PACKAGE_VERSION='0.7'
+PACKAGE_STRING='gflags 0.7'
PACKAGE_BUGREPORT='opensource@google.com'
ac_unique_file="README"
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures gflags 0.6 to adapt to many kinds of systems.
+\`configure' configures gflags 0.7 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gflags 0.6:";;
+ short | recursive ) echo "Configuration of gflags 0.7:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-gflags configure 0.6
+gflags configure 0.7
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by gflags $as_me 0.6, which was
+It was created by gflags $as_me 0.7, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='gflags'
- VERSION='0.6'
+ VERSION='0.7'
cat >>confdefs.h <<_ACEOF
} >&5
cat >&5 <<_CSEOF
-This file was extended by gflags $as_me 0.6, which was
+This file was extended by gflags $as_me 0.7, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-gflags config.status 0.6
+gflags config.status 0.7
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
# make sure we're interpreted by some minimal autoconf
AC_PREREQ(2.57)
-AC_INIT(gflags, 0.6, opensource@google.com)
+AC_INIT(gflags, 0.7, opensource@google.com)
# The argument here is just something that should be in the current directory
# (for sanity checking)
AC_CONFIG_SRCDIR(README)
methods such as <code>google::SetUsageMessage</code>, see
<code>gflags.h</code>.</p>
+
+<h2> <A name="misc">Miscellaneous Notes</code> </h2>
+
+<p>If your application has code like this:</p>
+<pre>
+ #define STRIP_FLAG_HELP 1 // this must go before the #include!
+ #include <google/gflags.h>
+</pre>
+<p>we will remove the help messages from the compiled source. This can
+reduce the size of the resulting binary somewhat, and may also be
+useful for security reasons.</p>
+
+
<hr>
<address>
Craig Silverstein<br>
--- /dev/null
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Marius Eriksen
+//
+// For now, this unit test does not cover all features of
+// commandlineflags.cc
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h> // for unlink()
+#include <sys/stat.h> // for mkdir()
+#include <math.h> // for isinf() and isnan()
+#include <vector>
+#include <string>
+#include "google/gflags.h"
+
+using std::vector;
+using std::string;
+
+// Returns the number of elements in an array. We don't use the safer
+// version in base/basictypes.h as commandlineflags is open-sourced.
+#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
+
+DECLARE_string(tryfromenv); // in commandlineflags.cc
+
+DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
+DEFINE_string(srcdir, google::StringFromEnv("SRCDIR", "."),
+ "Source-dir root, needed to find gflags_unittest_flagfile");
+
+
+DEFINE_bool(test_bool, false, "tests bool-ness");
+DEFINE_int32(test_int32, -1, "");
+DEFINE_int64(test_int64, -2, "");
+DEFINE_uint64(test_uint64, 2, "");
+DEFINE_double(test_double, -1.0, "");
+DEFINE_string(test_string, "initial", "");
+
+//
+// The below ugliness gets some additional code coverage in the -helpxml
+// and -helpmatch test cases having to do with string lengths and formatting
+//
+DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name,
+ false,
+ "extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning");
+
+DEFINE_string(test_str1, "initial", "");
+DEFINE_string(test_str2, "initial", "");
+DEFINE_string(test_str3, "initial", "");
+
+// This is used to test setting tryfromenv manually
+DEFINE_string(test_tryfromenv, "initial", "");
+
+// These are never used in this unittest, but can be used by
+// commandlineflags_unittest.sh when it needs to specify flags
+// that are legal for commandlineflags_unittest but don't need to
+// be a particular value.
+DEFINE_bool(unused_bool, true, "unused bool-ness");
+DEFINE_int32(unused_int32, -1001, "");
+DEFINE_int64(unused_int64, -2001, "");
+DEFINE_uint64(unused_uint64, 2000, "");
+DEFINE_double(unused_double, -1000.0, "");
+DEFINE_string(unused_string, "unused", "");
+
+_START_GOOGLE_NAMESPACE_
+
+// The following is some bare-bones testing infrastructure
+
+#define EXPECT_TRUE(cond) \
+ do { \
+ if (!(cond)) { \
+ fprintf(stderr, "Check failed: %s\n", #cond); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
+
+#define EXPECT_OP(op, val1, val2) \
+ do { \
+ if (!((val1) op (val2))) { \
+ fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
+#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
+#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
+#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
+
+#define EXPECT_NAN(arg) \
+ do { \
+ if (!isnan(arg)) { \
+ fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_INF(arg) \
+ do { \
+ if (!isinf(arg)) { \
+ fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_DOUBLE_EQ(val1, val2) \
+ do { \
+ if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
+ fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_STREQ(val1, val2) \
+ do { \
+ if (strcmp((val1), (val2)) != 0) { \
+ fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+static bool g_called_exit;
+static void CalledExit(int) { g_called_exit = true; }
+
+#define EXPECT_DEATH(fn, msg) \
+ do { \
+ g_called_exit = false; \
+ extern void (*commandlineflags_exitfunc)(int); /* in gflags.cc */ \
+ commandlineflags_exitfunc = &CalledExit; \
+ fn; \
+ commandlineflags_exitfunc = &exit; /* set back to its default */ \
+ if (!g_called_exit) { \
+ fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
+ exit(1); \
+ } \
+ } while (0)
+
+
+vector<void (*)()> g_testlist; // the tests to run
+
+#define TEST(a, b) \
+ struct Test_##a##_##b { \
+ Test_##a##_##b() { g_testlist.push_back(&Run); } \
+ static void Run() { FlagSaver fs; RunTest(); } \
+ static void RunTest(); \
+ }; \
+ static Test_##a##_##b g_test_##a##_##b; \
+ void Test_##a##_##b::RunTest()
+
+
+static int RUN_ALL_TESTS() {
+ vector<void (*)()>::const_iterator it;
+ for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
+ (*it)();
+ }
+ fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
+ return 0;
+}
+
+
+// Death tests for "help" options.
+//
+// The help system automatically calls exit(1) when you specify any of
+// the help-related flags ("-helpmatch", "-helpxml") so we can't test
+// those mainline.
+
+// Tests that "-helpmatch" causes the process to die.
+TEST(ReadFlagsFromStringDeathTest, HelpMatch) {
+ EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true),
+ "");
+}
+
+
+// Tests that "-helpxml" causes the process to die.
+TEST(ReadFlagsFromStringDeathTest, HelpXml) {
+ EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
+ "");
+}
+
+
+// A subroutine needed for testing reading flags from a string.
+void TestFlagString(const string& flags,
+ const string& expected_string,
+ bool expected_bool,
+ int32 expected_int32,
+ double expected_double) {
+ EXPECT_TRUE(ReadFlagsFromString(flags,
+ GetArgv0(),
+ // errors are fatal
+ true));
+
+ EXPECT_EQ(expected_string, FLAGS_test_string);
+ EXPECT_EQ(expected_bool, FLAGS_test_bool);
+ EXPECT_EQ(expected_int32, FLAGS_test_int32);
+ EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double);
+}
+
+
+// Tests reading flags from a string.
+TEST(FlagFileTest, ReadFlagsFromString) {
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "-test_double=0.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ 0.0);
+
+ TestFlagString(
+ // Flag string
+ "# let's make sure it can update values\n"
+ "-test_string=initial\n"
+ "-test_bool=false\n"
+ "-test_int32=123\n"
+ "-test_double=123.0\n",
+ // Expected values
+ "initial",
+ false,
+ 123,
+ 123.0);
+}
+
+// Tests the filename part of the flagfile
+TEST(FlagFileTest, FilenamesOurfileLast) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "not_our_filename\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "gflags_unittest\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ false,
+ -1,
+ 1000.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileFirst) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "gflags_unittest\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "not_our_filename\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ -1.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileGlob) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "*flags*\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "flags\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ -1.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileInBigList) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "*first* *flags* *third*\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "flags\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ -1.0);
+}
+
+// Tests that a failed flag-from-string read keeps flags at default values
+TEST(FlagFileTest, FailReadFlagsFromString) {
+ FLAGS_test_int32 = 119;
+ string flags("# let's make sure it can update values\n"
+ "-test_string=non_initial\n"
+ "-test_bool=false\n"
+ "-test_int32=123\n"
+ "-test_double=illegal\n");
+
+ EXPECT_FALSE(ReadFlagsFromString(flags,
+ GetArgv0(),
+ // errors are fatal
+ false));
+
+ EXPECT_EQ(119, FLAGS_test_int32);
+ EXPECT_EQ("initial", FLAGS_test_string);
+}
+
+// Tests that flags can be set to ordinary values.
+TEST(SetFlagValueTest, OrdinaryValues) {
+ EXPECT_EQ("initial", FLAGS_test_str1);
+
+ SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str1); // set; was default
+
+ SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str1); // already set once
+
+ FLAGS_test_str1 = "initial";
+ SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("initial", FLAGS_test_str1); // still already set before
+
+ SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE);
+ EXPECT_EQ("third", FLAGS_test_str1); // changed value
+
+ SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str1);
+ // value not changed (already set before)
+
+ EXPECT_EQ("initial", FLAGS_test_str2);
+
+ SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str2); // changed (was default)
+
+ FLAGS_test_str2 = "extra";
+ EXPECT_EQ("extra", FLAGS_test_str2);
+
+ FLAGS_test_str2 = "second";
+ SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str2); // still changed (was equal to default)
+
+ SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("fourth", FLAGS_test_str2); // changed (was default)
+
+ EXPECT_EQ("initial", FLAGS_test_str3);
+
+ SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str3); // changed
+
+ FLAGS_test_str3 = "third";
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
+
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
+
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE);
+ EXPECT_EQ("fourth", FLAGS_test_str3); // changed value
+}
+
+
+// Tests that flags can be set to exceptional values.
+TEST(SetFlagValueTest, ExceptionalValues) {
+ EXPECT_EQ("test_double set to inf\n",
+ SetCommandLineOption("test_double", "inf"));
+ EXPECT_INF(FLAGS_test_double);
+
+ EXPECT_EQ("test_double set to inf\n",
+ SetCommandLineOption("test_double", "INF"));
+ EXPECT_INF(FLAGS_test_double);
+
+ // set some bad values
+ EXPECT_EQ("",
+ SetCommandLineOption("test_double", "0.1xxx"));
+ EXPECT_EQ("",
+ SetCommandLineOption("test_double", " "));
+ EXPECT_EQ("",
+ SetCommandLineOption("test_double", ""));
+ EXPECT_EQ("test_double set to -inf\n",
+ SetCommandLineOption("test_double", "-inf"));
+ EXPECT_INF(FLAGS_test_double);
+ EXPECT_GT(0, FLAGS_test_double);
+
+ EXPECT_EQ("test_double set to nan\n",
+ SetCommandLineOption("test_double", "NaN"));
+ EXPECT_NAN(FLAGS_test_double);
+}
+
+// Tests that integer flags can be specified in many ways
+TEST(SetFlagValueTest, DifferentRadices) {
+ EXPECT_EQ("test_int32 set to 12\n",
+ SetCommandLineOption("test_int32", "12"));
+
+ EXPECT_EQ("test_int32 set to 16\n",
+ SetCommandLineOption("test_int32", "0x10"));
+
+ EXPECT_EQ("test_int32 set to 34\n",
+ SetCommandLineOption("test_int32", "0X22"));
+
+ // Leading 0 is *not* octal; it's still decimal
+ EXPECT_EQ("test_int32 set to 10\n",
+ SetCommandLineOption("test_int32", "010"));
+}
+
+// Tests what happens when you try to set a flag to an illegal value
+TEST(SetFlagValueTest, IllegalValues) {
+ FLAGS_test_bool = true;
+ FLAGS_test_int32 = 119;
+ FLAGS_test_int64 = 1191;
+ FLAGS_test_uint64 = 11911;
+
+ EXPECT_EQ("",
+ SetCommandLineOption("test_bool", "12"));
+
+ EXPECT_EQ("",
+ SetCommandLineOption("test_int32", "7000000000000"));
+
+ // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
+#if 0
+ EXPECT_EQ("",
+ SetCommandLineOption("test_uint64", "-1"));
+#endif
+
+ EXPECT_EQ("",
+ SetCommandLineOption("test_int64", "not a number!"));
+
+ // Test the empty string with each type of input
+ EXPECT_EQ("", SetCommandLineOption("test_bool", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_int32", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_int64", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_uint64", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_double", ""));
+ EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", ""));
+
+ EXPECT_EQ(true, FLAGS_test_bool);
+ EXPECT_EQ(119, FLAGS_test_int32);
+ EXPECT_EQ(1191, FLAGS_test_int64);
+ EXPECT_EQ(11911, FLAGS_test_uint64);
+}
+
+
+// Tests that the FooFromEnv does the right thing
+TEST(FromEnvTest, LegalValues) {
+ setenv("BOOL_VAL1", "true", 1);
+ setenv("BOOL_VAL2", "false", 1);
+ setenv("BOOL_VAL3", "1", 1);
+ setenv("BOOL_VAL4", "F", 1);
+ EXPECT_EQ(true, BoolFromEnv("BOOL_VAL1", false));
+ EXPECT_EQ(false, BoolFromEnv("BOOL_VAL2", true));
+ EXPECT_EQ(true, BoolFromEnv("BOOL_VAL3", false));
+ EXPECT_EQ(false, BoolFromEnv("BOOL_VAL4", true));
+ EXPECT_EQ(true, BoolFromEnv("BOOL_VAL_UNKNOWN", true));
+ EXPECT_EQ(false, BoolFromEnv("BOOL_VAL_UNKNOWN", false));
+
+ setenv("INT_VAL1", "1", 1);
+ setenv("INT_VAL2", "-1", 1);
+ EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10));
+ EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10));
+ EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10));
+
+ setenv("INT_VAL3", "1099511627776", 1);
+ EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20));
+ EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20));
+ EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL3", 20));
+ EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20));
+
+ EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30));
+ EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL3", 30));
+ EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30));
+
+ // I pick values here that can be easily represented exactly in floating-point
+ setenv("DOUBLE_VAL1", "0.0", 1);
+ setenv("DOUBLE_VAL2", "1.0", 1);
+ setenv("DOUBLE_VAL3", "-1.0", 1);
+ EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0));
+ EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0));
+ EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0));
+ EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0));
+
+ setenv("STRING_VAL1", "", 1);
+ setenv("STRING_VAL2", "my happy string!", 1);
+ EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown"));
+ EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown"));
+ EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
+}
+
+// Tests that the FooFromEnv dies on parse-error
+TEST(FromEnvTest, IllegalValues) {
+ setenv("BOOL_BAD1", "so true!",1 );
+ setenv("BOOL_BAD2", "", 1);
+ EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable");
+ EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable");
+
+ setenv("INT_BAD1", "one", 1);
+ setenv("INT_BAD2", "100000000000000000", 1);
+ setenv("INT_BAD3", "0xx10", 1);
+ setenv("INT_BAD4", "", 1);
+ EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable");
+ EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable");
+ EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable");
+ EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable");
+
+ setenv("BIGINT_BAD1", "18446744073709551616000", 1);
+ EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable");
+ EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable");
+ EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable");
+ EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable");
+
+ setenv("BIGINT_BAD2", "-1", 1);
+ EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable");
+ EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable");
+ EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable");
+ EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable");
+ // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
+#if 0
+ EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable");
+#endif
+
+ setenv("DOUBLE_BAD1", "0.0.0", 1);
+ setenv("DOUBLE_BAD2", "", 1);
+ EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
+ EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
+}
+
+// Tests that FlagSaver can save the states of string flags.
+TEST(FlagSaverTest, CanSaveStringFlagStates) {
+ // 1. Initializes the flags.
+
+ // State of flag test_str1:
+ // default value - "initial"
+ // current value - "initial"
+ // not set - true
+
+ SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE);
+ // State of flag test_str2:
+ // default value - "initial"
+ // current value - "second"
+ // not set - false
+
+ SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
+ // State of flag test_str3:
+ // default value - "second"
+ // current value - "second"
+ // not set - true
+
+ // 2. Saves the flag states.
+
+ {
+ FlagSaver fs;
+
+ // 3. Modifies the flag states.
+
+ SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE);
+ EXPECT_EQ("second", FLAGS_test_str1);
+ // State of flag test_str1:
+ // default value - "second"
+ // current value - "second"
+ // not set - true
+
+ SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str2);
+ // State of flag test_str2:
+ // default value - "third"
+ // current value - "second"
+ // not set - false
+
+ SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE);
+ EXPECT_EQ("third", FLAGS_test_str3);
+ // State of flag test_str1:
+ // default value - "second"
+ // current value - "third"
+ // not set - false
+
+ // 4. Restores the flag states.
+ }
+
+ // 5. Verifies that the states were restored.
+
+ // Verifies that the value of test_str1 was restored.
+ EXPECT_EQ("initial", FLAGS_test_str1);
+ // Verifies that the "not set" attribute of test_str1 was restored to true.
+ SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str1);
+
+ // Verifies that the value of test_str2 was restored.
+ EXPECT_EQ("second", FLAGS_test_str2);
+ // Verifies that the "not set" attribute of test_str2 was restored to false.
+ SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str2);
+
+ // Verifies that the value of test_str3 was restored.
+ EXPECT_EQ("second", FLAGS_test_str3);
+ // Verifies that the "not set" attribute of test_str3 was restored to true.
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("fourth", FLAGS_test_str3);
+}
+
+
+// Tests that FlagSaver can save the values of various-typed flags.
+TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) {
+ // Initializes the flags.
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_int64 = -2;
+ FLAGS_test_uint64 = 3;
+ FLAGS_test_double = 4.0;
+ FLAGS_test_string = "good";
+
+ // Saves the flag states.
+ {
+ FlagSaver fs;
+
+ // Modifies the flags.
+ FLAGS_test_bool = true;
+ FLAGS_test_int32 = -5;
+ FLAGS_test_int64 = -6;
+ FLAGS_test_uint64 = 7;
+ FLAGS_test_double = 8.0;
+ FLAGS_test_string = "bad";
+
+ // Restores the flag states.
+ }
+
+ // Verifies the flag values were restored.
+ EXPECT_FALSE(FLAGS_test_bool);
+ EXPECT_EQ(-1, FLAGS_test_int32);
+ EXPECT_EQ(-2, FLAGS_test_int64);
+ EXPECT_EQ(3, FLAGS_test_uint64);
+ EXPECT_DOUBLE_EQ(4.0, FLAGS_test_double);
+ EXPECT_EQ("good", FLAGS_test_string);
+}
+
+TEST(GetAllFlagsTest, BaseTest) {
+ vector<CommandLineFlagInfo> flags;
+ GetAllFlags(&flags);
+ bool found_test_bool = false;
+ vector<CommandLineFlagInfo>::const_iterator i;
+ for (i = flags.begin(); i != flags.end(); ++i) {
+ if (i->name == "test_bool") {
+ found_test_bool = true;
+ EXPECT_EQ(i->type, "bool");
+ EXPECT_EQ(i->default_value, "false");
+ break;
+ }
+ }
+ EXPECT_EQ(true, found_test_bool);
+}
+
+TEST(ShowUsageWithFlagsTest, BaseTest) {
+ // TODO(csilvers): test this by allowing output other than to stdout.
+ // Not urgent since this functionality is tested via
+ // gflags_unittest.sh, though only through use of --help.
+}
+
+TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
+ // TODO(csilvers): test this by allowing output other than to stdout.
+ // Not urgent since this functionality is tested via
+ // gflags_unittest.sh, though only through use of --helpmatch.
+}
+
+// Note: all these argv-based tests depend on SetArgv being called
+// before InitGoogle() in main(), below.
+TEST(GetArgvsTest, BaseTest) {
+ vector<string> argvs = GetArgvs();
+ EXPECT_EQ(4, argvs.size());
+ EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]);
+ EXPECT_EQ("argv 2", argvs[1]);
+ EXPECT_EQ("3rd argv", argvs[2]);
+ EXPECT_EQ("argv #4", argvs[3]);
+}
+
+TEST(GetArgvTest, BaseTest) {
+ EXPECT_STREQ("/test/argv/for/gflags_unittest "
+ "argv 2 3rd argv argv #4", GetArgv());
+}
+
+TEST(GetArgv0Test, BaseTest) {
+ EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0());
+}
+
+TEST(GetArgvSumTest, BaseTest) {
+ // This number is just the sum of the ASCII values of all the chars
+ // in GetArgv().
+ EXPECT_EQ(4904, GetArgvSum());
+}
+
+TEST(ProgramInvocationNameTest, BaseTest) {
+ EXPECT_STREQ("/test/argv/for/gflags_unittest",
+ ProgramInvocationName());
+}
+
+TEST(ProgramInvocationShortNameTest, BaseTest) {
+ EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
+}
+
+TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main()
+ EXPECT_STREQ("/test/argv/for/gflags_unittest: "
+ "<useless flag> [...]\nDoes something useless.\n",
+ ProgramUsage());
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) {
+ string value("will be changed");
+ bool r = GetCommandLineOption("test_bool", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("false", value);
+
+ r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("-1", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) {
+ FLAGS_test_int32 = 400;
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("400", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasSet) {
+ SetCommandLineOption("test_int32", "700");
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("700", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) {
+ // This doesn't set the flag's value, but rather its default value.
+ // is_default is still true, but the 'default' value returned has changed!
+ SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT);
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("800", value);
+ EXPECT_EQ(true, GetCommandLineFlagInfoOrDie("test_int32").is_default);
+
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) {
+ SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT);
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("900", value);
+}
+
+TEST(GetCommandLineOptionTest, NameDoesNotExist) {
+ string value("will not be changed");
+ const bool r = GetCommandLineOption("test_int3210", &value);
+ EXPECT_EQ(false, r);
+ EXPECT_EQ("will not be changed", value);
+}
+
+TEST(GetCommandLineFlagInfoTest, FlagExists) {
+ CommandLineFlagInfo info;
+ bool r = GetCommandLineFlagInfo("test_int32", &info);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("test_int32", info.name);
+ EXPECT_EQ("int32", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("-1", info.current_value);
+ EXPECT_EQ("-1", info.default_value);
+ EXPECT_EQ(true, info.is_default);
+
+ FLAGS_test_bool = true;
+ r = GetCommandLineFlagInfo("test_bool", &info);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("true", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(false, info.is_default);
+
+ FLAGS_test_bool = false;
+ r = GetCommandLineFlagInfo("test_bool", &info);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("false", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(false, info.is_default); // value is same, but flag *was* modified
+}
+
+TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) {
+ CommandLineFlagInfo info;
+ // Set to some random values that GetCommandLineFlagInfo should not change
+ info.name = "name";
+ info.type = "type";
+ info.current_value = "curr";
+ info.default_value = "def";
+ info.filename = "/";
+ info.is_default = false;
+ bool r = GetCommandLineFlagInfo("test_int3210", &info);
+ EXPECT_EQ(false, r);
+ EXPECT_EQ("name", info.name);
+ EXPECT_EQ("type", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("curr", info.current_value);
+ EXPECT_EQ("def", info.default_value);
+ EXPECT_EQ("/", info.filename);
+ EXPECT_EQ(false, info.is_default);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) {
+ CommandLineFlagInfo info;
+ info = GetCommandLineFlagInfoOrDie("test_int32");
+ EXPECT_EQ("test_int32", info.name);
+ EXPECT_EQ("int32", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("-1", info.current_value);
+ EXPECT_EQ("-1", info.default_value);
+ EXPECT_EQ(true, info.is_default);
+ info = GetCommandLineFlagInfoOrDie("test_bool");
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("false", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(true, info.is_default);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) {
+ FLAGS_test_int32 = 400;
+ CommandLineFlagInfo info;
+ info = GetCommandLineFlagInfoOrDie("test_int32");
+ EXPECT_EQ("test_int32", info.name);
+ EXPECT_EQ("int32", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("400", info.current_value);
+ EXPECT_EQ("-1", info.default_value);
+ EXPECT_EQ(false, info.is_default);
+ FLAGS_test_bool = true;
+ info = GetCommandLineFlagInfoOrDie("test_bool");
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("true", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(false, info.is_default);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagDoesNotExist) {
+ EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"),
+ ".*: flag test_int3210 does not exist");
+}
+
+
+// These are lightly tested because they're deprecated. Basically,
+// the tests are meant to cover how existing users use these functions,
+// but not necessarily how new users could use them.
+TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) {
+ string s = CommandlineFlagsIntoString();
+ EXPECT_NE(string::npos, s.find("--test_bool="));
+}
+
+TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) {
+ FLAGS_test_int32 = 10; // just to make the test more interesting
+ string filename(FLAGS_test_tmpdir + "/flagfile");
+ unlink(filename.c_str()); // just to be safe
+ const bool r = AppendFlagsIntoFile(filename, "not the real argv0");
+ EXPECT_EQ(true, r);
+
+ FILE* fp = fopen(filename.c_str(), "r");
+ EXPECT_TRUE(fp != NULL);
+ char line[8192];
+ fgets(line, sizeof(line)-1, fp); // first line should be progname
+ EXPECT_STREQ("not the real argv0\n", line);
+
+ bool found_bool = false, found_int32 = false;
+ while (fgets(line, sizeof(line)-1, fp)) {
+ line[sizeof(line)-1] = '\0'; // just to be safe
+ if (strcmp(line, "--test_bool=false\n") == 0)
+ found_bool = true;
+ if (strcmp(line, "--test_int32=10\n") == 0)
+ found_int32 = true;
+ }
+ EXPECT_EQ(true, found_int32);
+ EXPECT_EQ(true, found_bool);
+ fclose(fp);
+}
+
+TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
+ FLAGS_test_int32 = -10; // just to make the test more interesting
+ string filename(FLAGS_test_tmpdir + "/flagfile2");
+ unlink(filename.c_str()); // just to be safe
+ bool r = AppendFlagsIntoFile(filename, GetArgv0());
+ EXPECT_EQ(true, r);
+
+ FLAGS_test_int32 = -11;
+ r = ReadFromFlagsFile(filename, GetArgv0(), true);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ(-10, FLAGS_test_int32);
+}
+
+TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
+ FLAGS_test_int32 = -20;
+ string filename(FLAGS_test_tmpdir + "/flagfile3");
+ FILE* fp = fopen(filename.c_str(), "w");
+ EXPECT_TRUE(fp != NULL);
+ // Note the error in the bool assignment below...
+ fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0());
+ fclose(fp);
+
+ FLAGS_test_int32 = -22;
+ const bool r = ReadFromFlagsFile(filename, GetArgv0(), false);
+ EXPECT_EQ(false, r);
+ EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take
+}
+
+TEST(FlagsSetBeforeInitGoogleTest, TryFromEnv) {
+ EXPECT_EQ("pre-set", FLAGS_test_tryfromenv);
+}
+
+// The following test case verifies that ParseCommandLineFlags() and
+// ParseCommandLineNonHelpFlags() uses the last definition of a flag
+// in case it's defined more than once.
+
+DEFINE_int32(test_flag, -1, "used for testing commandlineflags.cc");
+
+// Returns the definition of the --flagfile flag to be used in the tests.
+const char* GetFlagFileFlag() {
+ static const string flagfile_flag = string("--flagfile=")
+ + FLAGS_srcdir + "/src/gflags_unittest_flagfile";
+
+ return flagfile_flag.c_str();
+}
+
+// Parses and returns the --test_flag flag.
+// If with_help is true, calls ParseCommandLineFlags; otherwise calls
+// ParseCommandLineNonHelpFlags.
+int32 ParseTestFlag(bool with_help, int argc, const char** const_argv) {
+ FlagSaver fs; // Restores the flags before returning.
+
+ // Makes a copy of the input array s.t. it can be reused
+ // (ParseCommandLineFlags() will alter the array).
+ char** const argv_save = new char*[argc + 1];
+ char** argv = argv_save;
+ memcpy(argv, const_argv, sizeof(*argv)*(argc + 1));
+
+ if (with_help) {
+ ParseCommandLineFlags(&argc, &argv, true);
+ } else {
+ ParseCommandLineNonHelpFlags(&argc, &argv, true);
+ }
+
+ delete[] argv_save;
+ return FLAGS_test_flag;
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedTwiceOnCommandLine) {
+ const char* argv[] = {
+ "my_test",
+ "--test_flag=1",
+ "--test_flag=2",
+ NULL,
+ };
+
+ EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedTwiceInFlagFile) {
+ const char* argv[] = {
+ "my_test",
+ GetFlagFileFlag(),
+ NULL,
+ };
+
+ EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedInCommandLineAndThenFlagFile) {
+ const char* argv[] = {
+ "my_test",
+ "--test_flag=0",
+ GetFlagFileFlag(),
+ NULL,
+ };
+
+ EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedInFlagFileAndThenCommandLine) {
+ const char* argv[] = {
+ "my_test",
+ GetFlagFileFlag(),
+ "--test_flag=3",
+ NULL,
+ };
+
+ EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedInCommandLineAndFlagFileAndThenCommandLine) {
+ const char* argv[] = {
+ "my_test",
+ "--test_flag=0",
+ GetFlagFileFlag(),
+ "--test_flag=3",
+ NULL,
+ };
+
+ EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+static int Main(int argc, char **argv) {
+ // We need to call SetArgv before InitGoogle, so our "test" argv will
+ // win out over this executable's real argv. That makes running this
+ // test with a real --help flag kinda annoying, unfortunately.
+ const char* test_argv[] = { "/test/argv/for/gflags_unittest",
+ "argv 2", "3rd argv", "argv #4" };
+ SetArgv(GET_ARRAY_SIZE(test_argv), test_argv);
+
+ // The first arg is the usage message, also important for testing.
+ string usage_message = (string(GetArgv0()) +
+ ": <useless flag> [...]\nDoes something useless.\n");
+
+ // We test setting tryfromenv manually, and making sure initgoogle still
+ // evaluates it.
+ FLAGS_tryfromenv = "test_tryfromenv";
+ setenv("FLAGS_test_tryfromenv", "pre-set", 1);
+
+ SetUsageMessage(usage_message.c_str());
+ ParseCommandLineFlags(&argc, &argv, true);
+
+ mkdir(FLAGS_test_tmpdir.c_str(), 0755);
+
+ return RUN_ALL_TESTS();
+}
+
+_END_GOOGLE_NAMESPACE_
+
+int main(int argc, char** argv) {
+ return GOOGLE_NAMESPACE::Main(argc, argv);
+}
--- /dev/null
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Marius Eriksen
+//
+// For now, this unit test does not cover all features of
+// commandlineflags.cc
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h> // for unlink()
+#include <sys/stat.h> // for mkdir()
+#include <math.h> // for isinf() and isnan()
+#include <vector>
+#include <string>
+#include "google/gflags.h"
+
+using std::vector;
+using std::string;
+
+// Returns the number of elements in an array. We don't use the safer
+// version in base/basictypes.h as commandlineflags is open-sourced.
+#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
+
+DECLARE_string(tryfromenv); // in commandlineflags.cc
+
+DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
+DEFINE_string(srcdir, google::StringFromEnv("SRCDIR", "."),
+ "Source-dir root, needed to find gflags_unittest_flagfile");
+
+
+DEFINE_bool(test_bool, false, "tests bool-ness");
+DEFINE_int32(test_int32, -1, "");
+DEFINE_int64(test_int64, -2, "");
+DEFINE_uint64(test_uint64, 2, "");
+DEFINE_double(test_double, -1.0, "");
+DEFINE_string(test_string, "initial", "");
+
+//
+// The below ugliness gets some additional code coverage in the -helpxml
+// and -helpmatch test cases having to do with string lengths and formatting
+//
+DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name,
+ false,
+ "extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning");
+
+DEFINE_string(test_str1, "initial", "");
+DEFINE_string(test_str2, "initial", "");
+DEFINE_string(test_str3, "initial", "");
+
+// This is used to test setting tryfromenv manually
+DEFINE_string(test_tryfromenv, "initial", "");
+
+// These are never used in this unittest, but can be used by
+// commandlineflags_unittest.sh when it needs to specify flags
+// that are legal for commandlineflags_unittest but don't need to
+// be a particular value.
+DEFINE_bool(unused_bool, true, "unused bool-ness");
+DEFINE_int32(unused_int32, -1001, "");
+DEFINE_int64(unused_int64, -2001, "");
+DEFINE_uint64(unused_uint64, 2000, "");
+DEFINE_double(unused_double, -1000.0, "");
+DEFINE_string(unused_string, "unused", "");
+
+_START_GOOGLE_NAMESPACE_
+
+// The following is some bare-bones testing infrastructure
+
+#define EXPECT_TRUE(cond) \
+ do { \
+ if (!(cond)) { \
+ fprintf(stderr, "Check failed: %s\n", #cond); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
+
+#define EXPECT_OP(op, val1, val2) \
+ do { \
+ if (!((val1) op (val2))) { \
+ fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
+#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
+#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
+#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
+
+#define EXPECT_NAN(arg) \
+ do { \
+ if (!isnan(arg)) { \
+ fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_INF(arg) \
+ do { \
+ if (!isinf(arg)) { \
+ fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_DOUBLE_EQ(val1, val2) \
+ do { \
+ if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
+ fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_STREQ(val1, val2) \
+ do { \
+ if (strcmp((val1), (val2)) != 0) { \
+ fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+static bool g_called_exit;
+static void CalledExit(int) { g_called_exit = true; }
+
+#define EXPECT_DEATH(fn, msg) \
+ do { \
+ g_called_exit = false; \
+ extern void (*commandlineflags_exitfunc)(int); /* in gflags.cc */ \
+ commandlineflags_exitfunc = &CalledExit; \
+ fn; \
+ commandlineflags_exitfunc = &exit; /* set back to its default */ \
+ if (!g_called_exit) { \
+ fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
+ exit(1); \
+ } \
+ } while (0)
+
+
+vector<void (*)()> g_testlist; // the tests to run
+
+#define TEST(a, b) \
+ struct Test_##a##_##b { \
+ Test_##a##_##b() { g_testlist.push_back(&Run); } \
+ static void Run() { FlagSaver fs; RunTest(); } \
+ static void RunTest(); \
+ }; \
+ static Test_##a##_##b g_test_##a##_##b; \
+ void Test_##a##_##b::RunTest()
+
+
+static int RUN_ALL_TESTS() {
+ vector<void (*)()>::const_iterator it;
+ for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
+ (*it)();
+ }
+ fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
+ return 0;
+}
+
+
+// Death tests for "help" options.
+//
+// The help system automatically calls exit(1) when you specify any of
+// the help-related flags ("-helpmatch", "-helpxml") so we can't test
+// those mainline.
+
+// Tests that "-helpmatch" causes the process to die.
+TEST(ReadFlagsFromStringDeathTest, HelpMatch) {
+ EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true),
+ "");
+}
+
+
+// Tests that "-helpxml" causes the process to die.
+TEST(ReadFlagsFromStringDeathTest, HelpXml) {
+ EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
+ "");
+}
+
+
+// A subroutine needed for testing reading flags from a string.
+void TestFlagString(const string& flags,
+ const string& expected_string,
+ bool expected_bool,
+ int32 expected_int32,
+ double expected_double) {
+ EXPECT_TRUE(ReadFlagsFromString(flags,
+ GetArgv0(),
+ // errors are fatal
+ true));
+
+ EXPECT_EQ(expected_string, FLAGS_test_string);
+ EXPECT_EQ(expected_bool, FLAGS_test_bool);
+ EXPECT_EQ(expected_int32, FLAGS_test_int32);
+ EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double);
+}
+
+
+// Tests reading flags from a string.
+TEST(FlagFileTest, ReadFlagsFromString) {
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "-test_double=0.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ 0.0);
+
+ TestFlagString(
+ // Flag string
+ "# let's make sure it can update values\n"
+ "-test_string=initial\n"
+ "-test_bool=false\n"
+ "-test_int32=123\n"
+ "-test_double=123.0\n",
+ // Expected values
+ "initial",
+ false,
+ 123,
+ 123.0);
+}
+
+// Tests the filename part of the flagfile
+TEST(FlagFileTest, FilenamesOurfileLast) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "not_our_filename\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "gflags_unittest\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ false,
+ -1,
+ 1000.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileFirst) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "gflags_unittest\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "not_our_filename\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ -1.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileGlob) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "*flags*\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "flags\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ -1.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileInBigList) {
+ FLAGS_test_string = "initial";
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_double = -1.0;
+ TestFlagString(
+ // Flag string
+ "-test_string=continued\n"
+ "# some comments are in order\n"
+ "# some\n"
+ " # comments\n"
+ "#are\n"
+ " #trickier\n"
+ "# than others\n"
+ "*first* *flags* *third*\n"
+ "-test_bool=true\n"
+ " -test_int32=1\n"
+ "flags\n"
+ "-test_double=1000.0\n",
+ // Expected values
+ "continued",
+ true,
+ 1,
+ -1.0);
+}
+
+// Tests that a failed flag-from-string read keeps flags at default values
+TEST(FlagFileTest, FailReadFlagsFromString) {
+ FLAGS_test_int32 = 119;
+ string flags("# let's make sure it can update values\n"
+ "-test_string=non_initial\n"
+ "-test_bool=false\n"
+ "-test_int32=123\n"
+ "-test_double=illegal\n");
+
+ EXPECT_FALSE(ReadFlagsFromString(flags,
+ GetArgv0(),
+ // errors are fatal
+ false));
+
+ EXPECT_EQ(119, FLAGS_test_int32);
+ EXPECT_EQ("initial", FLAGS_test_string);
+}
+
+// Tests that flags can be set to ordinary values.
+TEST(SetFlagValueTest, OrdinaryValues) {
+ EXPECT_EQ("initial", FLAGS_test_str1);
+
+ SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str1); // set; was default
+
+ SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str1); // already set once
+
+ FLAGS_test_str1 = "initial";
+ SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("initial", FLAGS_test_str1); // still already set before
+
+ SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE);
+ EXPECT_EQ("third", FLAGS_test_str1); // changed value
+
+ SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str1);
+ // value not changed (already set before)
+
+ EXPECT_EQ("initial", FLAGS_test_str2);
+
+ SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str2); // changed (was default)
+
+ FLAGS_test_str2 = "extra";
+ EXPECT_EQ("extra", FLAGS_test_str2);
+
+ FLAGS_test_str2 = "second";
+ SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str2); // still changed (was equal to default)
+
+ SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("fourth", FLAGS_test_str2); // changed (was default)
+
+ EXPECT_EQ("initial", FLAGS_test_str3);
+
+ SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str3); // changed
+
+ FLAGS_test_str3 = "third";
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
+
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
+
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE);
+ EXPECT_EQ("fourth", FLAGS_test_str3); // changed value
+}
+
+
+// Tests that flags can be set to exceptional values.
+TEST(SetFlagValueTest, ExceptionalValues) {
+ EXPECT_EQ("test_double set to inf\n",
+ SetCommandLineOption("test_double", "inf"));
+ EXPECT_INF(FLAGS_test_double);
+
+ EXPECT_EQ("test_double set to inf\n",
+ SetCommandLineOption("test_double", "INF"));
+ EXPECT_INF(FLAGS_test_double);
+
+ // set some bad values
+ EXPECT_EQ("",
+ SetCommandLineOption("test_double", "0.1xxx"));
+ EXPECT_EQ("",
+ SetCommandLineOption("test_double", " "));
+ EXPECT_EQ("",
+ SetCommandLineOption("test_double", ""));
+ EXPECT_EQ("test_double set to -inf\n",
+ SetCommandLineOption("test_double", "-inf"));
+ EXPECT_INF(FLAGS_test_double);
+ EXPECT_GT(0, FLAGS_test_double);
+
+ EXPECT_EQ("test_double set to nan\n",
+ SetCommandLineOption("test_double", "NaN"));
+ EXPECT_NAN(FLAGS_test_double);
+}
+
+// Tests that integer flags can be specified in many ways
+TEST(SetFlagValueTest, DifferentRadices) {
+ EXPECT_EQ("test_int32 set to 12\n",
+ SetCommandLineOption("test_int32", "12"));
+
+ EXPECT_EQ("test_int32 set to 16\n",
+ SetCommandLineOption("test_int32", "0x10"));
+
+ EXPECT_EQ("test_int32 set to 34\n",
+ SetCommandLineOption("test_int32", "0X22"));
+
+ // Leading 0 is *not* octal; it's still decimal
+ EXPECT_EQ("test_int32 set to 10\n",
+ SetCommandLineOption("test_int32", "010"));
+}
+
+// Tests what happens when you try to set a flag to an illegal value
+TEST(SetFlagValueTest, IllegalValues) {
+ FLAGS_test_bool = true;
+ FLAGS_test_int32 = 119;
+ FLAGS_test_int64 = 1191;
+ FLAGS_test_uint64 = 11911;
+
+ EXPECT_EQ("",
+ SetCommandLineOption("test_bool", "12"));
+
+ EXPECT_EQ("",
+ SetCommandLineOption("test_int32", "7000000000000"));
+
+ // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
+#if 0
+ EXPECT_EQ("",
+ SetCommandLineOption("test_uint64", "-1"));
+#endif
+
+ EXPECT_EQ("",
+ SetCommandLineOption("test_int64", "not a number!"));
+
+ // Test the empty string with each type of input
+ EXPECT_EQ("", SetCommandLineOption("test_bool", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_int32", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_int64", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_uint64", ""));
+ EXPECT_EQ("", SetCommandLineOption("test_double", ""));
+ EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", ""));
+
+ EXPECT_EQ(true, FLAGS_test_bool);
+ EXPECT_EQ(119, FLAGS_test_int32);
+ EXPECT_EQ(1191, FLAGS_test_int64);
+ EXPECT_EQ(11911, FLAGS_test_uint64);
+}
+
+
+// Tests that the FooFromEnv does the right thing
+TEST(FromEnvTest, LegalValues) {
+ setenv("BOOL_VAL1", "true", 1);
+ setenv("BOOL_VAL2", "false", 1);
+ setenv("BOOL_VAL3", "1", 1);
+ setenv("BOOL_VAL4", "F", 1);
+ EXPECT_EQ(true, BoolFromEnv("BOOL_VAL1", false));
+ EXPECT_EQ(false, BoolFromEnv("BOOL_VAL2", true));
+ EXPECT_EQ(true, BoolFromEnv("BOOL_VAL3", false));
+ EXPECT_EQ(false, BoolFromEnv("BOOL_VAL4", true));
+ EXPECT_EQ(true, BoolFromEnv("BOOL_VAL_UNKNOWN", true));
+ EXPECT_EQ(false, BoolFromEnv("BOOL_VAL_UNKNOWN", false));
+
+ setenv("INT_VAL1", "1", 1);
+ setenv("INT_VAL2", "-1", 1);
+ EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10));
+ EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10));
+ EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10));
+
+ setenv("INT_VAL3", "1099511627776", 1);
+ EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20));
+ EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20));
+ EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL3", 20));
+ EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20));
+
+ EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30));
+ EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL3", 30));
+ EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30));
+
+ // I pick values here that can be easily represented exactly in floating-point
+ setenv("DOUBLE_VAL1", "0.0", 1);
+ setenv("DOUBLE_VAL2", "1.0", 1);
+ setenv("DOUBLE_VAL3", "-1.0", 1);
+ EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0));
+ EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0));
+ EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0));
+ EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0));
+
+ setenv("STRING_VAL1", "", 1);
+ setenv("STRING_VAL2", "my happy string!", 1);
+ EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown"));
+ EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown"));
+ EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
+}
+
+// Tests that the FooFromEnv dies on parse-error
+TEST(FromEnvTest, IllegalValues) {
+ setenv("BOOL_BAD1", "so true!",1 );
+ setenv("BOOL_BAD2", "", 1);
+ EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable");
+ EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable");
+
+ setenv("INT_BAD1", "one", 1);
+ setenv("INT_BAD2", "100000000000000000", 1);
+ setenv("INT_BAD3", "0xx10", 1);
+ setenv("INT_BAD4", "", 1);
+ EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable");
+ EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable");
+ EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable");
+ EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable");
+
+ setenv("BIGINT_BAD1", "18446744073709551616000", 1);
+ EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable");
+ EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable");
+ EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable");
+ EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable");
+
+ setenv("BIGINT_BAD2", "-1", 1);
+ EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable");
+ EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable");
+ EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable");
+ EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable");
+ // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
+#if 0
+ EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable");
+#endif
+
+ setenv("DOUBLE_BAD1", "0.0.0", 1);
+ setenv("DOUBLE_BAD2", "", 1);
+ EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
+ EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
+}
+
+// Tests that FlagSaver can save the states of string flags.
+TEST(FlagSaverTest, CanSaveStringFlagStates) {
+ // 1. Initializes the flags.
+
+ // State of flag test_str1:
+ // default value - "initial"
+ // current value - "initial"
+ // not set - true
+
+ SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE);
+ // State of flag test_str2:
+ // default value - "initial"
+ // current value - "second"
+ // not set - false
+
+ SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
+ // State of flag test_str3:
+ // default value - "second"
+ // current value - "second"
+ // not set - true
+
+ // 2. Saves the flag states.
+
+ {
+ FlagSaver fs;
+
+ // 3. Modifies the flag states.
+
+ SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE);
+ EXPECT_EQ("second", FLAGS_test_str1);
+ // State of flag test_str1:
+ // default value - "second"
+ // current value - "second"
+ // not set - true
+
+ SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str2);
+ // State of flag test_str2:
+ // default value - "third"
+ // current value - "second"
+ // not set - false
+
+ SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE);
+ EXPECT_EQ("third", FLAGS_test_str3);
+ // State of flag test_str1:
+ // default value - "second"
+ // current value - "third"
+ // not set - false
+
+ // 4. Restores the flag states.
+ }
+
+ // 5. Verifies that the states were restored.
+
+ // Verifies that the value of test_str1 was restored.
+ EXPECT_EQ("initial", FLAGS_test_str1);
+ // Verifies that the "not set" attribute of test_str1 was restored to true.
+ SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str1);
+
+ // Verifies that the value of test_str2 was restored.
+ EXPECT_EQ("second", FLAGS_test_str2);
+ // Verifies that the "not set" attribute of test_str2 was restored to false.
+ SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("second", FLAGS_test_str2);
+
+ // Verifies that the value of test_str3 was restored.
+ EXPECT_EQ("second", FLAGS_test_str3);
+ // Verifies that the "not set" attribute of test_str3 was restored to true.
+ SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
+ EXPECT_EQ("fourth", FLAGS_test_str3);
+}
+
+
+// Tests that FlagSaver can save the values of various-typed flags.
+TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) {
+ // Initializes the flags.
+ FLAGS_test_bool = false;
+ FLAGS_test_int32 = -1;
+ FLAGS_test_int64 = -2;
+ FLAGS_test_uint64 = 3;
+ FLAGS_test_double = 4.0;
+ FLAGS_test_string = "good";
+
+ // Saves the flag states.
+ {
+ FlagSaver fs;
+
+ // Modifies the flags.
+ FLAGS_test_bool = true;
+ FLAGS_test_int32 = -5;
+ FLAGS_test_int64 = -6;
+ FLAGS_test_uint64 = 7;
+ FLAGS_test_double = 8.0;
+ FLAGS_test_string = "bad";
+
+ // Restores the flag states.
+ }
+
+ // Verifies the flag values were restored.
+ EXPECT_FALSE(FLAGS_test_bool);
+ EXPECT_EQ(-1, FLAGS_test_int32);
+ EXPECT_EQ(-2, FLAGS_test_int64);
+ EXPECT_EQ(3, FLAGS_test_uint64);
+ EXPECT_DOUBLE_EQ(4.0, FLAGS_test_double);
+ EXPECT_EQ("good", FLAGS_test_string);
+}
+
+TEST(GetAllFlagsTest, BaseTest) {
+ vector<CommandLineFlagInfo> flags;
+ GetAllFlags(&flags);
+ bool found_test_bool = false;
+ vector<CommandLineFlagInfo>::const_iterator i;
+ for (i = flags.begin(); i != flags.end(); ++i) {
+ if (i->name == "test_bool") {
+ found_test_bool = true;
+ EXPECT_EQ(i->type, "bool");
+ EXPECT_EQ(i->default_value, "false");
+ break;
+ }
+ }
+ EXPECT_EQ(true, found_test_bool);
+}
+
+TEST(ShowUsageWithFlagsTest, BaseTest) {
+ // TODO(csilvers): test this by allowing output other than to stdout.
+ // Not urgent since this functionality is tested via
+ // gflags_unittest.sh, though only through use of --help.
+}
+
+TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
+ // TODO(csilvers): test this by allowing output other than to stdout.
+ // Not urgent since this functionality is tested via
+ // gflags_unittest.sh, though only through use of --helpmatch.
+}
+
+// Note: all these argv-based tests depend on SetArgv being called
+// before InitGoogle() in main(), below.
+TEST(GetArgvsTest, BaseTest) {
+ vector<string> argvs = GetArgvs();
+ EXPECT_EQ(4, argvs.size());
+ EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]);
+ EXPECT_EQ("argv 2", argvs[1]);
+ EXPECT_EQ("3rd argv", argvs[2]);
+ EXPECT_EQ("argv #4", argvs[3]);
+}
+
+TEST(GetArgvTest, BaseTest) {
+ EXPECT_STREQ("/test/argv/for/gflags_unittest "
+ "argv 2 3rd argv argv #4", GetArgv());
+}
+
+TEST(GetArgv0Test, BaseTest) {
+ EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0());
+}
+
+TEST(GetArgvSumTest, BaseTest) {
+ // This number is just the sum of the ASCII values of all the chars
+ // in GetArgv().
+ EXPECT_EQ(4904, GetArgvSum());
+}
+
+TEST(ProgramInvocationNameTest, BaseTest) {
+ EXPECT_STREQ("/test/argv/for/gflags_unittest",
+ ProgramInvocationName());
+}
+
+TEST(ProgramInvocationShortNameTest, BaseTest) {
+ EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
+}
+
+TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main()
+ EXPECT_STREQ("/test/argv/for/gflags_unittest: "
+ "<useless flag> [...]\nDoes something useless.\n",
+ ProgramUsage());
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) {
+ string value("will be changed");
+ bool r = GetCommandLineOption("test_bool", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("false", value);
+
+ r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("-1", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) {
+ FLAGS_test_int32 = 400;
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("400", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasSet) {
+ SetCommandLineOption("test_int32", "700");
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("700", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) {
+ // This doesn't set the flag's value, but rather its default value.
+ // is_default is still true, but the 'default' value returned has changed!
+ SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT);
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("800", value);
+ EXPECT_EQ(true, GetCommandLineFlagInfoOrDie("test_int32").is_default);
+
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) {
+ SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT);
+ string value("will be changed");
+ const bool r = GetCommandLineOption("test_int32", &value);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("900", value);
+}
+
+TEST(GetCommandLineOptionTest, NameDoesNotExist) {
+ string value("will not be changed");
+ const bool r = GetCommandLineOption("test_int3210", &value);
+ EXPECT_EQ(false, r);
+ EXPECT_EQ("will not be changed", value);
+}
+
+TEST(GetCommandLineFlagInfoTest, FlagExists) {
+ CommandLineFlagInfo info;
+ bool r = GetCommandLineFlagInfo("test_int32", &info);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("test_int32", info.name);
+ EXPECT_EQ("int32", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("-1", info.current_value);
+ EXPECT_EQ("-1", info.default_value);
+ EXPECT_EQ(true, info.is_default);
+
+ FLAGS_test_bool = true;
+ r = GetCommandLineFlagInfo("test_bool", &info);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("true", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(false, info.is_default);
+
+ FLAGS_test_bool = false;
+ r = GetCommandLineFlagInfo("test_bool", &info);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("false", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(false, info.is_default); // value is same, but flag *was* modified
+}
+
+TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) {
+ CommandLineFlagInfo info;
+ // Set to some random values that GetCommandLineFlagInfo should not change
+ info.name = "name";
+ info.type = "type";
+ info.current_value = "curr";
+ info.default_value = "def";
+ info.filename = "/";
+ info.is_default = false;
+ bool r = GetCommandLineFlagInfo("test_int3210", &info);
+ EXPECT_EQ(false, r);
+ EXPECT_EQ("name", info.name);
+ EXPECT_EQ("type", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("curr", info.current_value);
+ EXPECT_EQ("def", info.default_value);
+ EXPECT_EQ("/", info.filename);
+ EXPECT_EQ(false, info.is_default);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) {
+ CommandLineFlagInfo info;
+ info = GetCommandLineFlagInfoOrDie("test_int32");
+ EXPECT_EQ("test_int32", info.name);
+ EXPECT_EQ("int32", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("-1", info.current_value);
+ EXPECT_EQ("-1", info.default_value);
+ EXPECT_EQ(true, info.is_default);
+ info = GetCommandLineFlagInfoOrDie("test_bool");
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("false", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(true, info.is_default);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) {
+ FLAGS_test_int32 = 400;
+ CommandLineFlagInfo info;
+ info = GetCommandLineFlagInfoOrDie("test_int32");
+ EXPECT_EQ("test_int32", info.name);
+ EXPECT_EQ("int32", info.type);
+ EXPECT_EQ("", info.description);
+ EXPECT_EQ("400", info.current_value);
+ EXPECT_EQ("-1", info.default_value);
+ EXPECT_EQ(false, info.is_default);
+ FLAGS_test_bool = true;
+ info = GetCommandLineFlagInfoOrDie("test_bool");
+ EXPECT_EQ("test_bool", info.name);
+ EXPECT_EQ("bool", info.type);
+ EXPECT_EQ("tests bool-ness", info.description);
+ EXPECT_EQ("true", info.current_value);
+ EXPECT_EQ("false", info.default_value);
+ EXPECT_EQ(false, info.is_default);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagDoesNotExist) {
+ EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"),
+ ".*: flag test_int3210 does not exist");
+}
+
+
+// These are lightly tested because they're deprecated. Basically,
+// the tests are meant to cover how existing users use these functions,
+// but not necessarily how new users could use them.
+TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) {
+ string s = CommandlineFlagsIntoString();
+ EXPECT_NE(string::npos, s.find("--test_bool="));
+}
+
+TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) {
+ FLAGS_test_int32 = 10; // just to make the test more interesting
+ string filename(FLAGS_test_tmpdir + "/flagfile");
+ unlink(filename.c_str()); // just to be safe
+ const bool r = AppendFlagsIntoFile(filename, "not the real argv0");
+ EXPECT_EQ(true, r);
+
+ FILE* fp = fopen(filename.c_str(), "r");
+ EXPECT_TRUE(fp != NULL);
+ char line[8192];
+ fgets(line, sizeof(line)-1, fp); // first line should be progname
+ EXPECT_STREQ("not the real argv0\n", line);
+
+ bool found_bool = false, found_int32 = false;
+ while (fgets(line, sizeof(line)-1, fp)) {
+ line[sizeof(line)-1] = '\0'; // just to be safe
+ if (strcmp(line, "--test_bool=false\n") == 0)
+ found_bool = true;
+ if (strcmp(line, "--test_int32=10\n") == 0)
+ found_int32 = true;
+ }
+ EXPECT_EQ(true, found_int32);
+ EXPECT_EQ(true, found_bool);
+ fclose(fp);
+}
+
+TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
+ FLAGS_test_int32 = -10; // just to make the test more interesting
+ string filename(FLAGS_test_tmpdir + "/flagfile2");
+ unlink(filename.c_str()); // just to be safe
+ bool r = AppendFlagsIntoFile(filename, GetArgv0());
+ EXPECT_EQ(true, r);
+
+ FLAGS_test_int32 = -11;
+ r = ReadFromFlagsFile(filename, GetArgv0(), true);
+ EXPECT_EQ(true, r);
+ EXPECT_EQ(-10, FLAGS_test_int32);
+}
+
+TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
+ FLAGS_test_int32 = -20;
+ string filename(FLAGS_test_tmpdir + "/flagfile3");
+ FILE* fp = fopen(filename.c_str(), "w");
+ EXPECT_TRUE(fp != NULL);
+ // Note the error in the bool assignment below...
+ fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0());
+ fclose(fp);
+
+ FLAGS_test_int32 = -22;
+ const bool r = ReadFromFlagsFile(filename, GetArgv0(), false);
+ EXPECT_EQ(false, r);
+ EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take
+}
+
+TEST(FlagsSetBeforeInitGoogleTest, TryFromEnv) {
+ EXPECT_EQ("pre-set", FLAGS_test_tryfromenv);
+}
+
+// The following test case verifies that ParseCommandLineFlags() and
+// ParseCommandLineNonHelpFlags() uses the last definition of a flag
+// in case it's defined more than once.
+
+DEFINE_int32(test_flag, -1, "used for testing commandlineflags.cc");
+
+// Returns the definition of the --flagfile flag to be used in the tests.
+const char* GetFlagFileFlag() {
+ static const string flagfile_flag = string("--flagfile=")
+ + FLAGS_srcdir + "/src/gflags_unittest_flagfile";
+
+ return flagfile_flag.c_str();
+}
+
+// Parses and returns the --test_flag flag.
+// If with_help is true, calls ParseCommandLineFlags; otherwise calls
+// ParseCommandLineNonHelpFlags.
+int32 ParseTestFlag(bool with_help, int argc, const char** const_argv) {
+ FlagSaver fs; // Restores the flags before returning.
+
+ // Makes a copy of the input array s.t. it can be reused
+ // (ParseCommandLineFlags() will alter the array).
+ char** const argv_save = new char*[argc + 1];
+ char** argv = argv_save;
+ memcpy(argv, const_argv, sizeof(*argv)*(argc + 1));
+
+ if (with_help) {
+ ParseCommandLineFlags(&argc, &argv, true);
+ } else {
+ ParseCommandLineNonHelpFlags(&argc, &argv, true);
+ }
+
+ delete[] argv_save;
+ return FLAGS_test_flag;
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedTwiceOnCommandLine) {
+ const char* argv[] = {
+ "my_test",
+ "--test_flag=1",
+ "--test_flag=2",
+ NULL,
+ };
+
+ EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedTwiceInFlagFile) {
+ const char* argv[] = {
+ "my_test",
+ GetFlagFileFlag(),
+ NULL,
+ };
+
+ EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedInCommandLineAndThenFlagFile) {
+ const char* argv[] = {
+ "my_test",
+ "--test_flag=0",
+ GetFlagFileFlag(),
+ NULL,
+ };
+
+ EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedInFlagFileAndThenCommandLine) {
+ const char* argv[] = {
+ "my_test",
+ GetFlagFileFlag(),
+ "--test_flag=3",
+ NULL,
+ };
+
+ EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+ WhenFlagIsDefinedInCommandLineAndFlagFileAndThenCommandLine) {
+ const char* argv[] = {
+ "my_test",
+ "--test_flag=0",
+ GetFlagFileFlag(),
+ "--test_flag=3",
+ NULL,
+ };
+
+ EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
+ EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
+}
+
+static int Main(int argc, char **argv) {
+ // We need to call SetArgv before InitGoogle, so our "test" argv will
+ // win out over this executable's real argv. That makes running this
+ // test with a real --help flag kinda annoying, unfortunately.
+ const char* test_argv[] = { "/test/argv/for/gflags_unittest",
+ "argv 2", "3rd argv", "argv #4" };
+ SetArgv(GET_ARRAY_SIZE(test_argv), test_argv);
+
+ // The first arg is the usage message, also important for testing.
+ string usage_message = (string(GetArgv0()) +
+ ": <useless flag> [...]\nDoes something useless.\n");
+
+ // We test setting tryfromenv manually, and making sure initgoogle still
+ // evaluates it.
+ FLAGS_tryfromenv = "test_tryfromenv";
+ setenv("FLAGS_test_tryfromenv", "pre-set", 1);
+
+ SetUsageMessage(usage_message.c_str());
+ ParseCommandLineFlags(&argc, &argv, true);
+
+ mkdir(FLAGS_test_tmpdir.c_str(), 0755);
+
+ return RUN_ALL_TESTS();
+}
+
+_END_GOOGLE_NAMESPACE_
+
+int main(int argc, char** argv) {
+ return GOOGLE_NAMESPACE::Main(argc, argv);
+}
+google-gflags (0.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 18 Oct 2007 11:33:20 -0700
+
google-gflags (0.6-2) unstable; urgency=low
* Somehow 0.6-1 was missing the lib* control files, so the .deb produced
sys.exit(1)
if FLAGS.debug: print 'non-flag arguments:', argv
print 'Happy Birthday', FLAGS.name
- if FLAGS.age != None:
+ if FLAGS.age is not None:
print "You are a %s, who is %d years old" % (FLAGS.gender, FLAGS.age)
if __name__ == '__main__': main(sys.argv)
-#!/usr/bin/python2.2
+#!/usr/bin/env python
# Copyright (c) 2007, Google Inc.
# All rights reserved.
author_email='opensource@google.com',
url='http://code.google.com/p/google-gflags',
py_modules=["gflags"],
- data_files=[("/usr/local/bin", ["gflags2man.py"])])
+ data_files=[("bin", ["gflags2man.py"])])
static const char kError[] = "ERROR: ";
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
+// before including base/commandlineflags.h (or in
+// base/global_strip_options.h).
+
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
// Indicates that undefined options are to be ignored.
// Enables deferred processing of flags in dynamically loaded libraries.
}
// We want to use pthread_once here, for safety, but have to worry about
-// whether libpthread is linked in or not.
+// whether libpthread is linked in or not. We declare a weak version of
+// the function, so we'll always compile (if the weak version is the only
+// one that ends up existing, then pthread_once will be equal to NULL).
+#ifdef HAVE___ATTRIBUTE__
+ // __THROW is defined in glibc systems. It means, counter-intuitively,
+ // "This function will never throw an exception." It's an optional
+ // optimization tool, but we may need to use it to match glibc prototypes.
+# ifndef __THROW // I guess we're not on a glibc system
+# define __THROW // __THROW is just an optimization, so ok to make it ""
+# endif
+extern "C" int pthread_once(pthread_once_t *, void (*)(void))
+ __THROW __attribute__((weak));
+#endif
+
FlagRegistry* FlagRegistry::GlobalRegistry() {
if (pthread_once) { // means we're running with pthreads
pthread_once(&global_registry_once_, &FlagRegistry::InitGlobalRegistry);
return global_registry_;
}
+
+void FlagsTypeWarn(const char *name) {
+ fprintf(stderr, "ERROR: Flag %s is of type bool, "
+ "but its default value is not a boolean.\n", name);
+ // This can (and one day should) become a compilations error
+ //commandlineflags_exitfunc(1); // almost certainly exit()
+}
+
// --------------------------------------------------------------------
// FlagRegisterer
// This class exists merely to have a global constructor (the
// Append data type
AddString(string("type: ") + flag.type, &final_string, &chars_in_line);
- // Append default value
+ // Append the effective default value (i.e., the value that the flag
+ // will have after the command line is parsed if the flag is not
+ // specified on the command line), which may be different from the
+ // stored default value. This would happen if the value of the flag
+ // was modified before the command line was parsed. (Unless the
+ // value was modified using SetCommandLineOptionWithMode() with mode
+ // SET_FLAGS_DEFAULT.)
+ // Note that we are assuming this code is being executed because a help
+ // request was just parsed from the command line, in which case the
+ // printed value is indeed the effective default, as long as no value
+ // for the flag was parsed from the command line before "--help".
if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings
- AddString(string("default: \"") + flag.default_value + string("\""),
+ AddString(string("default: \"") + flag.current_value + string("\""),
&final_string, &chars_in_line);
} else {
- AddString(string("default: ") + flag.default_value,
+ AddString(string("default: ") + flag.current_value,
&final_string, &chars_in_line);
}
return filename.substr(0, (sep == string::npos) ? 0 : sep);
}
-void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
-#ifndef DO_NOT_SHOW_COMMANDLINE_HELP
+// Test whether a filename contains at least one of the substrings.
+static bool FileMatchesSubstring(const string& filename,
+ const vector<string>& substrings) {
+ for (vector<string>::const_iterator target = substrings.begin();
+ target != substrings.end();
+ ++target) {
+ if (strstr(filename.c_str(), target->c_str()) != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Show help for every filename which matches any of the target substrings.
+// If substrings is empty, shows help for every file. If a flag's help message
+// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' to
+// base/global_strip_options.h), then this flag will not be displayed by
+// '--help' and its variants.
+static void ShowUsageWithFlagsMatching(const char *argv0,
+ const vector<string> &substrings) {
fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage());
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags); // flags are sorted by filename, then flagname
- const bool have_restrict = (restrict != NULL) && (*restrict != '\0');
string last_filename = ""; // so we know when we're at a new file
bool first_directory = true; // controls blank lines between dirs
bool found_match = false; // stays false iff no dir matches restrict
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
- if (have_restrict && strstr(flag->filename.c_str(), restrict) == NULL) {
- continue; // this flag doesn't pass the restrict
- }
- found_match = true; // this flag passed the restrict!
- if (flag->filename != last_filename) { // new file
- if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir!
- if (!first_directory)
- fprintf(stdout, "\n\n"); // put blank lines between directories
- first_directory = false;
+ if (substrings.empty() ||
+ FileMatchesSubstring(flag->filename, substrings)) {
+ // If the flag has been stripped, pretend that it doesn't exist.
+ if (flag->description == kStrippedFlagHelp) continue;
+ found_match = true; // this flag passed the match!
+ if (flag->filename != last_filename) { // new file
+ if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir!
+ if (!first_directory)
+ fprintf(stdout, "\n\n"); // put blank lines between directories
+ first_directory = false;
+ }
+ fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str());
+ last_filename = flag->filename;
}
- fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str());
- last_filename = flag->filename;
+ // Now print this flag
+ fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str());
}
- // Now print this flag
- fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str());
}
- if (!found_match && restrict == NULL) {
- fprintf(stdout, "\n No modules matched program name `%s': use -help\n",
- Basename(argv0));
+ if (!found_match && !substrings.empty()) {
+ fprintf(stdout, "\n No modules matched: use -help\n");
+ }
+}
+
+void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
+ vector<string> substrings;
+ if (restrict != NULL && *restrict != '\0') {
+ substrings.push_back(restrict);
}
-#endif // DO_NOT_SHOW_COMMANDLINE_HELP
+ ShowUsageWithFlagsMatching(argv0, substrings);
}
void ShowUsageWithFlags(const char *argv0) {
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
- fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
+ if (flag->description != kStrippedFlagHelp)
+ fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
}
// The end of the document
fprintf(stdout, "</AllFlags>\n");
if (FLAGS_helpshort) {
// show only flags related to this binary:
// E.g. for fileutil.cc, want flags containing ... "/fileutil." cc
- string restrict = string("/") + progname + ".";
- ShowUsageWithFlagsRestrict(progname, restrict.c_str());
+ vector<string> substrings;
+ substrings.push_back(string("/") + progname + ".");
+ substrings.push_back(string("/") + progname + "-main.");
+ substrings.push_back(string("/") + progname + "_main.");
+ ShowUsageWithFlagsMatching(progname, substrings);
commandlineflags_exitfunc(1); // almost certainly exit()
} else if (FLAGS_help || FLAGS_helpfull) {
// filename like "/progname.cc", and take the dirname of that.
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags);
- const string restrict = string("/") + progname + ".";
+ vector<string> substrings;
+ substrings.push_back(string("/") + progname + ".");
+ substrings.push_back(string("/") + progname + "-main.");
+ substrings.push_back(string("/") + progname + "_main.");
string last_package = "";
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
- if (!strstr(flag->filename.c_str(), restrict.c_str()))
+ if (!FileMatchesSubstring(flag->filename, substrings))
continue;
const string package = Dirname(flag->filename) + "/";
if (package != last_package) {
// This is used to test setting tryfromenv manually
DEFINE_string(test_tryfromenv, "initial", "");
+// boolean flag assigned correctly with bool
+DEFINE_bool(test_bool_bool, true, "");
+
+// boolean flag assigned with string
+DEFINE_bool(test_bool_string, "", "");
+
+// boolean flag assigned with float
+DEFINE_bool(test_bool_float, 1.0, "");
+
+// boolean flag assigned with int
+DEFINE_bool(test_bool_int, 1, "");
+
// These are never used in this unittest, but can be used by
// commandlineflags_unittest.sh when it needs to specify flags
// that are legal for commandlineflags_unittest but don't need to
DEFINE_double(unused_double, -1000.0, "");
DEFINE_string(unused_string, "unused", "");
+// These flags are used by gflags_unittest.sh
+DEFINE_bool(changed_bool1, false, "changed");
+DEFINE_bool(changed_bool2, false, "changed");
+
_START_GOOGLE_NAMESPACE_
// The following is some bare-bones testing infrastructure
FLAGS_tryfromenv = "test_tryfromenv";
setenv("FLAGS_test_tryfromenv", "pre-set", 1);
+ // Modify flag values from declared default value in two ways.
+ // The recommended way:
+ SetCommandLineOptionWithMode("changed_bool1", "true", SET_FLAGS_DEFAULT);
+ // The non-recommended way:
+ FLAGS_changed_bool2 = true;
+
SetUsageMessage(usage_message.c_str());
ParseCommandLineFlags(&argc, &argv, true);
SRCDIR=${2:-./}
TMPDIR=${3:-/tmp/gflags}
-# $1: line-number $2: expected return code. $3: substring of expected output.
-# $4: a substring you *don't* expect to find in the output. $5+ flags
-Expect() {
+# Executables built with the main source file suffixed with "-main" and "_main".
+EXE2=${EXE}2 # eg, gflags_unittest2
+EXE3=${EXE}3 # eg, gflags_unittest3
+
+# $1: executable
+# $2: line-number $3: expected return code. $4: substring of expected output.
+# $5: a substring you *don't* expect to find in the output. $6+ flags
+ExpectExe() {
+ local executable="$1"
+ shift
local line_number="$1"
shift
local expected_rc="$1"
shift
# We always add --srcdir=$SRCDIR because it's needed for correctness
- $EXE --srcdir="$SRCDIR" "$@" > "$TMPDIR/test.$line_number" 2>&1
+ $executable --srcdir="$SRCDIR" "$@" > "$TMPDIR/test.$line_number" 2>&1
local actual_rc=$?
if [ $actual_rc != $expected_rc ]; then
echo "Test on line $line_number failed:" \
exit 1;
fi
if [ -n "$expected_output" ] &&
- ! fgrep -q "$expected_output" "$TMPDIR/test.$line_number"; then
+ ! fgrep -q -- "$expected_output" "$TMPDIR/test.$line_number"; then
echo "Test on line $line_number failed:" \
"did not find expected substring '$expected_output'"
exit 1;
fi
if [ -n "$unexpected_output" ] &&
- fgrep -q "$unexpected_output" "$TMPDIR/test.$line_number"; then
+ fgrep -q -- "$unexpected_output" "$TMPDIR/test.$line_number"; then
echo "Test line $line_number failed:" \
"found unexpected substring '$unexpected_output'"
exit 1;
fi
}
+# $1: line-number $2: expected return code. $3: substring of expected output.
+# $4: a substring you *don't* expect to find in the output. $5+ flags
+Expect() {
+ ExpectExe $EXE "$@"
+}
+
rm -rf $TMPDIR
mkdir $TMPDIR || exit 2
# --help should show all flags, including flags from gflags_reporting.cc
Expect $LINENO 1 "/gflags_reporting.cc" "" --help
+# Make sure --help reflects flag changes made before flag-parsing
+Expect $LINENO 1 \
+ "-changed_bool1 (changed) type: bool default: true" "" --help
+Expect $LINENO 1 \
+ "-changed_bool2 (changed) type: bool default: true" "" --help
+
# --nohelp and --help=false should be as if we didn't say anything
Expect $LINENO 0 "PASS" "" --nohelp
Expect $LINENO 0 "PASS" "" --help=false
# --helpshort should show only flags from the unittest itself
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags_reporting.cc" --helpshort
+# --helpshort should work if the main source file is suffixed with [_-]main
+ExpectExe $EXE2 $LINENO 1 "/gflags_unittest-main.cc" "/gflags_reporting.cc" \
+ --helpshort
+ExpectExe $EXE3 $LINENO 1 "/gflags_unittest_main.cc" "/gflags_reporting.cc" \
+ --helpshort
+
# --helpon needs an argument
Expect $LINENO 1 "'--helpon' is missing its argument" "" --helpon
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
-helpmatch=unittest
+# if no flags are found with helpmatch or helpon, suggest --help
+Expect $LINENO 1 "No modules matched" "/commandlineflags_unittest.cc" \
+ -helpmatch=nosuchsubstring
+Expect $LINENO 1 "No modules matched" "/commandlineflags_unittest.cc" \
+ -helpon=nosuchmodule
+
# helppackage shows all the flags in the same dir as this unittest
# --help should show all flags, including flags from google.cc
Expect $LINENO 1 "/gflags_reporting.cc" "" --helppackage
# Make sure -- by itself stops argv processing
Expect $LINENO 0 "PASS" "" -- --help
+# Make sure boolean flags gives warning when type of default value is not bool
+Expect $LINENO 0 "Flag test_bool_string is of type bool, but its default value is not a boolean."
+Expect $LINENO 0 "Flag test_bool_float is of type bool, but its default value is not a boolean."
+Expect $LINENO 0 "Flag test_bool_int is of type bool, but its default value is not a boolean."
+
+# Make sure that boolean flags don't give warning when default value is bool
+Expect $LINENO 0 "" "Flag test_bool_bool is of type bool, but its default value is not a boolean."
+
echo "PASS"
exit 0
extern uint32 ReparseCommandLineNonHelpFlags();
+// The following code is added to check if proper value types are passed to
+// flags. Specially for boolean flags. Since almost anything can be implicitly
+// casted to boolean many copy-paste type of errors got through and they are
+// there in code now. As of now, flags_safe_cast is written such a way that
+// it raises only warning for type mismatches.
+//
+// TODO(who?): This needs to be changed to give compilation error if type
+// does not match.
+extern void FlagsTypeWarn(const char *name);
+
+template<typename From>
+inline bool flags_safe_bool(From from, const char *name) {
+ FlagsTypeWarn(name);
+ return from;
+}
+
+inline bool flags_safe_bool(bool from, const char *name) {
+ return from;
+}
+
+
// --------------------------------------------------------------------
// Now come the command line flag declaration/definition macros that
// will actually be used. They're kind of hairy. A major reason
};
// namespc should be 'std::', and type 'string', for a var of type 'std::string'
-#define DECLARE_VARIABLE(namespc, type, name) \
- namespace Flag_Names_##type { \
- extern namespc type& FLAGS_##name; \
- } \
- using Flag_Names_##type::FLAGS_##name
-
-#define DEFINE_VARIABLE(namespc, type, name, value, help) \
- namespace Flag_Names_##type { \
- static union { void* align; char store[sizeof(namespc type)]; } cur_##name;\
- static union { void* align; char store[sizeof(namespc type)]; } dfl_##name;\
- static @ac_google_namespace@::FlagRegisterer object_##name( \
- #name, #type, help, __FILE__, \
- new (cur_##name.store) namespc type(value), \
- new (dfl_##name.store) namespc type(value)); \
- namespc type& FLAGS_##name = \
- *(reinterpret_cast<namespc type*>(cur_##name.store)); \
- char FLAGS_no##name @ac_cv___attribute__unused@; \
- } \
- using Flag_Names_##type::FLAGS_##name
+#define DECLARE_VARIABLE(namespc, type, shorttype, name) \
+ namespace fL##shorttype { \
+ extern namespc type& FLAGS_##name; \
+ } \
+ using fL##shorttype::FLAGS_##name
+
+// If your application #defines STRIP_FLAG_HELP to a non-zero value
+// before #including this file, we remove the help message from the
+// binary file. This can reduce the size of the resulting binary
+// somewhat, and may also be useful for security reasons.
+
+extern const char kStrippedFlagHelp[];
+
+#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
+// Need this construct to avoid the 'defined but not used' warning.
+#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : kStrippedFlagHelp)
+#else
+#define MAYBE_STRIPPED_HELP(txt) txt
+#endif
+
+// Each command-line flag defines an internal array of two elements
+// of the appropriate time (each element is actually a union to get
+// the values to be aligned on larger-than-byte boundaries). Element
+// 0 of the s_##name array holds the current value, and element 1
+// holds the default value.
+#define DEFINE_VARIABLE(namespc, type, shorttype, name, value, help) \
+ namespace fL##shorttype { \
+ static union { void* align; char store[sizeof(namespc type)]; } \
+ s_##name[2]; \
+ static @ac_google_namespace@::FlagRegisterer o_##name( \
+ #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
+ new (s_##name[0].store) namespc type(value), \
+ new (s_##name[1].store) namespc type(value)); \
+ namespc type& FLAGS_##name = \
+ *(reinterpret_cast<namespc type*>(s_##name[0].store)); \
+ char FLAGS_no##name @ac_cv___attribute__unused@; \
+ } \
+ using fL##shorttype::FLAGS_##name
#ifndef SWIG // In swig, ignore the main flag declarations
-#define DECLARE_bool(name) DECLARE_VARIABLE(, bool, name)
-#define DEFINE_bool(name, val, txt) DEFINE_VARIABLE(, bool, name, val, txt)
+#define DECLARE_bool(name) DECLARE_VARIABLE(, bool, B, name)
+#define DEFINE_bool(name, val, txt) \
+ DEFINE_VARIABLE(, bool, B, name, @ac_google_namespace@::flags_safe_bool(val, #name), txt)
-#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::,int32, name)
-#define DEFINE_int32(name, val, txt) DEFINE_VARIABLE(@ac_google_namespace@::,int32, name, val, txt)
+#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::, int32,I, name)
+#define DEFINE_int32(name, val,txt) DEFINE_VARIABLE(@ac_google_namespace@::, int32,I, name,val,txt)
-#define DECLARE_int64(name) DECLARE_VARIABLE(@ac_google_namespace@::,int64, name)
-#define DEFINE_int64(name, val, txt) DEFINE_VARIABLE(@ac_google_namespace@::,int64, name, val, txt)
+#define DECLARE_int64(name) DECLARE_VARIABLE(@ac_google_namespace@::, int64,I64, name)
+#define DEFINE_int64(name, val,txt) DEFINE_VARIABLE(@ac_google_namespace@::, int64,I64, name,val,txt)
-#define DECLARE_uint64(name) DECLARE_VARIABLE(@ac_google_namespace@::,uint64, name)
-#define DEFINE_uint64(name, val, txt) DEFINE_VARIABLE(@ac_google_namespace@::,uint64, name, val, txt)
+#define DECLARE_uint64(name) DECLARE_VARIABLE(@ac_google_namespace@::, uint64,U64, name)
+#define DEFINE_uint64(name, val,txt) DEFINE_VARIABLE(@ac_google_namespace@::, uint64,U64,name,val,txt)
-#define DECLARE_double(name) DECLARE_VARIABLE(, double, name)
-#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(, double, name, val, txt)
+#define DECLARE_double(name) DECLARE_VARIABLE(, double,D, name)
+#define DEFINE_double(name, val,txt) DEFINE_VARIABLE(, double,D, name,val,txt)
-#define DECLARE_string(name) DECLARE_VARIABLE(std::, string, name)
-#define DEFINE_string(name, val, txt) DEFINE_VARIABLE(std::, string, name, val, txt)
+#define DECLARE_string(name) DECLARE_VARIABLE(std::, string,S, name)
+#define DEFINE_string(name, val,txt) DEFINE_VARIABLE(std::, string,S, name,val,txt)
#endif // SWIG