gmock-internal-utils.cc revision 13481
16242Sgblack@eecs.umich.edu// Copyright 2007, Google Inc.
210856SCurtis.Dunham@arm.com// All rights reserved.
37093Sgblack@eecs.umich.edu//
47093Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
57093Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
67093Sgblack@eecs.umich.edu// met:
77093Sgblack@eecs.umich.edu//
87093Sgblack@eecs.umich.edu//     * Redistributions of source code must retain the above copyright
97093Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer.
107093Sgblack@eecs.umich.edu//     * Redistributions in binary form must reproduce the above
117093Sgblack@eecs.umich.edu// copyright notice, this list of conditions and the following disclaimer
127093Sgblack@eecs.umich.edu// in the documentation and/or other materials provided with the
137093Sgblack@eecs.umich.edu// distribution.
146242Sgblack@eecs.umich.edu//     * Neither the name of Google Inc. nor the names of its
156242Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
166242Sgblack@eecs.umich.edu// this software without specific prior written permission.
176242Sgblack@eecs.umich.edu//
186242Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
196242Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
206242Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
216242Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
226242Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
236242Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
246242Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
256242Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
266242Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
276242Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
286242Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
296242Sgblack@eecs.umich.edu//
306242Sgblack@eecs.umich.edu// Author: wan@google.com (Zhanyong Wan)
316242Sgblack@eecs.umich.edu
326242Sgblack@eecs.umich.edu// Google Mock - a framework for writing C++ mock classes.
336242Sgblack@eecs.umich.edu//
346242Sgblack@eecs.umich.edu// This file defines some utilities useful for implementing Google
356242Sgblack@eecs.umich.edu// Mock.  They are subject to change without notice, so please DO NOT
366242Sgblack@eecs.umich.edu// USE THEM IN USER CODE.
376242Sgblack@eecs.umich.edu
386242Sgblack@eecs.umich.edu#include "gmock/internal/gmock-internal-utils.h"
396242Sgblack@eecs.umich.edu
406242Sgblack@eecs.umich.edu#include <ctype.h>
4110037SARM gem5 Developers#include <ostream>  // NOLINT
426242Sgblack@eecs.umich.edu#include <string>
436242Sgblack@eecs.umich.edu#include "gmock/gmock.h"
446242Sgblack@eecs.umich.edu#include "gmock/internal/gmock-port.h"
456242Sgblack@eecs.umich.edu#include "gtest/gtest.h"
4610037SARM gem5 Developers
4710037SARM gem5 Developersnamespace testing {
486242Sgblack@eecs.umich.edunamespace internal {
499256SAndreas.Sandberg@arm.com
506242Sgblack@eecs.umich.edu// Converts an identifier name to a space-separated list of lower-case
5110037SARM gem5 Developers// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
5210037SARM gem5 Developers// treated as one word.  For example, both "FooBar123" and
5310037SARM gem5 Developers// "foo_bar_123" are converted to "foo bar 123".
546242Sgblack@eecs.umich.eduGTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) {
556242Sgblack@eecs.umich.edu  string result;
566242Sgblack@eecs.umich.edu  char prev_char = '\0';
5710037SARM gem5 Developers  for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
5810037SARM gem5 Developers    // We don't care about the current locale as the input is
5910037SARM gem5 Developers    // guaranteed to be a valid C++ identifier name.
6010037SARM gem5 Developers    const bool starts_new_word = IsUpper(*p) ||
6110037SARM gem5 Developers        (!IsAlpha(prev_char) && IsLower(*p)) ||
6210037SARM gem5 Developers        (!IsDigit(prev_char) && IsDigit(*p));
6310037SARM gem5 Developers
6410037SARM gem5 Developers    if (IsAlNum(*p)) {
6510037SARM gem5 Developers      if (starts_new_word && result != "")
6610037SARM gem5 Developers        result += ' ';
6710037SARM gem5 Developers      result += ToLower(*p);
6810037SARM gem5 Developers    }
6910037SARM gem5 Developers  }
7010037SARM gem5 Developers  return result;
7110037SARM gem5 Developers}
727259Sgblack@eecs.umich.edu
7310037SARM gem5 Developers// This class reports Google Mock failures as Google Test failures.  A
7410037SARM gem5 Developers// user can define another class in a similar fashion if he intends to
7510037SARM gem5 Developers// use Google Mock with a testing framework other than Google Test.
7610037SARM gem5 Developersclass GoogleTestFailureReporter : public FailureReporterInterface {
7710037SARM gem5 Developers public:
7810037SARM gem5 Developers  virtual void ReportFailure(FailureType type, const char* file, int line,
7910037SARM gem5 Developers                             const string& message) {
8010037SARM gem5 Developers    AssertHelper(type == kFatal ?
8110037SARM gem5 Developers                 TestPartResult::kFatalFailure :
8210037SARM gem5 Developers                 TestPartResult::kNonFatalFailure,
8310037SARM gem5 Developers                 file,
8410037SARM gem5 Developers                 line,
8510037SARM gem5 Developers                 message.c_str()) = Message();
8610037SARM gem5 Developers    if (type == kFatal) {
8710037SARM gem5 Developers      posix::Abort();
8810037SARM gem5 Developers    }
898868SMatt.Horsnell@arm.com  }
9010037SARM gem5 Developers};
9110037SARM gem5 Developers
9210037SARM gem5 Developers// Returns the global failure reporter.  Will create a
9310037SARM gem5 Developers// GoogleTestFailureReporter and return it the first time called.
9410037SARM gem5 DevelopersGTEST_API_ FailureReporterInterface* GetFailureReporter() {
9510037SARM gem5 Developers  // Points to the global failure reporter used by Google Mock.  gcc
9610037SARM gem5 Developers  // guarantees that the following use of failure_reporter is
9710037SARM gem5 Developers  // thread-safe.  We may need to add additional synchronization to
9810037SARM gem5 Developers  // protect failure_reporter if we port Google Mock to other
9910037SARM gem5 Developers  // compilers.
10010037SARM gem5 Developers  static FailureReporterInterface* const failure_reporter =
10110037SARM gem5 Developers      new GoogleTestFailureReporter();
10210037SARM gem5 Developers  return failure_reporter;
10310037SARM gem5 Developers}
10410037SARM gem5 Developers
10510037SARM gem5 Developers// Protects global resources (stdout in particular) used by Log().
10610037SARM gem5 Developersstatic GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
10710037SARM gem5 Developers
10810037SARM gem5 Developers// Returns true iff a log with the given severity is visible according
10910037SARM gem5 Developers// to the --gmock_verbose flag.
11010037SARM gem5 DevelopersGTEST_API_ bool LogIsVisible(LogSeverity severity) {
11110037SARM gem5 Developers  if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
11210037SARM gem5 Developers    // Always show the log if --gmock_verbose=info.
11310037SARM gem5 Developers    return true;
11410037SARM gem5 Developers  } else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
11510037SARM gem5 Developers    // Always hide it if --gmock_verbose=error.
11610037SARM gem5 Developers    return false;
11710037SARM gem5 Developers  } else {
11810037SARM gem5 Developers    // If --gmock_verbose is neither "info" nor "error", we treat it
11910037SARM gem5 Developers    // as "warning" (its default value).
12010037SARM gem5 Developers    return severity == kWarning;
12110037SARM gem5 Developers  }
12210037SARM gem5 Developers}
12310037SARM gem5 Developers
12410037SARM gem5 Developers// Prints the given message to stdout iff 'severity' >= the level
12510037SARM gem5 Developers// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
12610037SARM gem5 Developers// 0, also prints the stack trace excluding the top
12710037SARM gem5 Developers// stack_frames_to_skip frames.  In opt mode, any positive
12810037SARM gem5 Developers// stack_frames_to_skip is treated as 0, since we don't know which
12910037SARM gem5 Developers// function calls will be inlined by the compiler and need to be
13010037SARM gem5 Developers// conservative.
13110037SARM gem5 DevelopersGTEST_API_ void Log(LogSeverity severity,
13210037SARM gem5 Developers                    const string& message,
13310037SARM gem5 Developers                    int stack_frames_to_skip) {
13410037SARM gem5 Developers  if (!LogIsVisible(severity))
13510037SARM gem5 Developers    return;
13610037SARM gem5 Developers
13710037SARM gem5 Developers  // Ensures that logs from different threads don't interleave.
13810037SARM gem5 Developers  MutexLock l(&g_log_mutex);
13910037SARM gem5 Developers
14010037SARM gem5 Developers  // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
1417351Sgblack@eecs.umich.edu  // macro.
14210037SARM gem5 Developers
14310037SARM gem5 Developers  if (severity == kWarning) {
14410037SARM gem5 Developers    // Prints a GMOCK WARNING marker to make the warnings easily searchable.
14510037SARM gem5 Developers    std::cout << "\nGMOCK WARNING:";
14610037SARM gem5 Developers  }
14710037SARM gem5 Developers  // Pre-pends a new-line to message if it doesn't start with one.
14810037SARM gem5 Developers  if (message.empty() || message[0] != '\n') {
14910037SARM gem5 Developers    std::cout << "\n";
15010037SARM gem5 Developers  }
15110037SARM gem5 Developers  std::cout << message;
15210037SARM gem5 Developers  if (stack_frames_to_skip >= 0) {
15310037SARM gem5 Developers#ifdef NDEBUG
15410037SARM gem5 Developers    // In opt mode, we have to be conservative and skip no stack frame.
15510037SARM gem5 Developers    const int actual_to_skip = 0;
15610037SARM gem5 Developers#else
15710037SARM gem5 Developers    // In dbg mode, we can do what the caller tell us to do (plus one
15810037SARM gem5 Developers    // for skipping this function's stack frame).
15910037SARM gem5 Developers    const int actual_to_skip = stack_frames_to_skip + 1;
16010037SARM gem5 Developers#endif  // NDEBUG
16110037SARM gem5 Developers
16210037SARM gem5 Developers    // Appends a new-line to message if it doesn't end with one.
16310037SARM gem5 Developers    if (!message.empty() && *message.rbegin() != '\n') {
16410037SARM gem5 Developers      std::cout << "\n";
16510037SARM gem5 Developers    }
16610037SARM gem5 Developers    std::cout << "Stack trace:\n"
16710037SARM gem5 Developers         << ::testing::internal::GetCurrentOsStackTraceExceptTop(
16810037SARM gem5 Developers             ::testing::UnitTest::GetInstance(), actual_to_skip);
16910037SARM gem5 Developers  }
17010037SARM gem5 Developers  std::cout << ::std::flush;
17110037SARM gem5 Developers}
17210037SARM gem5 Developers
17310037SARM gem5 Developers}  // namespace internal
17410037SARM gem5 Developers}  // namespace testing
17510037SARM gem5 Developers