Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
56a2e686
Commit
56a2e686
authored
Sep 01, 2009
by
zhanyong.wan
Browse files
Enables String to contain NUL (by Zhanyong Wan); Adds scons scripts (by Vlad Losev).
parent
cb2b1640
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
604 additions
and
140 deletions
+604
-140
include/gtest/internal/gtest-string.h
include/gtest/internal/gtest-string.h
+94
-63
scons/SConstruct
scons/SConstruct
+61
-0
scons/SConstruct.common
scons/SConstruct.common
+267
-0
src/gtest-filepath.cc
src/gtest-filepath.cc
+7
-7
src/gtest-port.cc
src/gtest-port.cc
+1
-1
src/gtest.cc
src/gtest.cc
+32
-51
test/gtest-death-test_test.cc
test/gtest-death-test_test.cc
+3
-3
test/gtest_unittest.cc
test/gtest_unittest.cc
+139
-15
No files found.
include/gtest/internal/gtest-string.h
View file @
56a2e686
...
@@ -51,6 +51,22 @@
...
@@ -51,6 +51,22 @@
namespace
testing
{
namespace
testing
{
namespace
internal
{
namespace
internal
{
// Holds data in a String object. We need this class in order to put
// String's data members on the heap instead of on the stack.
// Otherwise tests using many assertions (and thus Strings) in one
// function may need too much stack frame space to compile.
class
StringData
{
StringData
()
:
c_str_
(
NULL
),
length_
(
0
)
{}
~
StringData
()
{
delete
[]
c_str_
;
}
private:
friend
class
String
;
const
char
*
c_str_
;
size_t
length_
;
// Length of the string (excluding the terminating
// '\0' character).
};
// String - a UTF-8 string class.
// String - a UTF-8 string class.
//
//
// We cannot use std::string as Microsoft's STL implementation in
// We cannot use std::string as Microsoft's STL implementation in
...
@@ -80,19 +96,6 @@ class String {
...
@@ -80,19 +96,6 @@ class String {
public:
public:
// Static utility methods
// Static utility methods
// Returns the input if it's not NULL, otherwise returns "(null)".
// This function serves two purposes:
//
// 1. ShowCString(NULL) has type 'const char *', instead of the
// type of NULL (which is int).
//
// 2. In MSVC, streaming a null char pointer to StrStream generates
// an access violation, so we need to convert NULL to "(null)"
// before streaming it.
static
inline
const
char
*
ShowCString
(
const
char
*
c_str
)
{
return
c_str
?
c_str
:
"(null)"
;
}
// Returns the input enclosed in double quotes if it's not NULL;
// Returns the input enclosed in double quotes if it's not NULL;
// otherwise returns "(null)". For example, "\"Hello\"" is returned
// otherwise returns "(null)". For example, "\"Hello\"" is returned
// for input "Hello".
// for input "Hello".
...
@@ -199,27 +202,36 @@ class String {
...
@@ -199,27 +202,36 @@ class String {
// C'tors
// C'tors
// The default c'tor constructs a NULL string.
// The default c'tor constructs a NULL string, which is represented
String
()
:
c_str_
(
NULL
)
{}
// by data_ being NULL.
String
()
:
data_
(
NULL
)
{}
// Constructs a String by cloning a 0-terminated C string.
// Constructs a String by cloning a 0-terminated C string.
String
(
const
char
*
c_str
)
:
c_str_
(
NULL
)
{
// NOLINT
String
(
const
char
*
c_str
)
{
// NOLINT
*
this
=
c_str
;
if
(
c_str
==
NULL
)
{
data_
=
NULL
;
}
else
{
ConstructNonNull
(
c_str
,
strlen
(
c_str
));
}
}
}
// Constructs a String by copying a given number of chars from a
// Constructs a String by copying a given number of chars from a
// buffer. E.g. String("hello", 3) will create the string "hel".
// buffer. E.g. String("hello", 3) creates the string "hel",
String
(
const
char
*
buffer
,
size_t
len
);
// String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
// and String(NULL, 1) results in access violation.
String
(
const
char
*
buffer
,
size_t
length
)
{
ConstructNonNull
(
buffer
,
length
);
}
// The copy c'tor creates a new copy of the string. The two
// The copy c'tor creates a new copy of the string. The two
// String objects do not share content.
// String objects do not share content.
String
(
const
String
&
str
)
:
c_str_
(
NULL
)
{
String
(
const
String
&
str
)
:
data_
(
NULL
)
{
*
this
=
str
;
}
*
this
=
str
;
}
// D'tor. String is intended to be a final class, so the d'tor
// D'tor. String is intended to be a final class, so the d'tor
// doesn't need to be virtual.
// doesn't need to be virtual.
~
String
()
{
delete
[]
c_str_
;
}
~
String
()
{
delete
data_
;
}
// Allows a String to be implicitly converted to an ::std::string or
// Allows a String to be implicitly converted to an ::std::string or
// ::string, and vice versa. Converting a String containing a NULL
// ::string, and vice versa. Converting a String containing a NULL
...
@@ -228,21 +240,23 @@ class String {
...
@@ -228,21 +240,23 @@ class String {
// character to a String will result in the prefix up to the first
// character to a String will result in the prefix up to the first
// NUL character.
// NUL character.
#if GTEST_HAS_STD_STRING
#if GTEST_HAS_STD_STRING
String
(
const
::
std
::
string
&
str
)
:
c_str_
(
NULL
)
{
*
this
=
str
.
c_str
();
}
String
(
const
::
std
::
string
&
str
)
{
ConstructNonNull
(
str
.
c_str
(),
str
.
length
());
}
operator
::
std
::
string
()
const
{
return
::
std
::
string
(
c_str
_
);
}
operator
::
std
::
string
()
const
{
return
::
std
::
string
(
c_str
(),
length
()
);
}
#endif // GTEST_HAS_STD_STRING
#endif // GTEST_HAS_STD_STRING
#if GTEST_HAS_GLOBAL_STRING
#if GTEST_HAS_GLOBAL_STRING
String
(
const
::
string
&
str
)
:
c_str_
(
NULL
)
{
*
this
=
str
.
c_str
();
}
String
(
const
::
string
&
str
)
{
ConstructNonNull
(
str
.
c_str
(),
str
.
length
());
}
operator
::
string
()
const
{
return
::
string
(
c_str
_
);
}
operator
::
string
()
const
{
return
::
string
(
c_str
(),
length
()
);
}
#endif // GTEST_HAS_GLOBAL_STRING
#endif // GTEST_HAS_GLOBAL_STRING
// Returns true iff this is an empty string (i.e. "").
// Returns true iff this is an empty string (i.e. "").
bool
empty
()
const
{
bool
empty
()
const
{
return
(
c_str
()
!=
NULL
)
&&
(
length
()
==
0
);
}
return
(
c_str_
!=
NULL
)
&&
(
*
c_str_
==
'\0'
);
}
// Compares this with another String.
// Compares this with another String.
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
...
@@ -251,19 +265,15 @@ class String {
...
@@ -251,19 +265,15 @@ class String {
// Returns true iff this String equals the given C string. A NULL
// Returns true iff this String equals the given C string. A NULL
// string and a non-NULL string are considered not equal.
// string and a non-NULL string are considered not equal.
bool
operator
==
(
const
char
*
c_str
)
const
{
bool
operator
==
(
const
char
*
c_str
)
const
{
return
Compare
(
c_str
)
==
0
;
}
return
CStringEquals
(
c_str_
,
c_str
);
}
// Returns true iff this String is less than the given
C s
tring. A
NULL
// Returns true iff this String is less than the given
S
tring. A
// string is considered less than "".
//
NULL
string is considered less than "".
bool
operator
<
(
const
String
&
rhs
)
const
{
return
Compare
(
rhs
)
<
0
;
}
bool
operator
<
(
const
String
&
rhs
)
const
{
return
Compare
(
rhs
)
<
0
;
}
// Returns true iff this String doesn't equal the given C string. A NULL
// Returns true iff this String doesn't equal the given C string. A NULL
// string and a non-NULL string are considered not equal.
// string and a non-NULL string are considered not equal.
bool
operator
!=
(
const
char
*
c_str
)
const
{
bool
operator
!=
(
const
char
*
c_str
)
const
{
return
!
(
*
this
==
c_str
);
}
return
!
CStringEquals
(
c_str_
,
c_str
);
}
// Returns true iff this String ends with the given suffix. *Any*
// Returns true iff this String ends with the given suffix. *Any*
// String is considered to end with a NULL or empty suffix.
// String is considered to end with a NULL or empty suffix.
...
@@ -273,45 +283,66 @@ class String {
...
@@ -273,45 +283,66 @@ class String {
// case. Any String is considered to end with a NULL or empty suffix.
// case. Any String is considered to end with a NULL or empty suffix.
bool
EndsWithCaseInsensitive
(
const
char
*
suffix
)
const
;
bool
EndsWithCaseInsensitive
(
const
char
*
suffix
)
const
;
// Returns the length of the encapsulated string, or
-1
if the
// Returns the length of the encapsulated string, or
0
if the
// string is NULL.
// string is NULL.
int
GetLength
()
const
{
size_t
length
()
const
{
return
(
data_
==
NULL
)
?
0
:
data_
->
length_
;
}
return
c_str_
?
static_cast
<
int
>
(
strlen
(
c_str_
))
:
-
1
;
}
// Gets the 0-terminated C string this String object represents.
// Gets the 0-terminated C string this String object represents.
// The String object still owns the string. Therefore the caller
// The String object still owns the string. Therefore the caller
// should NOT delete the return value.
// should NOT delete the return value.
const
char
*
c_str
()
const
{
return
c_str_
;
}
const
char
*
c_str
()
const
{
return
(
data_
==
NULL
)
?
NULL
:
data_
->
c_str_
;
}
// Sets the 0-terminated C string this String object represents.
// The old string in this object is deleted, and this object will
// own a clone of the input string. This function copies only up to
// length bytes (plus a terminating null byte), or until the first
// null byte, whichever comes first.
//
// This function works even when the c_str parameter has the same
// value as that of the c_str_ field.
void
Set
(
const
char
*
c_str
,
size_t
length
);
// Assigns a C string to this object. Self-assignment works.
// Assigns a C string to this object. Self-assignment works.
const
String
&
operator
=
(
const
char
*
c_str
)
;
const
String
&
operator
=
(
const
char
*
c_str
)
{
return
*
this
=
String
(
c_str
);
}
// Assigns a String object to this object. Self-assignment works.
// Assigns a String object to this object. Self-assignment works.
const
String
&
operator
=
(
const
String
&
rhs
)
{
const
String
&
operator
=
(
const
String
&
rhs
)
{
*
this
=
rhs
.
c_str_
;
if
(
this
!=
&
rhs
)
{
delete
data_
;
data_
=
NULL
;
if
(
rhs
.
data_
!=
NULL
)
{
ConstructNonNull
(
rhs
.
data_
->
c_str_
,
rhs
.
data_
->
length_
);
}
}
return
*
this
;
return
*
this
;
}
}
private:
private:
const
char
*
c_str_
;
// Constructs a non-NULL String from the given content. This
};
// function can only be called when data_ has not been allocated.
// ConstructNonNull(NULL, 0) results in an empty string ("").
// ConstructNonNull(NULL, non_zero) is undefined behavior.
void
ConstructNonNull
(
const
char
*
buffer
,
size_t
length
)
{
data_
=
new
StringData
;
char
*
const
str
=
new
char
[
length
+
1
];
memcpy
(
str
,
buffer
,
length
);
str
[
length
]
=
'\0'
;
data_
->
c_str_
=
str
;
data_
->
length_
=
length
;
}
// Streams a String to an ostream.
// Points to the representation of the String. A NULL String is
inline
::
std
::
ostream
&
operator
<<
(
::
std
::
ostream
&
os
,
const
String
&
str
)
{
// represented by data_ == NULL.
// We call String::ShowCString() to convert NULL to "(null)".
StringData
*
data_
;
// Otherwise we'll get an access violation on Windows.
};
// class String
return
os
<<
String
::
ShowCString
(
str
.
c_str
());
// Streams a String to an ostream. Each '\0' character in the String
// is replaced with "\\0".
inline
::
std
::
ostream
&
operator
<<
(
::
std
::
ostream
&
os
,
const
String
&
str
)
{
if
(
str
.
c_str
()
==
NULL
)
{
os
<<
"(null)"
;
}
else
{
const
char
*
const
c_str
=
str
.
c_str
();
for
(
size_t
i
=
0
;
i
!=
str
.
length
();
i
++
)
{
if
(
c_str
[
i
]
==
'\0'
)
{
os
<<
"
\\
0"
;
}
else
{
os
<<
c_str
[
i
];
}
}
}
return
os
;
}
}
// Gets the content of the StrStream's buffer as a String. Each '\0'
// Gets the content of the StrStream's buffer as a String. Each '\0'
...
...
scons/SConstruct
0 → 100644
View file @
56a2e686
# -*- Python -*-
# Copyright 2008 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: joi@google.com (Joi Sigurdsson)
# Author: vladl@google.com (Vlad Losev)
#
# Base build file for Google Test Tests.
#
# Usage:
# cd to the directory with this file, then
# ./scons.py [OPTIONS]
#
# where frequently used command-line options include:
# -h print usage help.
# BUILD=all build all build types.
# BUILD=win-opt build the given build type.
EnsurePythonVersion
(
2
,
3
)
sconstruct_helper
=
SConscript
(
'SConstruct.common'
)
sconstruct_helper
.
Initialize
(
build_root_path
=
'..'
,
support_multiple_win_builds
=
False
)
win_base
=
sconstruct_helper
.
MakeWinBaseEnvironment
()
if
win_base
.
get
(
'MSVS_VERSION'
,
None
)
==
'7.1'
:
sconstruct_helper
.
AllowVc71StlWithoutExceptions
(
win_base
)
sconstruct_helper
.
MakeWinDebugEnvironment
(
win_base
,
'win-dbg'
)
sconstruct_helper
.
MakeWinOptimizedEnvironment
(
win_base
,
'win-opt'
)
sconstruct_helper
.
ConfigureGccEnvironments
()
sconstruct_helper
.
BuildSelectedEnvironments
()
scons/SConstruct.common
0 → 100644
View file @
56a2e686
# -*- Python -*-
# Copyright 2008 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: joi@google.com (Joi Sigurdsson)
# Author: vladl@google.com (Vlad Losev)
#
# Shared SCons utilities for building Google Test inside and outside of
# Google's environment.
#
EnsurePythonVersion(2, 3)
BUILD_DIR_PREFIX = 'build'
class SConstructHelper:
def __init__(self):
# A dictionary to look up an environment by its name.
self.env_dict = {}
def Initialize(self, build_root_path, support_multiple_win_builds=False):
test_env = Environment()
platform = test_env['PLATFORM']
if platform == 'win32':
if support_multiple_win_builds:
available_build_types = ['win-dbg8', 'win-opt8', 'win-dbg', 'win-opt']
else:
available_build_types = ['win-dbg', 'win-opt']
elif platform == 'darwin': # MacOSX
available_build_types = ['mac-dbg', 'mac-opt']
else:
available_build_types = ['dbg', 'opt'] # Assuming POSIX-like environment
# with GCC by default.
vars = Variables()
vars.Add(ListVariable('BUILD', 'Build type', available_build_types[0],
available_build_types))
vars.Add(BoolVariable('GTEST_BUILD_SAMPLES', 'Build samples', False))
# Create base environment.
self.env_base = Environment(variables=vars,
BUILD_MODE={'BUILD' : '"${BUILD}"'})
# Leave around a variable pointing at the build root so that SConscript
# files from outside our project root can find their bearings. Trick
# borrowed from Hammer in Software Construction Toolkit
# (http://code.google.com/p/swtoolkit/); if/when we switch to using the
# Hammer idioms instead of just Hammer's version of SCons, we should be
# able to remove this line.
self.env_base['SOURCE_ROOT'] = self.env_base.Dir(build_root_path)
# And another that definitely always points to the project root.
self.env_base['PROJECT_ROOT'] = self.env_base.Dir('.').abspath
# Enable scons -h
Help(vars.GenerateHelpText(self.env_base))
def AllowVc71StlWithoutExceptions(self, env):
env.Append(
CPPDEFINES = [# needed for using some parts of STL with exception
# disabled. The scoop is given here, with comments
# from P.J. Plauger at
# http://groups.google.com/group/microsoft.public.vc.stl/browse_thread/thread/5e719833c6bdb177?q=_HAS_EXCEPTIONS+using+namespace+std&pli=1
'_TYPEINFO_'])
def MakeWinBaseEnvironment(self):
win_base = self.env_base.Clone(
platform='win32',
CCFLAGS=['-GS', # Enable buffer security check
'-W4', # Warning level
# Disables warnings that are either uninteresting or
# hard to fix.
'/wd4100',
# unreferenced formal parameter. The violation is in
# gcc's TR1 tuple and hard to fix.
'/wd4127',
# constant conditional expression. The macro
# GTEST_IS_NULL_LITERAL_() triggers it and I cannot find
# a fix.
'/wd4511', '/wd4512',
# copy ctor / assignment operator cannot be generated.
'-WX', # Treat warning as errors
#'-GR-', # Disable runtime type information
'-RTCs', # Enable stack-frame run-time error checks
'-RTCu', # Report when variable used without init.
#'-EHs', # enable C++ EH (no SEH exceptions)
'-nologo', # Suppress logo line
'-J', # All chars unsigned
#'-Wp64', # Detect 64-bit portability issues
'-Zi', # Produce debug information in PDB files.
],
CCPDBFLAGS='',
CPPDEFINES=['_UNICODE', 'UNICODE',
'WIN32', '_WIN32',
'STRICT',
'WIN32_LEAN_AND_MEAN',
'_HAS_EXCEPTIONS=0',
],
LIBPATH=['#/$MAIN_DIR/lib'],
LINKFLAGS=['-MACHINE:x86', # Enable safe SEH (not supp. on x64)
'-DEBUG', # Generate debug info
'-NOLOGO', # Suppress logo line
],
# All strings in string tables zero terminated.
RCFLAGS=['-n'])
return win_base
def SetBuildNameAndDir(self, env, name):
env['BUILD_NAME'] = name;
env['BUILD_DIR'] = '%s/%s' % (BUILD_DIR_PREFIX, name)
self.env_dict[name] = env
def MakeWinDebugEnvironment(self, base_environment, name):
"""Takes a VC71 or VC80 base environment and adds debug settings."""
debug_env = base_environment.Clone()
self.SetBuildNameAndDir(debug_env, name)
debug_env.Append(
CCFLAGS = ['-Od', # Disable optimizations
'-MTd', # Multithreaded, static link (debug)
# Path for PDB files
'-Fd%s\\' % debug_env.Dir(debug_env['BUILD_DIR']),
],
CPPDEFINES = ['DEBUG',
'_DEBUG',
],
LIBPATH = [],
LINKFLAGS = ['-INCREMENTAL:yes',
'/OPT:NOICF',
]
)
# Tell SCons to build depdendencies in random order (apart from the
# actual dependency order). This helps ensure we don't introduce
# build files that "accidentally" work sometimes (e.g. when you are
# building some targets) and not other times.
debug_env.SetOption('random', 1)
return debug_env
def MakeWinOptimizedEnvironment(self, base_environment, name):
"""Takes a VC71 or VC80 base environment and adds release settings."""
optimized_env = base_environment.Clone()
self.SetBuildNameAndDir(optimized_env, name)
optimized_env.Append(
CCFLAGS = ['-GL', # Enable link-time code generation (/GL)
'-GF', # Enable String Pooling (/GF)
'-MT', # Multithreaded, static link
# Path for PDB files
'-Fd%s\\' % optimized_env.Dir(optimized_env['BUILD_DIR']),
# Favor small code (this is /O1 minus /Og)
'-Os',
'-Oy',
'-Ob2',
'-Gs',
'-GF',
'-Gy',
],
CPPDEFINES = ['NDEBUG',
'_NDEBUG',
],
LIBPATH = [],
ARFLAGS = ['-LTCG'], # Link-time Code Generation
LINKFLAGS = ['-LTCG', # Link-time Code Generation
'-OPT:REF', # Optimize by reference.
'-OPT:ICF=32', # Optimize by identical COMDAT folding
'-OPT:NOWIN98', # Optimize by not aligning section for
# Win98
'-INCREMENTAL:NO', # No incremental linking as we don't
# want padding bytes in release build.
],
)
return optimized_env
def AddGccFlagsTo(self, env, optimized):
env.Append(CCFLAGS=['-fno-exceptions',
'-Wall',
'-Werror',
])
if optimized:
env.Append(CCFLAGS=['-O2'], CPPDEFINES=['NDEBUG', '_NDEBUG'])
else:
env.Append(CCFLAGS=['-g'], CPPDEFINES=['DEBUG', '_DEBUG'])
def ConfigureGccEnvironments(self):
# Mac environments.
mac_base = self.env_base.Clone(platform='darwin')
mac_dbg = mac_base.Clone()
self.AddGccFlagsTo(mac_dbg, optimized=False)
self.SetBuildNameAndDir(mac_dbg, 'mac-dbg')
mac_opt = mac_base.Clone()
self.AddGccFlagsTo(mac_opt, optimized=True)
self.SetBuildNameAndDir(mac_opt, 'mac-opt')
# Generic GCC environments.
gcc_dbg = self.env_base.Clone()
self.AddGccFlagsTo(gcc_dbg, optimized=False)
self.SetBuildNameAndDir(gcc_dbg, 'dbg')
gcc_opt = self.env_base.Clone()
self.AddGccFlagsTo(gcc_opt, optimized=True)
self.SetBuildNameAndDir(gcc_opt, 'opt')
def BuildSelectedEnvironments(self):
# Build using whichever environments the 'BUILD' option selected
for build_name in self.env_base['BUILD']:
print 'BUILDING %s' % build_name
env = self.env_dict[build_name]
# Make sure SConscript files can refer to base build dir
env['MAIN_DIR'] = env.Dir(env['BUILD_DIR'])
#print 'CCFLAGS: %s' % env.subst('$CCFLAGS')
#print 'LINK: %s' % env.subst('$LINK')
#print 'AR: %s' % env.subst('$AR')
#print 'CC: %s' % env.subst('$CC')
#print 'CXX: %s' % env.subst('$CXX')
#print 'LIBPATH: %s' % env.subst('$LIBPATH')
#print 'ENV:PATH: %s' % env['ENV']['PATH']
#print 'ENV:INCLUDE: %s' % env['ENV']['INCLUDE']
#print 'ENV:LIB: %s' % env['ENV']['LIB']
#print 'ENV:TEMP: %s' % env['ENV']['TEMP']
Export('env')
# Invokes SConscript with variant_dir being build/<config name>.
# Counter-intuitively, src_dir is relative to the build dir and has
# to be '..' to point to the scons directory.
SConscript('SConscript',
src_dir='..',
variant_dir=env['BUILD_DIR'],
duplicate=0)
sconstruct_helper = SConstructHelper()
Return('sconstruct_helper')
src/gtest-filepath.cc
View file @
56a2e686
...
@@ -103,7 +103,7 @@ FilePath FilePath::GetCurrentDir() {
...
@@ -103,7 +103,7 @@ FilePath FilePath::GetCurrentDir() {
FilePath
FilePath
::
RemoveExtension
(
const
char
*
extension
)
const
{
FilePath
FilePath
::
RemoveExtension
(
const
char
*
extension
)
const
{
String
dot_extension
(
String
::
Format
(
".%s"
,
extension
));
String
dot_extension
(
String
::
Format
(
".%s"
,
extension
));
if
(
pathname_
.
EndsWithCaseInsensitive
(
dot_extension
.
c_str
()))
{
if
(
pathname_
.
EndsWithCaseInsensitive
(
dot_extension
.
c_str
()))
{
return
FilePath
(
String
(
pathname_
.
c_str
(),
pathname_
.
GetL
ength
()
-
4
));
return
FilePath
(
String
(
pathname_
.
c_str
(),
pathname_
.
l
ength
()
-
4
));
}
}
return
*
this
;
return
*
this
;
}
}
...
@@ -217,7 +217,7 @@ bool FilePath::IsRootDirectory() const {
...
@@ -217,7 +217,7 @@ bool FilePath::IsRootDirectory() const {
// TODO(wan@google.com): on Windows a network share like
// TODO(wan@google.com): on Windows a network share like
// \\server\share can be a root directory, although it cannot be the
// \\server\share can be a root directory, although it cannot be the
// current directory. Handle this properly.
// current directory. Handle this properly.
return
pathname_
.
GetL
ength
()
==
3
&&
IsAbsolutePath
();
return
pathname_
.
l
ength
()
==
3
&&
IsAbsolutePath
();
#else
#else
return
pathname_
==
kPathSeparatorString
;
return
pathname_
==
kPathSeparatorString
;
#endif
#endif
...
@@ -227,7 +227,7 @@ bool FilePath::IsRootDirectory() const {
...
@@ -227,7 +227,7 @@ bool FilePath::IsRootDirectory() const {
bool
FilePath
::
IsAbsolutePath
()
const
{
bool
FilePath
::
IsAbsolutePath
()
const
{
const
char
*
const
name
=
pathname_
.
c_str
();
const
char
*
const
name
=
pathname_
.
c_str
();
#if GTEST_OS_WINDOWS
#if GTEST_OS_WINDOWS
return
pathname_
.
GetL
ength
()
>=
3
&&
return
pathname_
.
l
ength
()
>=
3
&&
((
name
[
0
]
>=
'a'
&&
name
[
0
]
<=
'z'
)
||
((
name
[
0
]
>=
'a'
&&
name
[
0
]
<=
'z'
)
||
(
name
[
0
]
>=
'A'
&&
name
[
0
]
<=
'Z'
))
&&
(
name
[
0
]
>=
'A'
&&
name
[
0
]
<=
'Z'
))
&&
name
[
1
]
==
':'
&&
name
[
1
]
==
':'
&&
...
@@ -271,7 +271,7 @@ bool FilePath::CreateDirectoriesRecursively() const {
...
@@ -271,7 +271,7 @@ bool FilePath::CreateDirectoriesRecursively() const {
return
false
;
return
false
;
}
}
if
(
pathname_
.
GetL
ength
()
==
0
||
this
->
DirectoryExists
())
{
if
(
pathname_
.
l
ength
()
==
0
||
this
->
DirectoryExists
())
{
return
true
;
return
true
;
}
}
...
@@ -307,7 +307,7 @@ bool FilePath::CreateFolder() const {
...
@@ -307,7 +307,7 @@ bool FilePath::CreateFolder() const {
// On Windows platform, uses \ as the separator, other platforms use /.
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath
FilePath
::
RemoveTrailingPathSeparator
()
const
{
FilePath
FilePath
::
RemoveTrailingPathSeparator
()
const
{
return
pathname_
.
EndsWith
(
kPathSeparatorString
)
return
pathname_
.
EndsWith
(
kPathSeparatorString
)
?
FilePath
(
String
(
pathname_
.
c_str
(),
pathname_
.
GetL
ength
()
-
1
))
?
FilePath
(
String
(
pathname_
.
c_str
(),
pathname_
.
l
ength
()
-
1
))
:
*
this
;
:
*
this
;
}
}
...
@@ -320,9 +320,9 @@ void FilePath::Normalize() {
...
@@ -320,9 +320,9 @@ void FilePath::Normalize() {
return
;
return
;
}
}
const
char
*
src
=
pathname_
.
c_str
();
const
char
*
src
=
pathname_
.
c_str
();
char
*
const
dest
=
new
char
[
pathname_
.
GetL
ength
()
+
1
];
char
*
const
dest
=
new
char
[
pathname_
.
l
ength
()
+
1
];
char
*
dest_ptr
=
dest
;
char
*
dest_ptr
=
dest
;
memset
(
dest_ptr
,
0
,
pathname_
.
GetL
ength
()
+
1
);
memset
(
dest_ptr
,
0
,
pathname_
.
l
ength
()
+
1
);
while
(
*
src
!=
'\0'
)
{
while
(
*
src
!=
'\0'
)
{
*
dest_ptr
++
=
*
src
;
*
dest_ptr
++
=
*
src
;
...
...
src/gtest-port.cc
View file @
56a2e686
...
@@ -585,7 +585,7 @@ static String FlagToEnvVar(const char* flag) {
...
@@ -585,7 +585,7 @@ static String FlagToEnvVar(const char* flag) {
(
Message
()
<<
GTEST_FLAG_PREFIX_
<<
flag
).
GetString
();
(
Message
()
<<
GTEST_FLAG_PREFIX_
<<
flag
).
GetString
();
Message
env_var
;
Message
env_var
;
for
(
in
t
i
=
0
;
i
!=
full_flag
.
GetL
ength
();
i
++
)
{
for
(
size_
t
i
=
0
;
i
!=
full_flag
.
l
ength
();
i
++
)
{
env_var
<<
static_cast
<
char
>
(
toupper
(
full_flag
.
c_str
()[
i
]));
env_var
<<
static_cast
<
char
>
(
toupper
(
full_flag
.
c_str
()[
i
]));
}
}
...
...
src/gtest.cc
View file @
56a2e686
...
@@ -445,7 +445,7 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
...
@@ -445,7 +445,7 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
positive
=
GTEST_FLAG
(
filter
).
c_str
();
// Whole string is a positive filter
positive
=
GTEST_FLAG
(
filter
).
c_str
();
// Whole string is a positive filter
negative
=
String
(
""
);
negative
=
String
(
""
);
}
else
{
}
else
{
positive
.
Set
(
p
,
dash
-
p
);
// Everything up to the dash
positive
=
String
(
p
,
dash
-
p
);
// Everything up to the dash
negative
=
String
(
dash
+
1
);
// Everything after the dash
negative
=
String
(
dash
+
1
);
// Everything after the dash
if
(
positive
.
empty
())
{
if
(
positive
.
empty
())
{
// Treat '-test1' as the same as '*-test1'
// Treat '-test1' as the same as '*-test1'
...
@@ -926,17 +926,17 @@ bool String::CStringEquals(const char * lhs, const char * rhs) {
...
@@ -926,17 +926,17 @@ bool String::CStringEquals(const char * lhs, const char * rhs) {
// Converts an array of wide chars to a narrow string using the UTF-8
// Converts an array of wide chars to a narrow string using the UTF-8
// encoding, and streams the result to the given Message object.
// encoding, and streams the result to the given Message object.
static
void
StreamWideCharsToMessage
(
const
wchar_t
*
wstr
,
size_t
len
,
static
void
StreamWideCharsToMessage
(
const
wchar_t
*
wstr
,
size_t
len
gth
,
Message
*
msg
)
{
Message
*
msg
)
{
// TODO(wan): consider allowing a testing::String object to
// TODO(wan): consider allowing a testing::String object to
// contain '\0'. This will make it behave more like std::string,
// contain '\0'. This will make it behave more like std::string,
// and will allow ToUtf8String() to return the correct encoding
// and will allow ToUtf8String() to return the correct encoding
// for '\0' s.t. we can get rid of the conditional here (and in
// for '\0' s.t. we can get rid of the conditional here (and in
// several other places).
// several other places).
for
(
size_t
i
=
0
;
i
!=
len
;
)
{
// NOLINT
for
(
size_t
i
=
0
;
i
!=
len
gth
;
)
{
// NOLINT
if
(
wstr
[
i
]
!=
L'\0'
)
{
if
(
wstr
[
i
]
!=
L'\0'
)
{
*
msg
<<
WideStringToUtf8
(
wstr
+
i
,
static_cast
<
int
>
(
len
-
i
));
*
msg
<<
WideStringToUtf8
(
wstr
+
i
,
static_cast
<
int
>
(
len
gth
-
i
));
while
(
i
!=
len
&&
wstr
[
i
]
!=
L'\0'
)
while
(
i
!=
len
gth
&&
wstr
[
i
]
!=
L'\0'
)
i
++
;
i
++
;
}
else
{
}
else
{
*
msg
<<
'\0'
;
*
msg
<<
'\0'
;
...
@@ -1679,24 +1679,30 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
...
@@ -1679,24 +1679,30 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
#endif // OS selector
#endif // OS selector
}
}
// Constructs a String by copying a given number of chars from a
// buffer. E.g. String("hello", 3) will create the string "hel".
String
::
String
(
const
char
*
buffer
,
size_t
len
)
{
char
*
const
temp
=
new
char
[
len
+
1
];
memcpy
(
temp
,
buffer
,
len
);
temp
[
len
]
=
'\0'
;
c_str_
=
temp
;
}
// Compares this with another String.
// Compares this with another String.
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
// if this is greater than rhs.
// if this is greater than rhs.
int
String
::
Compare
(
const
String
&
rhs
)
const
{
int
String
::
Compare
(
const
String
&
rhs
)
const
{
if
(
c_str_
==
NULL
)
{
const
char
*
const
lhs_c_str
=
c_str
();
return
rhs
.
c_str_
==
NULL
?
0
:
-
1
;
// NULL < anything except NULL
const
char
*
const
rhs_c_str
=
rhs
.
c_str
();
if
(
lhs_c_str
==
NULL
)
{
return
rhs_c_str
==
NULL
?
0
:
-
1
;
// NULL < anything except NULL
}
else
if
(
rhs_c_str
==
NULL
)
{
return
1
;
}
}
return
rhs
.
c_str_
==
NULL
?
1
:
strcmp
(
c_str_
,
rhs
.
c_str_
);
const
size_t
shorter_str_len
=
length
()
<=
rhs
.
length
()
?
length
()
:
rhs
.
length
();
for
(
size_t
i
=
0
;
i
!=
shorter_str_len
;
i
++
)
{
if
(
lhs_c_str
[
i
]
<
rhs_c_str
[
i
])
{
return
-
1
;
}
else
if
(
lhs_c_str
[
i
]
>
rhs_c_str
[
i
])
{
return
1
;
}
}
return
(
length
()
<
rhs
.
length
())
?
-
1
:
(
length
()
>
rhs
.
length
())
?
1
:
0
;
}
}
// Returns true iff this String ends with the given suffix. *Any*
// Returns true iff this String ends with the given suffix. *Any*
...
@@ -1704,12 +1710,12 @@ int String::Compare(const String & rhs) const {
...
@@ -1704,12 +1710,12 @@ int String::Compare(const String & rhs) const {
bool
String
::
EndsWith
(
const
char
*
suffix
)
const
{
bool
String
::
EndsWith
(
const
char
*
suffix
)
const
{
if
(
suffix
==
NULL
||
CStringEquals
(
suffix
,
""
))
return
true
;
if
(
suffix
==
NULL
||
CStringEquals
(
suffix
,
""
))
return
true
;
if
(
c_str
_
==
NULL
)
return
false
;
if
(
c_str
()
==
NULL
)
return
false
;
const
size_t
this_len
=
strlen
(
c_str
_
);
const
size_t
this_len
=
strlen
(
c_str
()
);
const
size_t
suffix_len
=
strlen
(
suffix
);
const
size_t
suffix_len
=
strlen
(
suffix
);
return
(
this_len
>=
suffix_len
)
&&
return
(
this_len
>=
suffix_len
)
&&
CStringEquals
(
c_str
_
+
this_len
-
suffix_len
,
suffix
);
CStringEquals
(
c_str
()
+
this_len
-
suffix_len
,
suffix
);
}
}
// Returns true iff this String ends with the given suffix, ignoring case.
// Returns true iff this String ends with the given suffix, ignoring case.
...
@@ -1717,37 +1723,12 @@ bool String::EndsWith(const char* suffix) const {
...
@@ -1717,37 +1723,12 @@ bool String::EndsWith(const char* suffix) const {
bool
String
::
EndsWithCaseInsensitive
(
const
char
*
suffix
)
const
{
bool
String
::
EndsWithCaseInsensitive
(
const
char
*
suffix
)
const
{
if
(
suffix
==
NULL
||
CStringEquals
(
suffix
,
""
))
return
true
;
if
(
suffix
==
NULL
||
CStringEquals
(
suffix
,
""
))
return
true
;
if
(
c_str
_
==
NULL
)
return
false
;
if
(
c_str
()
==
NULL
)
return
false
;
const
size_t
this_len
=
strlen
(
c_str
_
);
const
size_t
this_len
=
strlen
(
c_str
()
);
const
size_t
suffix_len
=
strlen
(
suffix
);
const
size_t
suffix_len
=
strlen
(
suffix
);
return
(
this_len
>=
suffix_len
)
&&
return
(
this_len
>=
suffix_len
)
&&
CaseInsensitiveCStringEquals
(
c_str_
+
this_len
-
suffix_len
,
suffix
);
CaseInsensitiveCStringEquals
(
c_str
()
+
this_len
-
suffix_len
,
suffix
);
}
// Sets the 0-terminated C string this String object represents. The
// old string in this object is deleted, and this object will own a
// clone of the input string. This function copies only up to length
// bytes (plus a terminating null byte), or until the first null byte,
// whichever comes first.
//
// This function works even when the c_str parameter has the same
// value as that of the c_str_ field.
void
String
::
Set
(
const
char
*
c_str
,
size_t
length
)
{
// Makes sure this works when c_str == c_str_
const
char
*
const
temp
=
CloneString
(
c_str
,
length
);
delete
[]
c_str_
;
c_str_
=
temp
;
}
// Assigns a C string to this object. Self-assignment works.
const
String
&
String
::
operator
=
(
const
char
*
c_str
)
{
// Makes sure this works when c_str == c_str_
if
(
c_str
!=
c_str_
)
{
delete
[]
c_str_
;
c_str_
=
CloneCString
(
c_str
);
}
return
*
this
;
}
}
// Formats a list of arguments to a String, using the same format
// Formats a list of arguments to a String, using the same format
...
@@ -1778,7 +1759,7 @@ String String::Format(const char * format, ...) {
...
@@ -1778,7 +1759,7 @@ String String::Format(const char * format, ...) {
#endif // _MSC_VER
#endif // _MSC_VER
va_end
(
args
);
va_end
(
args
);
return
String
(
size
>=
0
?
buffer
:
"<buffer exceeded>"
);
return
(
size
>=
0
)
?
String
(
buffer
,
size
)
:
String
(
"<buffer exceeded>"
);
}
}
// Converts the buffer in a StrStream to a String, converting NUL
// Converts the buffer in a StrStream to a String, converting NUL
...
@@ -3491,7 +3472,7 @@ int UnitTest::Run() {
...
@@ -3491,7 +3472,7 @@ int UnitTest::Run() {
// Catch SEH-style exceptions.
// Catch SEH-style exceptions.
const
bool
in_death_test_child_process
=
const
bool
in_death_test_child_process
=
internal
::
GTEST_FLAG
(
internal_run_death_test
).
GetL
ength
()
>
0
;
internal
::
GTEST_FLAG
(
internal_run_death_test
).
l
ength
()
>
0
;
// Either the user wants Google Test to catch exceptions thrown by the
// Either the user wants Google Test to catch exceptions thrown by the
// tests or this is executing in the context of death test child
// tests or this is executing in the context of death test child
...
@@ -4161,7 +4142,7 @@ const char* ParseFlagValue(const char* str,
...
@@ -4161,7 +4142,7 @@ const char* ParseFlagValue(const char* str,
// The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
// The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
const
String
flag_str
=
String
::
Format
(
"--%s%s"
,
GTEST_FLAG_PREFIX_
,
flag
);
const
String
flag_str
=
String
::
Format
(
"--%s%s"
,
GTEST_FLAG_PREFIX_
,
flag
);
const
size_t
flag_len
=
flag_str
.
GetL
ength
();
const
size_t
flag_len
=
flag_str
.
l
ength
();
if
(
strncmp
(
str
,
flag_str
.
c_str
(),
flag_len
)
!=
0
)
return
NULL
;
if
(
strncmp
(
str
,
flag_str
.
c_str
(),
flag_len
)
!=
0
)
return
NULL
;
// Skips the flag name.
// Skips the flag name.
...
...
test/gtest-death-test_test.cc
View file @
56a2e686
...
@@ -292,7 +292,7 @@ TEST_F(TestForDeathTest, SingleStatement) {
...
@@ -292,7 +292,7 @@ TEST_F(TestForDeathTest, SingleStatement) {
}
}
void
DieWithEmbeddedNul
()
{
void
DieWithEmbeddedNul
()
{
fprintf
(
stderr
,
"Hello%cworld.
\n
"
,
'\0'
);
fprintf
(
stderr
,
"Hello%c
my null
world.
\n
"
,
'\0'
);
fflush
(
stderr
);
fflush
(
stderr
);
_exit
(
1
);
_exit
(
1
);
}
}
...
@@ -303,8 +303,8 @@ void DieWithEmbeddedNul() {
...
@@ -303,8 +303,8 @@ void DieWithEmbeddedNul() {
TEST_F
(
TestForDeathTest
,
EmbeddedNulInMessage
)
{
TEST_F
(
TestForDeathTest
,
EmbeddedNulInMessage
)
{
// TODO(wan@google.com): <regex.h> doesn't support matching strings
// TODO(wan@google.com): <regex.h> doesn't support matching strings
// with embedded NUL characters - find a way to workaround it.
// with embedded NUL characters - find a way to workaround it.
EXPECT_DEATH
(
DieWithEmbeddedNul
(),
"
w.*
ld"
);
EXPECT_DEATH
(
DieWithEmbeddedNul
(),
"
my null wor
ld"
);
ASSERT_DEATH
(
DieWithEmbeddedNul
(),
"
w.*
ld"
);
ASSERT_DEATH
(
DieWithEmbeddedNul
(),
"
my null wor
ld"
);
}
}
#endif // GTEST_USES_PCRE
#endif // GTEST_USES_PCRE
...
...
test/gtest_unittest.cc
View file @
56a2e686
...
@@ -697,25 +697,61 @@ TEST(ListDeathTest, GetElement) {
...
@@ -697,25 +697,61 @@ TEST(ListDeathTest, GetElement) {
// Tests the String class.
// Tests the String class.
TEST
(
StringTest
,
SizeIsSmall
)
{
// To avoid breaking clients that use lots of assertions in one
// function, we cannot grow the size of String.
EXPECT_LE
(
sizeof
(
String
),
sizeof
(
void
*
));
}
// Tests String's constructors.
// Tests String's constructors.
TEST
(
StringTest
,
Constructors
)
{
TEST
(
StringTest
,
Constructors
)
{
// Default ctor.
// Default ctor.
String
s1
;
String
s1
;
// We aren't using EXPECT_EQ(NULL, s1.c_str()) because comparing
// We aren't using EXPECT_EQ(NULL, s1.c_str()) because comparing
// pointers with NULL isn't supported on all platforms.
// pointers with NULL isn't supported on all platforms.
EXPECT_EQ
(
0U
,
s1
.
length
());
EXPECT_TRUE
(
NULL
==
s1
.
c_str
());
EXPECT_TRUE
(
NULL
==
s1
.
c_str
());
// Implicitly constructs from a C-string.
// Implicitly constructs from a C-string.
String
s2
=
"Hi"
;
String
s2
=
"Hi"
;
EXPECT_EQ
(
2U
,
s2
.
length
());
EXPECT_STREQ
(
"Hi"
,
s2
.
c_str
());
EXPECT_STREQ
(
"Hi"
,
s2
.
c_str
());
// Constructs from a C-string and a length.
// Constructs from a C-string and a length.
String
s3
(
"hello"
,
3
);
String
s3
(
"hello"
,
3
);
EXPECT_EQ
(
3U
,
s3
.
length
());
EXPECT_STREQ
(
"hel"
,
s3
.
c_str
());
EXPECT_STREQ
(
"hel"
,
s3
.
c_str
());
// Copy ctor.
// The empty String should be created when String is constructed with
String
s4
=
s3
;
// a NULL pointer and length 0.
EXPECT_STREQ
(
"hel"
,
s4
.
c_str
());
EXPECT_EQ
(
0U
,
String
(
NULL
,
0
).
length
());
EXPECT_FALSE
(
String
(
NULL
,
0
).
c_str
()
==
NULL
);
// Constructs a String that contains '\0'.
String
s4
(
"a
\0
bcd"
,
4
);
EXPECT_EQ
(
4U
,
s4
.
length
());
EXPECT_EQ
(
'a'
,
s4
.
c_str
()[
0
]);
EXPECT_EQ
(
'\0'
,
s4
.
c_str
()[
1
]);
EXPECT_EQ
(
'b'
,
s4
.
c_str
()[
2
]);
EXPECT_EQ
(
'c'
,
s4
.
c_str
()[
3
]);
// Copy ctor where the source is NULL.
const
String
null_str
;
String
s5
=
null_str
;
EXPECT_TRUE
(
s5
.
c_str
()
==
NULL
);
// Copy ctor where the source isn't NULL.
String
s6
=
s3
;
EXPECT_EQ
(
3U
,
s6
.
length
());
EXPECT_STREQ
(
"hel"
,
s6
.
c_str
());
// Copy ctor where the source contains '\0'.
String
s7
=
s4
;
EXPECT_EQ
(
4U
,
s7
.
length
());
EXPECT_EQ
(
'a'
,
s7
.
c_str
()[
0
]);
EXPECT_EQ
(
'\0'
,
s7
.
c_str
()[
1
]);
EXPECT_EQ
(
'b'
,
s7
.
c_str
()[
2
]);
EXPECT_EQ
(
'c'
,
s7
.
c_str
()[
3
]);
}
}
#if GTEST_HAS_STD_STRING
#if GTEST_HAS_STD_STRING
...
@@ -724,17 +760,22 @@ TEST(StringTest, ConvertsFromStdString) {
...
@@ -724,17 +760,22 @@ TEST(StringTest, ConvertsFromStdString) {
// An empty std::string.
// An empty std::string.
const
std
::
string
src1
(
""
);
const
std
::
string
src1
(
""
);
const
String
dest1
=
src1
;
const
String
dest1
=
src1
;
EXPECT_EQ
(
0U
,
dest1
.
length
());
EXPECT_STREQ
(
""
,
dest1
.
c_str
());
EXPECT_STREQ
(
""
,
dest1
.
c_str
());
// A normal std::string.
// A normal std::string.
const
std
::
string
src2
(
"Hi"
);
const
std
::
string
src2
(
"Hi"
);
const
String
dest2
=
src2
;
const
String
dest2
=
src2
;
EXPECT_EQ
(
2U
,
dest2
.
length
());
EXPECT_STREQ
(
"Hi"
,
dest2
.
c_str
());
EXPECT_STREQ
(
"Hi"
,
dest2
.
c_str
());
// An std::string with an embedded NUL character.
// An std::string with an embedded NUL character.
const
char
src3
[]
=
"
Hello
\0
world.
"
;
const
char
src3
[]
=
"
a
\0
b
"
;
const
String
dest3
=
std
::
string
(
src3
,
sizeof
(
src3
));
const
String
dest3
=
std
::
string
(
src3
,
sizeof
(
src3
));
EXPECT_STREQ
(
"Hello"
,
dest3
.
c_str
());
EXPECT_EQ
(
sizeof
(
src3
),
dest3
.
length
());
EXPECT_EQ
(
'a'
,
dest3
.
c_str
()[
0
]);
EXPECT_EQ
(
'\0'
,
dest3
.
c_str
()[
1
]);
EXPECT_EQ
(
'b'
,
dest3
.
c_str
()[
2
]);
}
}
TEST
(
StringTest
,
ConvertsToStdString
)
{
TEST
(
StringTest
,
ConvertsToStdString
)
{
...
@@ -747,6 +788,11 @@ TEST(StringTest, ConvertsToStdString) {
...
@@ -747,6 +788,11 @@ TEST(StringTest, ConvertsToStdString) {
const
String
src2
(
"Hi"
);
const
String
src2
(
"Hi"
);
const
std
::
string
dest2
=
src2
;
const
std
::
string
dest2
=
src2
;
EXPECT_EQ
(
"Hi"
,
dest2
);
EXPECT_EQ
(
"Hi"
,
dest2
);
// A String containing a '\0'.
const
String
src3
(
"x
\0
y"
,
3
);
const
std
::
string
dest3
=
src3
;
EXPECT_EQ
(
std
::
string
(
"x
\0
y"
,
3
),
dest3
);
}
}
#endif // GTEST_HAS_STD_STRING
#endif // GTEST_HAS_STD_STRING
...
@@ -757,17 +803,22 @@ TEST(StringTest, ConvertsFromGlobalString) {
...
@@ -757,17 +803,22 @@ TEST(StringTest, ConvertsFromGlobalString) {
// An empty ::string.
// An empty ::string.
const
::
string
src1
(
""
);
const
::
string
src1
(
""
);
const
String
dest1
=
src1
;
const
String
dest1
=
src1
;
EXPECT_EQ
(
0U
,
dest1
.
length
());
EXPECT_STREQ
(
""
,
dest1
.
c_str
());
EXPECT_STREQ
(
""
,
dest1
.
c_str
());
// A normal ::string.
// A normal ::string.
const
::
string
src2
(
"Hi"
);
const
::
string
src2
(
"Hi"
);
const
String
dest2
=
src2
;
const
String
dest2
=
src2
;
EXPECT_EQ
(
2U
,
dest2
.
length
());
EXPECT_STREQ
(
"Hi"
,
dest2
.
c_str
());
EXPECT_STREQ
(
"Hi"
,
dest2
.
c_str
());
// An ::string with an embedded NUL character.
// An ::string with an embedded NUL character.
const
char
src3
[]
=
"
Hello
\0
world.
"
;
const
char
src3
[]
=
"
x
\0
y
"
;
const
String
dest3
=
::
string
(
src3
,
sizeof
(
src3
));
const
String
dest3
=
::
string
(
src3
,
sizeof
(
src3
));
EXPECT_STREQ
(
"Hello"
,
dest3
.
c_str
());
EXPECT_EQ
(
sizeof
(
src3
),
dest3
.
length
());
EXPECT_EQ
(
'x'
,
dest3
.
c_str
()[
0
]);
EXPECT_EQ
(
'\0'
,
dest3
.
c_str
()[
1
]);
EXPECT_EQ
(
'y'
,
dest3
.
c_str
()[
2
]);
}
}
TEST
(
StringTest
,
ConvertsToGlobalString
)
{
TEST
(
StringTest
,
ConvertsToGlobalString
)
{
...
@@ -780,17 +831,14 @@ TEST(StringTest, ConvertsToGlobalString) {
...
@@ -780,17 +831,14 @@ TEST(StringTest, ConvertsToGlobalString) {
const
String
src2
(
"Hi"
);
const
String
src2
(
"Hi"
);
const
::
string
dest2
=
src2
;
const
::
string
dest2
=
src2
;
EXPECT_EQ
(
"Hi"
,
dest2
);
EXPECT_EQ
(
"Hi"
,
dest2
);
const
String
src3
(
"x
\0
y"
,
3
);
const
::
string
dest3
=
src3
;
EXPECT_EQ
(
::
string
(
"x
\0
y"
,
3
),
dest3
);
}
}
#endif // GTEST_HAS_GLOBAL_STRING
#endif // GTEST_HAS_GLOBAL_STRING
// Tests String::ShowCString().
TEST
(
StringTest
,
ShowCString
)
{
EXPECT_STREQ
(
"(null)"
,
String
::
ShowCString
(
NULL
));
EXPECT_STREQ
(
""
,
String
::
ShowCString
(
""
));
EXPECT_STREQ
(
"foo"
,
String
::
ShowCString
(
"foo"
));
}
// Tests String::ShowCStringQuoted().
// Tests String::ShowCStringQuoted().
TEST
(
StringTest
,
ShowCStringQuoted
)
{
TEST
(
StringTest
,
ShowCStringQuoted
)
{
EXPECT_STREQ
(
"(null)"
,
EXPECT_STREQ
(
"(null)"
,
...
@@ -801,6 +849,53 @@ TEST(StringTest, ShowCStringQuoted) {
...
@@ -801,6 +849,53 @@ TEST(StringTest, ShowCStringQuoted) {
String
::
ShowCStringQuoted
(
"foo"
).
c_str
());
String
::
ShowCStringQuoted
(
"foo"
).
c_str
());
}
}
// Tests String::empty().
TEST
(
StringTest
,
Empty
)
{
EXPECT_TRUE
(
String
(
""
).
empty
());
EXPECT_FALSE
(
String
().
empty
());
EXPECT_FALSE
(
String
(
NULL
).
empty
());
EXPECT_FALSE
(
String
(
"a"
).
empty
());
EXPECT_FALSE
(
String
(
"
\0
"
,
1
).
empty
());
}
// Tests String::Compare().
TEST
(
StringTest
,
Compare
)
{
// NULL vs NULL.
EXPECT_EQ
(
0
,
String
().
Compare
(
String
()));
// NULL vs non-NULL.
EXPECT_EQ
(
-
1
,
String
().
Compare
(
String
(
""
)));
// Non-NULL vs NULL.
EXPECT_EQ
(
1
,
String
(
""
).
Compare
(
String
()));
// The following covers non-NULL vs non-NULL.
// "" vs "".
EXPECT_EQ
(
0
,
String
(
""
).
Compare
(
String
(
""
)));
// "" vs non-"".
EXPECT_EQ
(
-
1
,
String
(
""
).
Compare
(
String
(
"
\0
"
,
1
)));
EXPECT_EQ
(
-
1
,
String
(
""
).
Compare
(
" "
));
// Non-"" vs "".
EXPECT_EQ
(
1
,
String
(
"a"
).
Compare
(
String
(
""
)));
// The following covers non-"" vs non-"".
// Same length and equal.
EXPECT_EQ
(
0
,
String
(
"a"
).
Compare
(
String
(
"a"
)));
// Same length and different.
EXPECT_EQ
(
-
1
,
String
(
"a
\0
b"
,
3
).
Compare
(
String
(
"a
\0
c"
,
3
)));
EXPECT_EQ
(
1
,
String
(
"b"
).
Compare
(
String
(
"a"
)));
// Different lengths.
EXPECT_EQ
(
-
1
,
String
(
"a"
).
Compare
(
String
(
"ab"
)));
EXPECT_EQ
(
-
1
,
String
(
"a"
).
Compare
(
String
(
"a
\0
"
,
2
)));
EXPECT_EQ
(
1
,
String
(
"abc"
).
Compare
(
String
(
"aacd"
)));
}
// Tests String::operator==().
// Tests String::operator==().
TEST
(
StringTest
,
Equals
)
{
TEST
(
StringTest
,
Equals
)
{
const
String
null
(
NULL
);
const
String
null
(
NULL
);
...
@@ -818,6 +913,9 @@ TEST(StringTest, Equals) {
...
@@ -818,6 +913,9 @@ TEST(StringTest, Equals) {
EXPECT_FALSE
(
foo
==
""
);
// NOLINT
EXPECT_FALSE
(
foo
==
""
);
// NOLINT
EXPECT_FALSE
(
foo
==
"bar"
);
// NOLINT
EXPECT_FALSE
(
foo
==
"bar"
);
// NOLINT
EXPECT_TRUE
(
foo
==
"foo"
);
// NOLINT
EXPECT_TRUE
(
foo
==
"foo"
);
// NOLINT
const
String
bar
(
"x
\0
y"
,
3
);
EXPECT_FALSE
(
bar
==
"x"
);
}
}
// Tests String::operator!=().
// Tests String::operator!=().
...
@@ -837,6 +935,17 @@ TEST(StringTest, NotEquals) {
...
@@ -837,6 +935,17 @@ TEST(StringTest, NotEquals) {
EXPECT_TRUE
(
foo
!=
""
);
// NOLINT
EXPECT_TRUE
(
foo
!=
""
);
// NOLINT
EXPECT_TRUE
(
foo
!=
"bar"
);
// NOLINT
EXPECT_TRUE
(
foo
!=
"bar"
);
// NOLINT
EXPECT_FALSE
(
foo
!=
"foo"
);
// NOLINT
EXPECT_FALSE
(
foo
!=
"foo"
);
// NOLINT
const
String
bar
(
"x
\0
y"
,
3
);
EXPECT_TRUE
(
bar
!=
"x"
);
}
// Tests String::length().
TEST
(
StringTest
,
Length
)
{
EXPECT_EQ
(
0U
,
String
().
length
());
EXPECT_EQ
(
0U
,
String
(
""
).
length
());
EXPECT_EQ
(
2U
,
String
(
"ab"
).
length
());
EXPECT_EQ
(
3U
,
String
(
"a
\0
b"
,
3
).
length
());
}
}
// Tests String::EndsWith().
// Tests String::EndsWith().
...
@@ -900,9 +1009,17 @@ TEST(StringTest, CanBeAssignedEmpty) {
...
@@ -900,9 +1009,17 @@ TEST(StringTest, CanBeAssignedEmpty) {
TEST
(
StringTest
,
CanBeAssignedNonEmpty
)
{
TEST
(
StringTest
,
CanBeAssignedNonEmpty
)
{
const
String
src
(
"hello"
);
const
String
src
(
"hello"
);
String
dest
;
String
dest
;
dest
=
src
;
dest
=
src
;
EXPECT_EQ
(
5U
,
dest
.
length
());
EXPECT_STREQ
(
"hello"
,
dest
.
c_str
());
EXPECT_STREQ
(
"hello"
,
dest
.
c_str
());
const
String
src2
(
"x
\0
y"
,
3
);
String
dest2
;
dest2
=
src2
;
EXPECT_EQ
(
3U
,
dest2
.
length
());
EXPECT_EQ
(
'x'
,
dest2
.
c_str
()[
0
]);
EXPECT_EQ
(
'\0'
,
dest2
.
c_str
()[
1
]);
EXPECT_EQ
(
'y'
,
dest2
.
c_str
()[
2
]);
}
}
// Tests that a String can be assigned to itself.
// Tests that a String can be assigned to itself.
...
@@ -913,6 +1030,13 @@ TEST(StringTest, CanBeAssignedSelf) {
...
@@ -913,6 +1030,13 @@ TEST(StringTest, CanBeAssignedSelf) {
EXPECT_STREQ
(
"hello"
,
dest
.
c_str
());
EXPECT_STREQ
(
"hello"
,
dest
.
c_str
());
}
}
// Tests streaming a String.
TEST
(
StringTest
,
Streams
)
{
EXPECT_EQ
(
StreamableToString
(
String
()),
"(null)"
);
EXPECT_EQ
(
StreamableToString
(
String
(
""
)),
""
);
EXPECT_EQ
(
StreamableToString
(
String
(
"a
\0
b"
,
3
)),
"a
\\
0b"
);
}
#if GTEST_OS_WINDOWS
#if GTEST_OS_WINDOWS
// Tests String::ShowWideCString().
// Tests String::ShowWideCString().
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment