Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
authorCraig Silverstein <csilvers+gflags@google.com>
Thu, 18 Oct 2007 20:08:26 +0000 (20:08 +0000)
committerCraig Silverstein <csilvers+gflags@google.com>
Thu, 18 Oct 2007 20:08:26 +0000 (20:08 +0000)
* 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)

git-svn-id: https://gflags.googlecode.com/svn/trunk@19 6586e3c6-dcc4-952a-343f-ff74eb82781d

16 files changed:
ChangeLog
Makefile.am
Makefile.in
configure
configure.ac
doc/gflags.html
gflags_unittest-main.cc [new file with mode: 0644]
gflags_unittest_main.cc [new file with mode: 0644]
packages/deb/changelog
python/gflags.py
python/setup.py
src/gflags.cc
src/gflags_reporting.cc
src/gflags_unittest.cc
src/gflags_unittest.sh
src/google/gflags.h.in

index 7efd7ba84c2ba6d756c83bbc4777b04b3270fabc..9a46b21a8ecc6b88bbfd566aeae2b76e1d86aeab 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+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
index 577e9ee49ca47a7a14e0fae32f59dc101f96a97e..7173895a497fc4badc398e1c79d0747e9fd677b4 100644 (file)
@@ -35,20 +35,21 @@ TESTS_ENVIRONMENT = SRCDIR="$(top_srcdir)"
 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)
@@ -58,10 +59,32 @@ TESTS += gflags_nothreads_unittest
 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
index e3af0ecf2039eea46d24392221dec0200855ffb2..727e672f3395bb153911c61d2d360b0cce53178a 100644 (file)
@@ -79,7 +79,8 @@ am_libgflags_la_OBJECTS = $(am__objects_1) libgflags_la-gflags.lo \
        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)
@@ -90,6 +91,14 @@ am_gflags_unittest_OBJECTS = $(am__objects_1) \
        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
@@ -111,10 +120,12 @@ CCLD = $(CC)
 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)
@@ -258,25 +269,40 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
 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
@@ -386,6 +412,12 @@ gflags_nothreads_unittest$(EXEEXT): $(gflags_nothreads_unittest_OBJECTS) $(gflag
 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)
@@ -394,7 +426,9 @@ distclean-compile:
        -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@
 
@@ -461,6 +495,34 @@ gflags_unittest-gflags_unittest.obj: src/gflags_unittest.cc
 @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
 
@@ -780,6 +842,7 @@ install-strip:
 mostlyclean-generic:
 
 clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -860,7 +923,13 @@ uninstall-am: uninstall-dist_docDATA uninstall-googleincludeHEADERS \
        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
index 7f7da2a6ff79f9163c46eacbd20172e1aa5ccc1b..7dfdd13d454d078e726a44f8c5416f308beec1b8 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /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>.
 #
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # 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"
@@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
   # 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]...
 
@@ -1020,7 +1020,7 @@ fi
 
 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
 
@@ -1163,7 +1163,7 @@ fi
 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.
@@ -1177,7 +1177,7 @@ cat >&5 <<_ACEOF
 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 $@
@@ -1823,7 +1823,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='gflags'
- VERSION='0.6'
+ VERSION='0.7'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -20943,7 +20943,7 @@ _ASBOX
 } >&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
@@ -21006,7 +21006,7 @@ _ACEOF
 
 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'`\\"
 
index 0e363a689f77051d6d30193f2276ab481676dcc1..304c313e45a30e7304049273aa98d0e16975d881 100644 (file)
@@ -4,7 +4,7 @@
 # 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)
index 9f175e9dd8639570d5d758ebbdef128817f5b6a1..edb5b4882c52e5a81730cd986e8cdbb1e669b38a 100644 (file)
@@ -434,6 +434,19 @@ name (<code>argv[0]</code>).</p>
 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 &lt;google/gflags.h&gt;
