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