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