+</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>
diff --git a/gflags_unittest-main.cc b/gflags_unittest-main.cc
new file mode 100644 (file)
index 0000000..3ec0333
--- /dev/null
@@ -0,0 +1,1125 @@
+// 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);
+}
diff --git a/gflags_unittest_main.cc b/gflags_unittest_main.cc
new file mode 100644 (file)
index 0000000..3ec0333
--- /dev/null
@@ -0,0 +1,1125 @@
+// 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);
+}
index da02a1e03f538302b85983748d0432a58ae054aa..3025c8ceae3a764e2d0b4d01a6612c72a83217d0 100644 (file)
@@ -1,3 +1,9 @@
+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
index ee9bc97c106cd765b2c24cb08a8ee1718634038c..2a37afb25d3f8359c7fdb25257c57ae6fc1b7d7b 100755 (executable)
@@ -171,7 +171,7 @@ EXAMPLE USAGE:
       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)
index 8af83a2a604a4401454db3439de202bf863afe16..79f755433f82732dacb2a3ea10cfd3c477a9b12e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python2.2
+#!/usr/bin/env python
 
 # Copyright (c) 2007, Google Inc.
 # All rights reserved.
@@ -39,4 +39,4 @@ setup(name='gflags',
       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"])])
index 1210434409900942ceb4677cc40c9605933c9507..c14e120b4784ba3adc4abb5f5a9e6554c4e4f7fe 100644 (file)
@@ -93,6 +93,13 @@ _START_GOOGLE_NAMESPACE_
 
 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.
@@ -637,7 +644,20 @@ void FlagRegistry::InitGlobalRegistry() {
 }
 
 // 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);
@@ -648,6 +668,14 @@ FlagRegistry* FlagRegistry::GlobalRegistry() {
   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
index ce9e0bb97807df3efe6db4368725139adddc309f..981dccdda67ddbf0859ae28d28e322763cc2864d 100644 (file)
@@ -158,12 +158,22 @@ static string DescribeOneFlag(const CommandLineFlagInfo& flag) {
 
   // 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);
   }
 
@@ -217,41 +227,66 @@ static string Dirname(const string& filename) {
   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) {
@@ -276,7 +311,8 @@ static void ShowXMLOfFlags(const char *prog_name) {
   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");
@@ -312,8 +348,11 @@ void HandleCommandLineHelpFlags() {
   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) {
@@ -338,12 +377,15 @@ void HandleCommandLineHelpFlags() {
     // 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) {
index 3ec0333cf3c545f9800117ce704f08f06dde5c8a..8a8db97cfbe0f08fb9d9c4d1576b4279193a23ac 100644 (file)
@@ -79,6 +79,18 @@ DEFINE_string(test_str3, "initial", "");
 // 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
@@ -90,6 +102,10 @@ DEFINE_uint64(unused_uint64, 2000, "");
 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
@@ -1110,6 +1126,12 @@ static int Main(int argc, char **argv) {
   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);
 
index 76d63b30c9c5c02e358d39796c33d4a3135fabb2..cb214b8a79209f16fc97d0ecf9a1db6590e29b1e 100755 (executable)
@@ -46,9 +46,16 @@ EXE=$1
 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"
@@ -59,7 +66,7 @@ Expect() {
   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:" \
@@ -67,19 +74,25 @@ Expect() {
     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
 
@@ -101,6 +114,12 @@ Expect $LINENO 0 "PASS" ""
 # --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
@@ -111,6 +130,12 @@ Expect $LINENO 1 "/gflags_reporting.cc" "" -helpfull
 # --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
 
@@ -130,6 +155,12 @@ Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
 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
@@ -176,5 +207,13 @@ Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
 # 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
index 8dc257a815e30fa5d16bc543585cf7d90f67514a..285a53f364980db0c064b041108ab3df174848d6 100644 (file)
@@ -293,6 +293,27 @@ extern void AllowCommandLineReparsing();
 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
@@ -340,46 +361,66 @@ class FlagRegisterer {
 };
 
 // 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