Commit 585a44a0 authored by Craig Silverstein's avatar Craig Silverstein

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)


git-svn-id: https://gflags.googlecode.com/svn/trunk@19 6586e3c6-dcc4-952a-343f-ff74eb82781d
parent eb208399
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
......
......@@ -35,7 +35,8 @@ 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
......@@ -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
......
......@@ -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,11 +269,18 @@ 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
......@@ -277,6 +295,14 @@ 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
......
#! /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'`\\"
......
......@@ -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)
......
......@@ -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>
......
// 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);
}
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Marius Eriksen
//
// For now, this unit test does not cover all features of
// commandlineflags.cc
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h> // for unlink()
#include <sys/stat.h> // for mkdir()
#include <math.h> // for isinf() and isnan()
#include <vector>
#include <string>
#include "google/gflags.h"
using std::vector;
using std::string;
// Returns the number of elements in an array. We don't use the safer
// version in base/basictypes.h as commandlineflags is open-sourced.
#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
DECLARE_string(tryfromenv); // in commandlineflags.cc
DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
DEFINE_string(srcdir, google::StringFromEnv("SRCDIR", "."),
"Source-dir root, needed to find gflags_unittest_flagfile");
DEFINE_bool(test_bool, false, "tests bool-ness");
DEFINE_int32(test_int32, -1, "");
DEFINE_int64(test_int64, -2, "");
DEFINE_uint64(test_uint64, 2, "");
DEFINE_double(test_double, -1.0, "");
DEFINE_string(test_string, "initial", "");
//
// The below ugliness gets some additional code coverage in the -helpxml
// and -helpmatch test cases having to do with string lengths and formatting
//
DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name,
false,
"extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning");
DEFINE_string(test_str1, "initial", "");
DEFINE_string(test_str2, "initial", "");
DEFINE_string(test_str3, "initial", "");
// This is used to test setting tryfromenv manually
DEFINE_string(test_tryfromenv, "initial", "");
// These are never used in this unittest, but can be used by
// commandlineflags_unittest.sh when it needs to specify flags
// that are legal for commandlineflags_unittest but don't need to
// be a particular value.
DEFINE_bool(unused_bool, true, "unused bool-ness");
DEFINE_int32(unused_int32, -1001, "");
DEFINE_int64(unused_int64, -2001, "");
DEFINE_uint64(unused_uint64, 2000, "");
DEFINE_double(unused_double, -1000.0, "");
DEFINE_string(unused_string, "unused", "");
_START_GOOGLE_NAMESPACE_
// The following is some bare-bones testing infrastructure
#define EXPECT_TRUE(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "Check failed: %s\n", #cond); \
exit(1); \
} \
} while (0)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
#define EXPECT_OP(op, val1, val2) \
do { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
#define EXPECT_NAN(arg) \
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_INF(arg) \
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
static bool g_called_exit;
static void CalledExit(int) { g_called_exit = true; }
#define EXPECT_DEATH(fn, msg) \
do { \
g_called_exit = false; \
extern void (*commandlineflags_exitfunc)(int); /* in gflags.cc */ \
commandlineflags_exitfunc = &CalledExit; \
fn; \
commandlineflags_exitfunc = &exit; /* set back to its default */ \
if (!g_called_exit) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
vector<void (*)()> g_testlist; // the tests to run
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
static int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it;
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
(*it)();
}
fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
return 0;
}
// Death tests for "help" options.
//
// The help system automatically calls exit(1) when you specify any of
// the help-related flags ("-helpmatch", "-helpxml") so we can't test
// those mainline.
// Tests that "-helpmatch" causes the process to die.
TEST(ReadFlagsFromStringDeathTest, HelpMatch) {
EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true),
"");
}
// Tests that "-helpxml" causes the process to die.
TEST(ReadFlagsFromStringDeathTest, HelpXml) {
EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
"");
}
// A subroutine needed for testing reading flags from a string.
void TestFlagString(const string& flags,
const string& expected_string,
bool expected_bool,
int32 expected_int32,
double expected_double) {
EXPECT_TRUE(ReadFlagsFromString(flags,
GetArgv0(),
// errors are fatal
true));
EXPECT_EQ(expected_string, FLAGS_test_string);
EXPECT_EQ(expected_bool, FLAGS_test_bool);
EXPECT_EQ(expected_int32, FLAGS_test_int32);
EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double);
}
// Tests reading flags from a string.
TEST(FlagFileTest, ReadFlagsFromString) {
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"-test_bool=true\n"
" -test_int32=1\n"
"-test_double=0.0\n",
// Expected values
"continued",
true,
1,
0.0);
TestFlagString(
// Flag string
"# let's make sure it can update values\n"
"-test_string=initial\n"
"-test_bool=false\n"
"-test_int32=123\n"
"-test_double=123.0\n",
// Expected values
"initial",
false,
123,
123.0);
}
// Tests the filename part of the flagfile
TEST(FlagFileTest, FilenamesOurfileLast) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"not_our_filename\n"
"-test_bool=true\n"
" -test_int32=1\n"
"gflags_unittest\n"
"-test_double=1000.0\n",
// Expected values
"continued",
false,
-1,
1000.0);
}
TEST(FlagFileTest, FilenamesOurfileFirst) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"gflags_unittest\n"
"-test_bool=true\n"
" -test_int32=1\n"
"not_our_filename\n"
"-test_double=1000.0\n",
// Expected values
"continued",
true,
1,
-1.0);
}
TEST(FlagFileTest, FilenamesOurfileGlob) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"*flags*\n"
"-test_bool=true\n"
" -test_int32=1\n"
"flags\n"
"-test_double=1000.0\n",
// Expected values
"continued",
true,
1,
-1.0);
}
TEST(FlagFileTest, FilenamesOurfileInBigList) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"*first* *flags* *third*\n"
"-test_bool=true\n"
" -test_int32=1\n"
"flags\n"
"-test_double=1000.0\n",
// Expected values
"continued",
true,
1,
-1.0);
}
// Tests that a failed flag-from-string read keeps flags at default values
TEST(FlagFileTest, FailReadFlagsFromString) {
FLAGS_test_int32 = 119;
string flags("# let's make sure it can update values\n"
"-test_string=non_initial\n"
"-test_bool=false\n"
"-test_int32=123\n"
"-test_double=illegal\n");
EXPECT_FALSE(ReadFlagsFromString(flags,
GetArgv0(),
// errors are fatal
false));
EXPECT_EQ(119, FLAGS_test_int32);
EXPECT_EQ("initial", FLAGS_test_string);
}
// Tests that flags can be set to ordinary values.
TEST(SetFlagValueTest, OrdinaryValues) {
EXPECT_EQ("initial", FLAGS_test_str1);
SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str1); // set; was default
SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str1); // already set once
FLAGS_test_str1 = "initial";
SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("initial", FLAGS_test_str1); // still already set before
SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE);
EXPECT_EQ("third", FLAGS_test_str1); // changed value
SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str1);
// value not changed (already set before)
EXPECT_EQ("initial", FLAGS_test_str2);
SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str2); // changed (was default)
FLAGS_test_str2 = "extra";
EXPECT_EQ("extra", FLAGS_test_str2);
FLAGS_test_str2 = "second";
SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str2); // still changed (was equal to default)
SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("fourth", FLAGS_test_str2); // changed (was default)
EXPECT_EQ("initial", FLAGS_test_str3);
SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str3); // changed
FLAGS_test_str3 = "third";
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE);
EXPECT_EQ("fourth", FLAGS_test_str3); // changed value
}
// Tests that flags can be set to exceptional values.
TEST(SetFlagValueTest, ExceptionalValues) {
EXPECT_EQ("test_double set to inf\n",
SetCommandLineOption("test_double", "inf"));
EXPECT_INF(FLAGS_test_double);
EXPECT_EQ("test_double set to inf\n",
SetCommandLineOption("test_double", "INF"));
EXPECT_INF(FLAGS_test_double);
// set some bad values
EXPECT_EQ("",
SetCommandLineOption("test_double", "0.1xxx"));
EXPECT_EQ("",
SetCommandLineOption("test_double", " "));
EXPECT_EQ("",
SetCommandLineOption("test_double", ""));
EXPECT_EQ("test_double set to -inf\n",
SetCommandLineOption("test_double", "-inf"));
EXPECT_INF(FLAGS_test_double);
EXPECT_GT(0, FLAGS_test_double);
EXPECT_EQ("test_double set to nan\n",
SetCommandLineOption("test_double", "NaN"));
EXPECT_NAN(FLAGS_test_double);
}
// Tests that integer flags can be specified in many ways
TEST(SetFlagValueTest, DifferentRadices) {
EXPECT_EQ("test_int32 set to 12\n",
SetCommandLineOption("test_int32", "12"));
EXPECT_EQ("test_int32 set to 16\n",
SetCommandLineOption("test_int32", "0x10"));
EXPECT_EQ("test_int32 set to 34\n",
SetCommandLineOption("test_int32", "0X22"));
// Leading 0 is *not* octal; it's still decimal
EXPECT_EQ("test_int32 set to 10\n",
SetCommandLineOption("test_int32", "010"));
}
// Tests what happens when you try to set a flag to an illegal value
TEST(SetFlagValueTest, IllegalValues) {
FLAGS_test_bool = true;
FLAGS_test_int32 = 119;
FLAGS_test_int64 = 1191;
FLAGS_test_uint64 = 11911;
EXPECT_EQ("",
SetCommandLineOption("test_bool", "12"));
EXPECT_EQ("",
SetCommandLineOption("test_int32", "7000000000000"));
// TODO(csilvers): uncomment this when we disallow negative numbers for uint64
#if 0
EXPECT_EQ("",
SetCommandLineOption("test_uint64", "-1"));
#endif
EXPECT_EQ("",
SetCommandLineOption("test_int64", "not a number!"));
// Test the empty string with each type of input
EXPECT_EQ("", SetCommandLineOption("test_bool", ""));
EXPECT_EQ("", SetCommandLineOption("test_int32", ""));
EXPECT_EQ("", SetCommandLineOption("test_int64", ""));
EXPECT_EQ("", SetCommandLineOption("test_uint64", ""));
EXPECT_EQ("", SetCommandLineOption("test_double", ""));
EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", ""));
EXPECT_EQ(true, FLAGS_test_bool);
EXPECT_EQ(119, FLAGS_test_int32);
EXPECT_EQ(1191, FLAGS_test_int64);
EXPECT_EQ(11911, FLAGS_test_uint64);
}
// Tests that the FooFromEnv does the right thing
TEST(FromEnvTest, LegalValues) {
setenv("BOOL_VAL1", "true", 1);
setenv("BOOL_VAL2", "false", 1);
setenv("BOOL_VAL3", "1", 1);
setenv("BOOL_VAL4", "F", 1);
EXPECT_EQ(true, BoolFromEnv("BOOL_VAL1", false));
EXPECT_EQ(false, BoolFromEnv("BOOL_VAL2", true));
EXPECT_EQ(true, BoolFromEnv("BOOL_VAL3", false));
EXPECT_EQ(false, BoolFromEnv("BOOL_VAL4", true));
EXPECT_EQ(true, BoolFromEnv("BOOL_VAL_UNKNOWN", true));
EXPECT_EQ(false, BoolFromEnv("BOOL_VAL_UNKNOWN", false));
setenv("INT_VAL1", "1", 1);
setenv("INT_VAL2", "-1", 1);
EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10));
EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10));
EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10));
setenv("INT_VAL3", "1099511627776", 1);
EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20));
EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20));
EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL3", 20));
EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20));
EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30));
EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL3", 30));
EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30));
// I pick values here that can be easily represented exactly in floating-point
setenv("DOUBLE_VAL1", "0.0", 1);
setenv("DOUBLE_VAL2", "1.0", 1);
setenv("DOUBLE_VAL3", "-1.0", 1);
EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0));
EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0));
EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0));
EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0));
setenv("STRING_VAL1", "", 1);
setenv("STRING_VAL2", "my happy string!", 1);
EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown"));
EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown"));
EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
}
// Tests that the FooFromEnv dies on parse-error
TEST(FromEnvTest, IllegalValues) {
setenv("BOOL_BAD1", "so true!",1 );
setenv("BOOL_BAD2", "", 1);
EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable");
EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable");
setenv("INT_BAD1", "one", 1);
setenv("INT_BAD2", "100000000000000000", 1);
setenv("INT_BAD3", "0xx10", 1);
setenv("INT_BAD4", "", 1);
EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable");
EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable");
EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable");
EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable");
setenv("BIGINT_BAD1", "18446744073709551616000", 1);
EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable");
EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable");
EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable");
EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable");
setenv("BIGINT_BAD2", "-1", 1);
EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable");
EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable");
EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable");
EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable");
// TODO(csilvers): uncomment this when we disallow negative numbers for uint64
#if 0
EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable");
#endif
setenv("DOUBLE_BAD1", "0.0.0", 1);
setenv("DOUBLE_BAD2", "", 1);
EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
}
// Tests that FlagSaver can save the states of string flags.
TEST(FlagSaverTest, CanSaveStringFlagStates) {
// 1. Initializes the flags.
// State of flag test_str1:
// default value - "initial"
// current value - "initial"
// not set - true
SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE);
// State of flag test_str2:
// default value - "initial"
// current value - "second"
// not set - false
SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
// State of flag test_str3:
// default value - "second"
// current value - "second"
// not set - true
// 2. Saves the flag states.
{
FlagSaver fs;
// 3. Modifies the flag states.
SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE);
EXPECT_EQ("second", FLAGS_test_str1);
// State of flag test_str1:
// default value - "second"
// current value - "second"
// not set - true
SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str2);
// State of flag test_str2:
// default value - "third"
// current value - "second"
// not set - false
SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE);
EXPECT_EQ("third", FLAGS_test_str3);
// State of flag test_str1:
// default value - "second"
// current value - "third"
// not set - false
// 4. Restores the flag states.
}
// 5. Verifies that the states were restored.
// Verifies that the value of test_str1 was restored.
EXPECT_EQ("initial", FLAGS_test_str1);
// Verifies that the "not set" attribute of test_str1 was restored to true.
SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str1);
// Verifies that the value of test_str2 was restored.
EXPECT_EQ("second", FLAGS_test_str2);
// Verifies that the "not set" attribute of test_str2 was restored to false.
SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str2);
// Verifies that the value of test_str3 was restored.
EXPECT_EQ("second", FLAGS_test_str3);
// Verifies that the "not set" attribute of test_str3 was restored to true.
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("fourth", FLAGS_test_str3);
}
// Tests that FlagSaver can save the values of various-typed flags.
TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) {
// Initializes the flags.
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_int64 = -2;
FLAGS_test_uint64 = 3;
FLAGS_test_double = 4.0;
FLAGS_test_string = "good";
// Saves the flag states.
{
FlagSaver fs;
// Modifies the flags.
FLAGS_test_bool = true;
FLAGS_test_int32 = -5;
FLAGS_test_int64 = -6;
FLAGS_test_uint64 = 7;
FLAGS_test_double = 8.0;
FLAGS_test_string = "bad";
// Restores the flag states.
}
// Verifies the flag values were restored.
EXPECT_FALSE(FLAGS_test_bool);
EXPECT_EQ(-1, FLAGS_test_int32);
EXPECT_EQ(-2, FLAGS_test_int64);
EXPECT_EQ(3, FLAGS_test_uint64);
EXPECT_DOUBLE_EQ(4.0, FLAGS_test_double);
EXPECT_EQ("good", FLAGS_test_string);
}
TEST(GetAllFlagsTest, BaseTest) {
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags);
bool found_test_bool = false;
vector<CommandLineFlagInfo>::const_iterator i;
for (i = flags.begin(); i != flags.end(); ++i) {
if (i->name == "test_bool") {
found_test_bool = true;
EXPECT_EQ(i->type, "bool");
EXPECT_EQ(i->default_value, "false");
break;
}
}
EXPECT_EQ(true, found_test_bool);
}
TEST(ShowUsageWithFlagsTest, BaseTest) {
// TODO(csilvers): test this by allowing output other than to stdout.
// Not urgent since this functionality is tested via
// gflags_unittest.sh, though only through use of --help.
}
TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
// TODO(csilvers): test this by allowing output other than to stdout.
// Not urgent since this functionality is tested via
// gflags_unittest.sh, though only through use of --helpmatch.
}
// Note: all these argv-based tests depend on SetArgv being called
// before InitGoogle() in main(), below.
TEST(GetArgvsTest, BaseTest) {
vector<string> argvs = GetArgvs();
EXPECT_EQ(4, argvs.size());
EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]);
EXPECT_EQ("argv 2", argvs[1]);
EXPECT_EQ("3rd argv", argvs[2]);
EXPECT_EQ("argv #4", argvs[3]);
}
TEST(GetArgvTest, BaseTest) {
EXPECT_STREQ("/test/argv/for/gflags_unittest "
"argv 2 3rd argv argv #4", GetArgv());
}
TEST(GetArgv0Test, BaseTest) {
EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0());
}
TEST(GetArgvSumTest, BaseTest) {
// This number is just the sum of the ASCII values of all the chars
// in GetArgv().
EXPECT_EQ(4904, GetArgvSum());
}
TEST(ProgramInvocationNameTest, BaseTest) {
EXPECT_STREQ("/test/argv/for/gflags_unittest",
ProgramInvocationName());
}
TEST(ProgramInvocationShortNameTest, BaseTest) {
EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
}
TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main()
EXPECT_STREQ("/test/argv/for/gflags_unittest: "
"<useless flag> [...]\nDoes something useless.\n",
ProgramUsage());
}
TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) {
string value("will be changed");
bool r = GetCommandLineOption("test_bool", &value);
EXPECT_EQ(true, r);
EXPECT_EQ("false", value);
r = GetCommandLineOption("test_int32", &value);
EXPECT_EQ(true, r);
EXPECT_EQ("-1", value);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) {
FLAGS_test_int32 = 400;
string value("will be changed");
const bool r = GetCommandLineOption("test_int32", &value);
EXPECT_EQ(true, r);
EXPECT_EQ("400", value);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasSet) {
SetCommandLineOption("test_int32", "700");
string value("will be changed");
const bool r = GetCommandLineOption("test_int32", &value);
EXPECT_EQ(true, r);
EXPECT_EQ("700", value);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) {
// This doesn't set the flag's value, but rather its default value.
// is_default is still true, but the 'default' value returned has changed!
SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT);
string value("will be changed");
const bool r = GetCommandLineOption("test_int32", &value);
EXPECT_EQ(true, r);
EXPECT_EQ("800", value);
EXPECT_EQ(true, GetCommandLineFlagInfoOrDie("test_int32").is_default);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) {
SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT);
string value("will be changed");
const bool r = GetCommandLineOption("test_int32", &value);
EXPECT_EQ(true, r);
EXPECT_EQ("900", value);
}
TEST(GetCommandLineOptionTest, NameDoesNotExist) {
string value("will not be changed");
const bool r = GetCommandLineOption("test_int3210", &value);
EXPECT_EQ(false, r);
EXPECT_EQ("will not be changed", value);
}
TEST(GetCommandLineFlagInfoTest, FlagExists) {
CommandLineFlagInfo info;
bool r = GetCommandLineFlagInfo("test_int32", &info);
EXPECT_EQ(true, r);
EXPECT_EQ("test_int32", info.name);
EXPECT_EQ("int32", info.type);
EXPECT_EQ("", info.description);
EXPECT_EQ("-1", info.current_value);
EXPECT_EQ("-1", info.default_value);
EXPECT_EQ(true, info.is_default);
FLAGS_test_bool = true;
r = GetCommandLineFlagInfo("test_bool", &info);
EXPECT_EQ(true, r);
EXPECT_EQ("test_bool", info.name);
EXPECT_EQ("bool", info.type);
EXPECT_EQ("tests bool-ness", info.description);
EXPECT_EQ("true", info.current_value);
EXPECT_EQ("false", info.default_value);
EXPECT_EQ(false, info.is_default);
FLAGS_test_bool = false;
r = GetCommandLineFlagInfo("test_bool", &info);
EXPECT_EQ(true, r);
EXPECT_EQ("test_bool", info.name);
EXPECT_EQ("bool", info.type);
EXPECT_EQ("tests bool-ness", info.description);
EXPECT_EQ("false", info.current_value);
EXPECT_EQ("false", info.default_value);
EXPECT_EQ(false, info.is_default); // value is same, but flag *was* modified
}
TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) {
CommandLineFlagInfo info;
// Set to some random values that GetCommandLineFlagInfo should not change
info.name = "name";
info.type = "type";
info.current_value = "curr";
info.default_value = "def";
info.filename = "/";
info.is_default = false;
bool r = GetCommandLineFlagInfo("test_int3210", &info);
EXPECT_EQ(false, r);
EXPECT_EQ("name", info.name);
EXPECT_EQ("type", info.type);
EXPECT_EQ("", info.description);
EXPECT_EQ("curr", info.current_value);
EXPECT_EQ("def", info.default_value);
EXPECT_EQ("/", info.filename);
EXPECT_EQ(false, info.is_default);
}
TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) {
CommandLineFlagInfo info;
info = GetCommandLineFlagInfoOrDie("test_int32");
EXPECT_EQ("test_int32", info.name);
EXPECT_EQ("int32", info.type);
EXPECT_EQ("", info.description);
EXPECT_EQ("-1", info.current_value);
EXPECT_EQ("-1", info.default_value);
EXPECT_EQ(true, info.is_default);
info = GetCommandLineFlagInfoOrDie("test_bool");
EXPECT_EQ("test_bool", info.name);
EXPECT_EQ("bool", info.type);
EXPECT_EQ("tests bool-ness", info.description);
EXPECT_EQ("false", info.current_value);
EXPECT_EQ("false", info.default_value);
EXPECT_EQ(true, info.is_default);
}
TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) {
FLAGS_test_int32 = 400;
CommandLineFlagInfo info;
info = GetCommandLineFlagInfoOrDie("test_int32");
EXPECT_EQ("test_int32", info.name);
EXPECT_EQ("int32", info.type);
EXPECT_EQ("", info.description);
EXPECT_EQ("400", info.current_value);
EXPECT_EQ("-1", info.default_value);
EXPECT_EQ(false, info.is_default);
FLAGS_test_bool = true;
info = GetCommandLineFlagInfoOrDie("test_bool");
EXPECT_EQ("test_bool", info.name);
EXPECT_EQ("bool", info.type);
EXPECT_EQ("tests bool-ness", info.description);
EXPECT_EQ("true", info.current_value);
EXPECT_EQ("false", info.default_value);
EXPECT_EQ(false, info.is_default);
}
TEST(GetCommandLineFlagInfoOrDieTest, FlagDoesNotExist) {
EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"),
".*: flag test_int3210 does not exist");
}
// These are lightly tested because they're deprecated. Basically,
// the tests are meant to cover how existing users use these functions,
// but not necessarily how new users could use them.
TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) {
string s = CommandlineFlagsIntoString();
EXPECT_NE(string::npos, s.find("--test_bool="));
}
TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) {
FLAGS_test_int32 = 10; // just to make the test more interesting
string filename(FLAGS_test_tmpdir + "/flagfile");
unlink(filename.c_str()); // just to be safe
const bool r = AppendFlagsIntoFile(filename, "not the real argv0");
EXPECT_EQ(true, r);
FILE* fp = fopen(filename.c_str(), "r");
EXPECT_TRUE(fp != NULL);
char line[8192];
fgets(line, sizeof(line)-1, fp); // first line should be progname
EXPECT_STREQ("not the real argv0\n", line);
bool found_bool = false, found_int32 = false;
while (fgets(line, sizeof(line)-1, fp)) {
line[sizeof(line)-1] = '\0'; // just to be safe
if (strcmp(line, "--test_bool=false\n") == 0)
found_bool = true;
if (strcmp(line, "--test_int32=10\n") == 0)
found_int32 = true;
}
EXPECT_EQ(true, found_int32);
EXPECT_EQ(true, found_bool);
fclose(fp);
}
TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
FLAGS_test_int32 = -10; // just to make the test more interesting
string filename(FLAGS_test_tmpdir + "/flagfile2");
unlink(filename.c_str()); // just to be safe
bool r = AppendFlagsIntoFile(filename, GetArgv0());
EXPECT_EQ(true, r);
FLAGS_test_int32 = -11;
r = ReadFromFlagsFile(filename, GetArgv0(), true);
EXPECT_EQ(true, r);
EXPECT_EQ(-10, FLAGS_test_int32);
}
TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
FLAGS_test_int32 = -20;
string filename(FLAGS_test_tmpdir + "/flagfile3");
FILE* fp = fopen(filename.c_str(), "w");
EXPECT_TRUE(fp != NULL);
// Note the error in the bool assignment below...
fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0());
fclose(fp);
FLAGS_test_int32 = -22;
const bool r = ReadFromFlagsFile(filename, GetArgv0(), false);
EXPECT_EQ(false, r);
EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take
}
TEST(FlagsSetBeforeInitGoogleTest, TryFromEnv) {
EXPECT_EQ("pre-set", FLAGS_test_tryfromenv);
}
// The following test case verifies that ParseCommandLineFlags() and
// ParseCommandLineNonHelpFlags() uses the last definition of a flag
// in case it's defined more than once.
DEFINE_int32(test_flag, -1, "used for testing commandlineflags.cc");
// Returns the definition of the --flagfile flag to be used in the tests.
const char* GetFlagFileFlag() {
static const string flagfile_flag = string("--flagfile=")
+ FLAGS_srcdir + "/src/gflags_unittest_flagfile";
return flagfile_flag.c_str();
}
// Parses and returns the --test_flag flag.
// If with_help is true, calls ParseCommandLineFlags; otherwise calls
// ParseCommandLineNonHelpFlags.
int32 ParseTestFlag(bool with_help, int argc, const char** const_argv) {
FlagSaver fs; // Restores the flags before returning.
// Makes a copy of the input array s.t. it can be reused
// (ParseCommandLineFlags() will alter the array).
char** const argv_save = new char*[argc + 1];
char** argv = argv_save;
memcpy(argv, const_argv, sizeof(*argv)*(argc + 1));
if (with_help) {
ParseCommandLineFlags(&argc, &argv, true);
} else {
ParseCommandLineNonHelpFlags(&argc, &argv, true);
}
delete[] argv_save;
return FLAGS_test_flag;
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
WhenFlagIsDefinedTwiceOnCommandLine) {
const char* argv[] = {
"my_test",
"--test_flag=1",
"--test_flag=2",
NULL,
};
EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
WhenFlagIsDefinedTwiceInFlagFile) {
const char* argv[] = {
"my_test",
GetFlagFileFlag(),
NULL,
};
EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
WhenFlagIsDefinedInCommandLineAndThenFlagFile) {
const char* argv[] = {
"my_test",
"--test_flag=0",
GetFlagFileFlag(),
NULL,
};
EXPECT_EQ(2, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
EXPECT_EQ(2, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
WhenFlagIsDefinedInFlagFileAndThenCommandLine) {
const char* argv[] = {
"my_test",
GetFlagFileFlag(),
"--test_flag=3",
NULL,
};
EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
}
TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
WhenFlagIsDefinedInCommandLineAndFlagFileAndThenCommandLine) {
const char* argv[] = {
"my_test",
"--test_flag=0",
GetFlagFileFlag(),
"--test_flag=3",
NULL,
};
EXPECT_EQ(3, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
}
static int Main(int argc, char **argv) {
// We need to call SetArgv before InitGoogle, so our "test" argv will
// win out over this executable's real argv. That makes running this
// test with a real --help flag kinda annoying, unfortunately.
const char* test_argv[] = { "/test/argv/for/gflags_unittest",
"argv 2", "3rd argv", "argv #4" };
SetArgv(GET_ARRAY_SIZE(test_argv), test_argv);
// The first arg is the usage message, also important for testing.
string usage_message = (string(GetArgv0()) +
": <useless flag> [...]\nDoes something useless.\n");
// We test setting tryfromenv manually, and making sure initgoogle still
// evaluates it.
FLAGS_tryfromenv = "test_tryfromenv";
setenv("FLAGS_test_tryfromenv", "pre-set", 1);
SetUsageMessage(usage_message.c_str());
ParseCommandLineFlags(&argc, &argv, true);
mkdir(FLAGS_test_tmpdir.c_str(), 0755);
return RUN_ALL_TESTS();
}
_END_GOOGLE_NAMESPACE_
int main(int argc, char** argv) {
return GOOGLE_NAMESPACE::Main(argc, argv);
}
google-gflags (0.7-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Thu, 18 Oct 2007 11:33:20 -0700
google-gflags (0.6-2) unstable; urgency=low
* Somehow 0.6-1 was missing the lib* control files, so the .deb produced
......
......@@ -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)
......
#!/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"])])
......@@ -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
......
......@@ -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,24 +227,42 @@ 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 (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)
......@@ -247,11 +275,18 @@ void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
// 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));
}
#endif // DO_NOT_SHOW_COMMANDLINE_HELP
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);
}
ShowUsageWithFlagsMatching(argv0, substrings);
}
void ShowUsageWithFlags(const char *argv0) {
......@@ -276,6 +311,7 @@ static void ShowXMLOfFlags(const char *prog_name) {
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
if (flag->description != kStrippedFlagHelp)
fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
}
// The end of the document
......@@ -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) {
......
......@@ -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);
......
......@@ -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
......@@ -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 { \
#define DECLARE_VARIABLE(namespc, type, shorttype, name) \
namespace fL##shorttype { \
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)); \
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*>(cur_##name.store)); \
*(reinterpret_cast<namespc type*>(s_##name[0].store)); \
char FLAGS_no##name @ac_cv___attribute__unused@; \
} \
using Flag_Names_##type::FLAGS_##name
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment