Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
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 @@
namespace
testing
{
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.
//
// We cannot use std::string as Microsoft's STL implementation in
...
...
@@ -80,19 +96,6 @@ class String {
public:
// 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;
// otherwise returns "(null)". For example, "\"Hello\"" is returned
// for input "Hello".
...
...
@@ -199,27 +202,36 @@ class String {
// C'tors
// The default c'tor constructs a NULL string.
String
()
:
c_str_
(
NULL
)
{}
// The default c'tor constructs a NULL string, which is represented
// by data_ being NULL.
String
()
:
data_
(
NULL
)
{}
// Constructs a String by cloning a 0-terminated C string.
String
(
const
char
*
c_str
)
:
c_str_
(
NULL
)
{
// NOLINT
*
this
=
c_str
;
String
(
const
char
*
c_str
)
{
// NOLINT
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
// buffer. E.g. String("hello", 3) will create the string "hel".
String
(
const
char
*
buffer
,
size_t
len
);
// buffer. E.g. String("hello", 3) creates the string "hel",
// 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
// String objects do not share content.
String
(
const
String
&
str
)
:
c_str_
(
NULL
)
{
*
this
=
str
;
}
String
(
const
String
&
str
)
:
data_
(
NULL
)
{
*
this
=
str
;
}
// D'tor. String is intended to be a final class, so the d'tor
// 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
// ::string, and vice versa. Converting a String containing a NULL
...
...
@@ -228,21 +240,23 @@ class String {
// character to a String will result in the prefix up to the first
// NUL character.
#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
#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
// Returns true iff this is an empty string (i.e. "").
bool
empty
()
const
{
return
(
c_str_
!=
NULL
)
&&
(
*
c_str_
==
'\0'
);
}
bool
empty
()
const
{
return
(
c_str
()
!=
NULL
)
&&
(
length
()
==
0
);
}
// Compares this with another String.
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
...
...
@@ -251,19 +265,15 @@ class String {
// Returns true iff this String equals the given C string. A NULL
// string and a non-NULL string are considered not equal.
bool
operator
==
(
const
char
*
c_str
)
const
{
return
CStringEquals
(
c_str_
,
c_str
);
}
bool
operator
==
(
const
char
*
c_str
)
const
{
return
Compare
(
c_str
)
==
0
;
}
// Returns true iff this String is less than the given
C s
tring. A
NULL
// string is considered less than "".
// Returns true iff this String is less than the given
S
tring. A
//
NULL
string is considered less than "".
bool
operator
<
(
const
String
&
rhs
)
const
{
return
Compare
(
rhs
)
<
0
;
}
// Returns true iff this String doesn't equal the given C string. A NULL
// string and a non-NULL string are considered not equal.
bool
operator
!=
(
const
char
*
c_str
)
const
{
return
!
CStringEquals
(
c_str_
,
c_str
);
}
bool
operator
!=
(
const
char
*
c_str
)
const
{
return
!
(
*
this
==
c_str
);
}
// Returns true iff this String ends with the given suffix. *Any*
// String is considered to end with a NULL or empty suffix.
...
...
@@ -273,45 +283,66 @@ class String {
// case. Any String is considered to end with a NULL or empty suffix.
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.
int
GetLength
()
const
{
return
c_str_
?
static_cast
<
int
>
(
strlen
(
c_str_
))
:
-
1
;
}
size_t
length
()
const
{
return
(
data_
==
NULL
)
?
0
:
data_
->
length_
;
}
// Gets the 0-terminated C string this String object represents.
// The String object still owns the string. Therefore the caller
// should NOT delete the return value.
const
char
*
c_str
()
const
{
return
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
);
const
char
*
c_str
()
const
{
return
(
data_
==
NULL
)
?
NULL
:
data_
->
c_str_
;
}
// 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.
const
String
&
operator
=
(
const
String
&
rhs
)
{
*
this
=
rhs
.
c_str_
;
const
String
&
operator
=
(
const
String
&
rhs
)
{
if
(
this
!=
&
rhs
)
{
delete
data_
;
data_
=
NULL
;
if
(
rhs
.
data_
!=
NULL
)
{
ConstructNonNull
(
rhs
.
data_
->
c_str_
,
rhs
.
data_
->
length_
);
}
}
return
*
this
;
}
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.
inline
::
std
::
ostream
&
operator
<<
(
::
std
::
ostream
&
os
,
const
String
&
str
)
{
// We call String::ShowCString() to convert NULL to "(null)".
// Otherwise we'll get an access violation on Windows.
return
os
<<
String
::
ShowCString
(
str
.
c_str
());
// Points to the representation of the String. A NULL String is
// represented by data_ == NULL.
StringData
*
data_
;
};
// class String
// 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'
...
...
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() {
FilePath
FilePath
::
RemoveExtension
(
const
char
*
extension
)
const
{
String
dot_extension
(
String
::
Format
(
".%s"
,
extension
));
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
;
}
...
...
@@ -217,7 +217,7 @@ bool FilePath::IsRootDirectory() const {
// TODO(wan@google.com): on Windows a network share like
// \\server\share can be a root directory, although it cannot be the
// current directory. Handle this properly.
return
pathname_
.
GetL
ength
()
==
3
&&
IsAbsolutePath
();
return
pathname_
.
l
ength
()
==
3
&&
IsAbsolutePath
();
#else
return
pathname_
==
kPathSeparatorString
;
#endif
...
...
@@ -227,7 +227,7 @@ bool FilePath::IsRootDirectory() const {
bool
FilePath
::
IsAbsolutePath
()
const
{
const
char
*
const
name
=
pathname_
.
c_str
();
#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
[
1
]
==
':'
&&
...
...
@@ -271,7 +271,7 @@ bool FilePath::CreateDirectoriesRecursively() const {
return
false
;
}
if
(
pathname_
.
GetL
ength
()
==
0
||
this
->
DirectoryExists
())
{
if
(
pathname_
.
l
ength
()
==
0
||
this
->
DirectoryExists
())
{
return
true
;
}
...
...
@@ -307,7 +307,7 @@ bool FilePath::CreateFolder() const {
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath
FilePath
::
RemoveTrailingPathSeparator
()
const
{
return
pathname_
.
EndsWith
(
kPathSeparatorString
)
?
FilePath
(
String
(
pathname_
.
c_str
(),
pathname_
.
GetL
ength
()
-
1
))
?
FilePath
(
String
(
pathname_
.
c_str
(),
pathname_
.
l
ength
()
-
1
))
:
*
this
;
}
...
...
@@ -320,9 +320,9 @@ void FilePath::Normalize() {
return
;
}
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
;
memset
(
dest_ptr
,
0
,
pathname_
.
GetL
ength
()
+
1
);
memset
(
dest_ptr
,
0
,
pathname_
.
l
ength
()
+
1
);
while
(
*
src
!=
'\0'
)
{
*
dest_ptr
++
=
*
src
;
...
...
src/gtest-port.cc
View file @
56a2e686
...
...
@@ -585,7 +585,7 @@ static String FlagToEnvVar(const char* flag) {
(
Message
()
<<
GTEST_FLAG_PREFIX_
<<
flag
).
GetString
();
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
]));
}
...
...
src/gtest.cc
View file @
56a2e686
...
...
@@ -445,7 +445,7 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
positive
=
GTEST_FLAG
(
filter
).
c_str
();
// Whole string is a positive filter
negative
=
String
(
""
);
}
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
if
(
positive
.
empty
())
{
// Treat '-test1' as the same as '*-test1'
...
...
@@ -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
// 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
)
{
// TODO(wan): consider allowing a testing::String object to
// contain '\0'. This will make it behave more like std::string,
// and will allow ToUtf8String() to return the correct encoding
// for '\0' s.t. we can get rid of the conditional here (and in
// 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'
)
{
*
msg
<<
WideStringToUtf8
(
wstr
+
i
,
static_cast
<
int
>
(
len
-
i
));
while
(
i
!=
len
&&
wstr
[
i
]
!=
L'\0'
)
*
msg
<<
WideStringToUtf8
(
wstr
+
i
,
static_cast
<
int
>
(
len
gth
-
i
));
while
(
i
!=
len
gth
&&
wstr
[
i
]
!=
L'\0'
)
i
++
;
}
else
{
*
msg
<<
'\0'
;
...
...
@@ -1679,24 +1679,30 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
#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.
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
// if this is greater than rhs.
int
String
::
Compare
(
const
String
&
rhs
)
const
{
if
(
c_str_
==
NULL
)
{
return
rhs
.
c_str_
==
NULL
?
0
:
-
1
;
// NULL < anything except NULL
const
char
*
const
lhs_c_str
=
c_str
();
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*
...
...
@@ -1704,12 +1710,12 @@ int String::Compare(const String & rhs) const {
bool
String
::
EndsWith
(
const
char
*
suffix
)
const
{
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
);
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.
...
...
@@ -1717,37 +1723,12 @@ bool String::EndsWith(const char* suffix) const {
bool
String
::
EndsWithCaseInsensitive
(
const
char
*
suffix
)
const
{
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
);
return
(
this_len
>=
suffix_len
)
&&
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
;
CaseInsensitiveCStringEquals
(
c_str
()
+
this_len
-
suffix_len
,
suffix
);
}
// Formats a list of arguments to a String, using the same format
...
...
@@ -1778,7 +1759,7 @@ String String::Format(const char * format, ...) {
#endif // _MSC_VER
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
...
...
@@ -3491,7 +3472,7 @@ int UnitTest::Run() {
// Catch SEH-style exceptions.
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
// tests or this is executing in the context of death test child
...
...
@@ -4161,7 +4142,7 @@ const char* ParseFlagValue(const char* str,
// The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
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
;
// Skips the flag name.
...
...
test/gtest-death-test_test.cc
View file @
56a2e686
...
...
@@ -292,7 +292,7 @@ TEST_F(TestForDeathTest, SingleStatement) {
}
void
DieWithEmbeddedNul
()
{
fprintf
(
stderr
,
"Hello%cworld.
\n
"
,
'\0'
);
fprintf
(
stderr
,
"Hello%c
my null
world.
\n
"
,
'\0'
);
fflush
(
stderr
);
_exit
(
1
);
}
...
...
@@ -303,8 +303,8 @@ void DieWithEmbeddedNul() {
TEST_F
(
TestForDeathTest
,
EmbeddedNulInMessage
)
{
// TODO(wan@google.com): <regex.h> doesn't support matching strings
// with embedded NUL characters - find a way to workaround it.
EXPECT_DEATH
(
DieWithEmbeddedNul
(),
"
w.*
ld"
);
ASSERT_DEATH
(
DieWithEmbeddedNul
(),
"
w.*
ld"
);
EXPECT_DEATH
(
DieWithEmbeddedNul
(),
"
my null wor
ld"
);
ASSERT_DEATH
(
DieWithEmbeddedNul
(),
"
my null wor
ld"
);
}
#endif // GTEST_USES_PCRE
...
...
test/gtest_unittest.cc
View file @
56a2e686
...
...
@@ -697,25 +697,61 @@ TEST(ListDeathTest, GetElement) {
// 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.
TEST
(
StringTest
,
Constructors
)
{
// Default ctor.
String
s1
;
// We aren't using EXPECT_EQ(NULL, s1.c_str()) because comparing
// pointers with NULL isn't supported on all platforms.
EXPECT_EQ
(
0U
,
s1
.
length
());
EXPECT_TRUE
(
NULL
==
s1
.
c_str
());
// Implicitly constructs from a C-string.
String
s2
=
"Hi"
;
EXPECT_EQ
(
2U
,
s2
.
length
());
EXPECT_STREQ
(
"Hi"
,
s2
.
c_str
());
// Constructs from a C-string and a length.
String
s3
(
"hello"
,
3
);
EXPECT_EQ
(
3U
,
s3
.
length
());
EXPECT_STREQ
(
"hel"
,
s3
.
c_str
());
// Copy ctor.
String
s4
=
s3
;
EXPECT_STREQ
(
"hel"
,
s4
.
c_str
());
// The empty String should be created when String is constructed with
// a NULL pointer and length 0.
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
...
...
@@ -724,17 +760,22 @@ TEST(StringTest, ConvertsFromStdString) {
// An empty std::string.
const
std
::
string
src1
(
""
);
const
String
dest1
=
src1
;
EXPECT_EQ
(
0U
,
dest1
.
length
());
EXPECT_STREQ
(
""
,
dest1
.
c_str
());
// A normal std::string.
const
std
::
string
src2
(
"Hi"
);
const
String
dest2
=
src2
;
EXPECT_EQ
(
2U
,
dest2
.
length
());
EXPECT_STREQ
(
"Hi"
,
dest2
.
c_str
());
// 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
));
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
)
{
...
...
@@ -747,6 +788,11 @@ TEST(StringTest, ConvertsToStdString) {
const
String
src2
(
"Hi"
);
const
std
::
string
dest2
=
src2
;
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
...
...
@@ -757,17 +803,22 @@ TEST(StringTest, ConvertsFromGlobalString) {
// An empty ::string.
const
::
string
src1
(
""
);
const
String
dest1
=
src1
;
EXPECT_EQ
(
0U
,
dest1
.
length
());
EXPECT_STREQ
(
""
,
dest1
.
c_str
());
// A normal ::string.
const
::
string
src2
(
"Hi"
);
const
String
dest2
=
src2
;
EXPECT_EQ
(
2U
,
dest2
.
length
());
EXPECT_STREQ
(
"Hi"
,
dest2
.
c_str
());
// 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
));
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
)
{
...
...
@@ -780,17 +831,14 @@ TEST(StringTest, ConvertsToGlobalString) {
const
String
src2
(
"Hi"
);
const
::
string
dest2
=
src2
;
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
// 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().
TEST
(
StringTest
,
ShowCStringQuoted
)
{
EXPECT_STREQ
(
"(null)"
,
...
...
@@ -801,6 +849,53 @@ TEST(StringTest, ShowCStringQuoted) {
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==().
TEST
(
StringTest
,
Equals
)
{
const
String
null
(
NULL
);
...
...
@@ -818,6 +913,9 @@ TEST(StringTest, Equals) {
EXPECT_FALSE
(
foo
==
""
);
// NOLINT
EXPECT_FALSE
(
foo
==
"bar"
);
// NOLINT
EXPECT_TRUE
(
foo
==
"foo"
);
// NOLINT
const
String
bar
(
"x
\0
y"
,
3
);
EXPECT_FALSE
(
bar
==
"x"
);
}
// Tests String::operator!=().
...
...
@@ -837,6 +935,17 @@ TEST(StringTest, NotEquals) {
EXPECT_TRUE
(
foo
!=
""
);
// NOLINT
EXPECT_TRUE
(
foo
!=
"bar"
);
// 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().
...
...
@@ -900,9 +1009,17 @@ TEST(StringTest, CanBeAssignedEmpty) {
TEST
(
StringTest
,
CanBeAssignedNonEmpty
)
{
const
String
src
(
"hello"
);
String
dest
;
dest
=
src
;
EXPECT_EQ
(
5U
,
dest
.
length
());
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.
...
...
@@ -913,6 +1030,13 @@ TEST(StringTest, CanBeAssignedSelf) {
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
// 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