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