Enables String to contain NUL (by Zhanyong Wan); Adds scons scripts (by Vlad Losev).
This commit is contained in:
		@@ -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 {
 | 
				
			|||||||
 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 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // 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 {
 | 
				
			|||||||
  // 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 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // 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 string.  A NULL
 | 
					  // Returns true iff this String is less than the given String.  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 {
 | 
				
			|||||||
  // 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'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								scons/SConstruct
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								scons/SConstruct
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					# -*- 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()
 | 
				
			||||||
							
								
								
									
										267
									
								
								scons/SConstruct.common
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								scons/SConstruct.common
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,267 @@
 | 
				
			|||||||
 | 
					# -*- 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')
 | 
				
			||||||
@@ -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_.GetLength() - 4));
 | 
					    return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -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_.GetLength() == 3 && IsAbsolutePath();
 | 
					  return pathname_.length() == 3 && IsAbsolutePath();
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  return pathname_ == kPathSeparatorString;
 | 
					  return pathname_ == kPathSeparatorString;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -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_.GetLength() >= 3 &&
 | 
					  return pathname_.length() >= 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 {
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (pathname_.GetLength() == 0 || this->DirectoryExists()) {
 | 
					  if (pathname_.length() == 0 || this->DirectoryExists()) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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_.GetLength() - 1))
 | 
					      ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
 | 
				
			||||||
      : *this;
 | 
					      : *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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_.GetLength() + 1];
 | 
					  char* const dest = new char[pathname_.length() + 1];
 | 
				
			||||||
  char* dest_ptr = dest;
 | 
					  char* dest_ptr = dest;
 | 
				
			||||||
  memset(dest_ptr, 0, pathname_.GetLength() + 1);
 | 
					  memset(dest_ptr, 0, pathname_.length() + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (*src != '\0') {
 | 
					  while (*src != '\0') {
 | 
				
			||||||
    *dest_ptr++ = *src;
 | 
					    *dest_ptr++ = *src;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 (int i = 0; i != full_flag.GetLength(); i++) {
 | 
					  for (size_t i = 0; i != full_flag.length(); i++) {
 | 
				
			||||||
    env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
 | 
					    env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										83
									
								
								src/gtest.cc
									
									
									
									
									
								
							
							
						
						
									
										83
									
								
								src/gtest.cc
									
									
									
									
									
								
							@@ -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) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 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 length,
 | 
				
			||||||
                                     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 != length; ) {  // 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>(length - i));
 | 
				
			||||||
      while (i != len && wstr[i] != L'\0')
 | 
					      while (i != length && wstr[i] != L'\0')
 | 
				
			||||||
        i++;
 | 
					        i++;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      *msg << '\0';
 | 
					      *msg << '\0';
 | 
				
			||||||
@@ -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 {
 | 
				
			|||||||
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 {
 | 
				
			|||||||
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, ...) {
 | 
				
			|||||||
#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() {
 | 
				
			|||||||
  // 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).GetLength() > 0;
 | 
					      internal::GTEST_FLAG(internal_run_death_test).length() > 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,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // 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.GetLength();
 | 
					  const size_t flag_len = flag_str.length();
 | 
				
			||||||
  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.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -292,7 +292,7 @@ TEST_F(TestForDeathTest, SingleStatement) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DieWithEmbeddedNul() {
 | 
					void DieWithEmbeddedNul() {
 | 
				
			||||||
  fprintf(stderr, "Hello%cworld.\n", '\0');
 | 
					  fprintf(stderr, "Hello%cmy null world.\n", '\0');
 | 
				
			||||||
  fflush(stderr);
 | 
					  fflush(stderr);
 | 
				
			||||||
  _exit(1);
 | 
					  _exit(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -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 world");
 | 
				
			||||||
  ASSERT_DEATH(DieWithEmbeddedNul(), "w.*ld");
 | 
					  ASSERT_DEATH(DieWithEmbeddedNul(), "my null world");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif  // GTEST_USES_PCRE
 | 
					#endif  // GTEST_USES_PCRE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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\0bcd", 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) {
 | 
				
			|||||||
  // 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\0world.";
 | 
					  const char src3[] = "a\0b";
 | 
				
			||||||
  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) {
 | 
				
			|||||||
  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\0y", 3);
 | 
				
			||||||
 | 
					  const std::string dest3 = src3;
 | 
				
			||||||
 | 
					  EXPECT_EQ(std::string("x\0y", 3), dest3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif  // GTEST_HAS_STD_STRING
 | 
					#endif  // GTEST_HAS_STD_STRING
 | 
				
			||||||
@@ -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\0world.";
 | 
					  const char src3[] = "x\0y";
 | 
				
			||||||
  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) {
 | 
				
			|||||||
  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\0y", 3);
 | 
				
			||||||
 | 
					  const ::string dest3 = src3;
 | 
				
			||||||
 | 
					  EXPECT_EQ(::string("x\0y", 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) {
 | 
				
			|||||||
               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\0b", 3).Compare(String("a\0c", 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) {
 | 
				
			|||||||
  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\0y", 3);
 | 
				
			||||||
 | 
					  EXPECT_FALSE(bar == "x");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Tests String::operator!=().
 | 
					// Tests String::operator!=().
 | 
				
			||||||
@@ -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\0y", 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\0b", 3).length());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Tests String::EndsWith().
 | 
					// Tests String::EndsWith().
 | 
				
			||||||
@@ -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\0y", 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) {
 | 
				
			|||||||
  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\0b", 3)), "a\\0b");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if GTEST_OS_WINDOWS
 | 
					#if GTEST_OS_WINDOWS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Tests String::ShowWideCString().
 | 
					// Tests String::ShowWideCString().
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user