brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.2 KiB · 5c2ce0d Raw
258 lines · plain
1// Copyright 2007, Google Inc.2// All rights reserved.3//4// Redistribution and use in source and binary forms, with or without5// modification, are permitted provided that the following conditions are6// met:7//8//     * Redistributions of source code must retain the above copyright9// notice, this list of conditions and the following disclaimer.10//     * Redistributions in binary form must reproduce the above11// copyright notice, this list of conditions and the following disclaimer12// in the documentation and/or other materials provided with the13// distribution.14//     * Neither the name of Google Inc. nor the names of its15// contributors may be used to endorse or promote products derived from16// this software without specific prior written permission.17//18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29 30// Google Mock - a framework for writing C++ mock classes.31//32// This file defines some utilities useful for implementing Google33// Mock.  They are subject to change without notice, so please DO NOT34// USE THEM IN USER CODE.35 36#include "gmock/internal/gmock-internal-utils.h"37 38#include <ctype.h>39 40#include <array>41#include <cctype>42#include <cstdint>43#include <cstring>44#include <iostream>45#include <ostream>  // NOLINT46#include <string>47#include <vector>48 49#include "gmock/gmock.h"50#include "gmock/internal/gmock-port.h"51#include "gtest/gtest.h"52 53namespace testing {54namespace internal {55 56// Joins a vector of strings as if they are fields of a tuple; returns57// the joined string.58GTEST_API_ std::string JoinAsKeyValueTuple(59    const std::vector<const char*>& names, const Strings& values) {60  GTEST_CHECK_(names.size() == values.size());61  if (values.empty()) {62    return "";63  }64  const auto build_one = [&](const size_t i) {65    return std::string(names[i]) + ": " + values[i];66  };67  std::string result = "(" + build_one(0);68  for (size_t i = 1; i < values.size(); i++) {69    result += ", ";70    result += build_one(i);71  }72  result += ")";73  return result;74}75 76// Converts an identifier name to a space-separated list of lower-case77// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is78// treated as one word.  For example, both "FooBar123" and79// "foo_bar_123" are converted to "foo bar 123".80GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name) {81  std::string result;82  char prev_char = '\0';83  for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {84    // We don't care about the current locale as the input is85    // guaranteed to be a valid C++ identifier name.86    const bool starts_new_word = IsUpper(*p) ||87                                 (!IsAlpha(prev_char) && IsLower(*p)) ||88                                 (!IsDigit(prev_char) && IsDigit(*p));89 90    if (IsAlNum(*p)) {91      if (starts_new_word && !result.empty()) result += ' ';92      result += ToLower(*p);93    }94  }95  return result;96}97 98// This class reports Google Mock failures as Google Test failures.  A99// user can define another class in a similar fashion if they intend to100// use Google Mock with a testing framework other than Google Test.101class GoogleTestFailureReporter : public FailureReporterInterface {102 public:103  void ReportFailure(FailureType type, const char* file, int line,104                     const std::string& message) override {105    AssertHelper(type == kFatal ? TestPartResult::kFatalFailure106                                : TestPartResult::kNonFatalFailure,107                 file, line, message.c_str()) = Message();108    if (type == kFatal) {109      posix::Abort();110    }111  }112};113 114// Returns the global failure reporter.  Will create a115// GoogleTestFailureReporter and return it the first time called.116GTEST_API_ FailureReporterInterface* GetFailureReporter() {117  // Points to the global failure reporter used by Google Mock.  gcc118  // guarantees that the following use of failure_reporter is119  // thread-safe.  We may need to add additional synchronization to120  // protect failure_reporter if we port Google Mock to other121  // compilers.122  static FailureReporterInterface* const failure_reporter =123      new GoogleTestFailureReporter();124  return failure_reporter;125}126 127// Protects global resources (stdout in particular) used by Log().128static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);129 130// Returns true if and only if a log with the given severity is visible131// according to the --gmock_verbose flag.132GTEST_API_ bool LogIsVisible(LogSeverity severity) {133  if (GMOCK_FLAG_GET(verbose) == kInfoVerbosity) {134    // Always show the log if --gmock_verbose=info.135    return true;136  } else if (GMOCK_FLAG_GET(verbose) == kErrorVerbosity) {137    // Always hide it if --gmock_verbose=error.138    return false;139  } else {140    // If --gmock_verbose is neither "info" nor "error", we treat it141    // as "warning" (its default value).142    return severity == kWarning;143  }144}145 146// Prints the given message to stdout if and only if 'severity' >= the level147// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=148// 0, also prints the stack trace excluding the top149// stack_frames_to_skip frames.  In opt mode, any positive150// stack_frames_to_skip is treated as 0, since we don't know which151// function calls will be inlined by the compiler and need to be152// conservative.153GTEST_API_ void Log(LogSeverity severity, const std::string& message,154                    int stack_frames_to_skip) {155  if (!LogIsVisible(severity)) return;156 157  // Ensures that logs from different threads don't interleave.158  MutexLock l(&g_log_mutex);159 160  if (severity == kWarning) {161    // Prints a GMOCK WARNING marker to make the warnings easily searchable.162    std::cout << "\nGMOCK WARNING:";163  }164  // Pre-pends a new-line to message if it doesn't start with one.165  if (message.empty() || message[0] != '\n') {166    std::cout << "\n";167  }168  std::cout << message;169  if (stack_frames_to_skip >= 0) {170#ifdef NDEBUG171    // In opt mode, we have to be conservative and skip no stack frame.172    const int actual_to_skip = 0;173#else174    // In dbg mode, we can do what the caller tell us to do (plus one175    // for skipping this function's stack frame).176    const int actual_to_skip = stack_frames_to_skip + 1;177#endif  // NDEBUG178 179    // Appends a new-line to message if it doesn't end with one.180    if (!message.empty() && *message.rbegin() != '\n') {181      std::cout << "\n";182    }183    std::cout << "Stack trace:\n"184              << ::testing::internal::GetCurrentOsStackTraceExceptTop(185                     actual_to_skip);186  }187  std::cout << ::std::flush;188}189 190GTEST_API_ WithoutMatchers GetWithoutMatchers() { return WithoutMatchers(); }191 192GTEST_API_ void IllegalDoDefault(const char* file, int line) {193  internal::Assert(194      false, file, line,195      "You are using DoDefault() inside a composite action like "196      "DoAll() or WithArgs().  This is not supported for technical "197      "reasons.  Please instead spell out the default action, or "198      "assign the default action to an Action variable and use "199      "the variable in various places.");200}201 202constexpr char UndoWebSafeEncoding(char c) {203  return c == '-' ? '+' : c == '_' ? '/' : c;204}205 206constexpr char UnBase64Impl(char c, const char* const base64, char carry) {207  return *base64 == 0 ? static_cast<char>(65)208         : *base64 == c209             ? carry210             : UnBase64Impl(c, base64 + 1, static_cast<char>(carry + 1));211}212 213template <size_t... I>214constexpr std::array<char, 256> UnBase64Impl(IndexSequence<I...>,215                                             const char* const base64) {216  return {217      {UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}};218}219 220constexpr std::array<char, 256> UnBase64(const char* const base64) {221  return UnBase64Impl(MakeIndexSequence<256>{}, base64);222}223 224static constexpr char kBase64[] =225    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";226static constexpr std::array<char, 256> kUnBase64 = UnBase64(kBase64);227 228bool Base64Unescape(const std::string& encoded, std::string* decoded) {229  decoded->clear();230  size_t encoded_len = encoded.size();231  decoded->reserve(3 * (encoded_len / 4) + (encoded_len % 4));232  int bit_pos = 0;233  char dst = 0;234  for (int src : encoded) {235    if (std::isspace(src) || src == '=') {236      continue;237    }238    char src_bin = kUnBase64[static_cast<size_t>(src)];239    if (src_bin >= 64) {240      decoded->clear();241      return false;242    }243    if (bit_pos == 0) {244      dst |= static_cast<char>(src_bin << 2);245      bit_pos = 6;246    } else {247      dst |= static_cast<char>(src_bin >> (bit_pos - 2));248      decoded->push_back(dst);249      dst = static_cast<char>(src_bin << (10 - bit_pos));250      bit_pos = (bit_pos + 6) % 8;251    }252  }253  return true;254}255 256}  // namespace internal257}  // namespace testing258