Compare commits

...

10 Commits

Author SHA1 Message Date
jiemojiemo
d89f558f95
Merge f482391f3d28de1c8a258b9ec8181cc51e400be3 into a0f06a70e3da7afa88da9527c43951bca1f7cef2 2026-07-29 21:21:54 +00:00
Abseil Team
a0f06a70e3 Make GoogleTest handle std::monostate and valueless_by_exception() for std::variant similarly to how it handles std::nullopt
Fixes: #2066
PiperOrigin-RevId: 955981465
Change-Id: I6b34dc2e634d4b727a50fb3e21e5d8e25c39a13b
2026-07-29 11:08:13 -07:00
Copybara-Service
3ff51c3e80 Merge pull request #5041 from alvinjaison:fix/get-test-suite-shuffle-index
PiperOrigin-RevId: 955317170
Change-Id: I40e01cdafe58768ccdb743dcf38717e48edcde41
2026-07-28 09:58:12 -07:00
Abseil Team
c6f04243ed Automated Code Change
PiperOrigin-RevId: 955021426
Change-Id: I3ab06e960011d1d0cd44ea00595a5067aaa7f30b
2026-07-27 22:07:28 -07:00
Abseil Team
af4c3cfcb3 Automated Code Change
PiperOrigin-RevId: 955017590
Change-Id: I5125f56376603462fb63796fec1fbc50fd4d935f
2026-07-27 21:57:20 -07:00
Abseil Team
ecb18f0b03 Automated Code Change
PiperOrigin-RevId: 955003621
Change-Id: I83518a7f947d9f7d9b89fe14e1219d32bcdc95a3
2026-07-27 21:17:32 -07:00
Alvin Jaison
1269db9643 Fix GetTestSuite(i) ignoring shuffle order UnitTestImpl::GetTestSuite(int i) computes the shuffled index from test_suite_indices_ but then accesses test_suites_ using the raw parameter 'i' instead of the computed 'index'. This causes the public API UnitTest::GetTestSuite(i) to return test suites in original registration order rather than the active shuffle order. The mutable variant GetMutableSuiteCase(i) correctly uses 'index', and the equivalent function TestSuite::GetTestInfo(i) also uses 'index'. This was a copy-paste typo introduced in commit bd851333 (Sep 2009) when the shuffle feature was first added. The bug is observable from within TestEventListener callbacks during test execution when --gtest_shuffle is active. 2026-07-24 16:11:55 +01:00
jiemojiemo
f482391f3d add docs/quickstart-cmake-zh.md 2021-10-22 21:02:18 +08:00
jiemojiemo
b1e7595753 add docs/quickstart-bazel-zh.md 2021-10-22 21:01:56 +08:00
jiemojiemo
b2788e9227 add platforms-zh.md 2021-10-20 22:59:05 +08:00
12 changed files with 333 additions and 32 deletions

29
docs/platforms-zh.md Normal file
View File

@ -0,0 +1,29 @@
# 支持的平台
GoogleTest 需要符合 C++11 标准或者更新标准的代码库和编译器
GoogleTest 代码在以下平台上获得了正式支持。下面未列出的操作系统或工具是社区支持的。对于社区支持的平台,可以考虑使用不使代码复杂化的补丁。
如果在你的平台上发现任何问题,请将问题提交到 [GoogleTest GitHub Issue Tracker](https://github.com/google/googletest/issues). 欢迎提交 Pull requests 进行修复!
### 操作系统
* Linux
* macOS
* Windows
### 编译器
* gcc 5.0+
* clang 5.0+
* MSVC 2015+
**macOS 用户:** Xcode 9.3+ 提供了 clang 5.0+.
### 构建系统
* [Bazel](https://bazel.build/)
* [CMake](https://cmake.org/)
Bazel 是 google 团队内部和测试中使用的构建系统。CMake 是由开源社区支持的构建系统。

113
docs/quickstart-bazel-zh.md Normal file
View File

@ -0,0 +1,113 @@
# 快速入门:使用 Bazel 构建
这个教程旨在让你使用 Bazel 构建和运行 GoogleTest。如果你是第一次使用 GoogleTest或者需要复习一下我们建议将本教程作为起点。
## 前提条件
为了完成这个教程,你需要的工具有:
+ 一个兼容的操作系统(例如 LinuxmacOSWindows
+ 一个兼容的 C++ 编译器,至少支持 C++11。
+ [Bazel](https://bazel.build/)GoogleTest 团队使用的首选构建系统。
更多关于 GoogleTest 兼容平台的信息,请参见 [支持的平台](platforms-zh.md)。
如果你没有安装 Bazel参考 [Bazel installation guide](https://docs.bazel.build/versions/master/install.html)。
{: .callout .note}
注意: 本教程中的终端命令显示的是 Unix shell但这些命令在 Windows 命令行是哪个也可以使用。
## 建立一个 Bazel 工作区
[Bazel 工作区](https://docs.bazel.build/versions/master/build-ref.html#workspace) 是你文件系统上的一个目录,用于管理你想要构建的系统的源文件。每个工作区有个文本文件叫做 `WORKSPACE`,它可能是空的,也可能包含构建需要的外部依赖的引用。
首先,为你的工作区创建一个目录:
```
$ mkdir my_workspace && cd my_workspace
```
接着,创建 `WORKSPACE` 文件来指定依赖关系。为了依赖 GoogleTest一种常见且推荐方式是通过 [`http_archive` 规则](https://docs.bazel.build/versions/master/repo/http.html#http_archive) 使用 [Bazel 外部依赖](https://docs.bazel.build/versions/master/external.html)。为此,在你的工作空间根目录下(`my_workspace/`)创建一个名为`WORKSPACE`的文件,内容为:
```
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "com_google_googletest",
urls = ["https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip"],
strip_prefix = "googletest-609281088cfefc76f9d0ce82e1ff6c30cc3591e5",
)
```
上述配置声明了对 GoogleTest 的依赖GoogleTest 将以 ZIP 文件的形式从 Gihub 中下载。上述例子中,`609281088cfefc76f9d0ce82e1ff6c30cc3591e5`即 GoogleTest 版本的 Git commit ID。建议经常更新该值以指向最新的版本。
现在你已经准备好构建使用 GoogleTest 的 C++ 代码了。
## 创建并运行
随着 Bazel 工作区的建立,现在可以在你的项目中使用 GoogleTest 代码了。
举个例子,在 `my_workspace` 目录下创建 `hello_test.cc` 文件,内容为:
```cpp
#include <gtest/gtest.h>
// Demonstrate some basic assertions.
TEST(HelloTest, BasicAssertions) {
// Expect two strings not to be equal.
EXPECT_STRNE("hello", "world");
// Expect equality.
EXPECT_EQ(7 * 6, 42);
}
```
GoogleTest 提供了许多 [断言](primer.md#assertions),可以用它们来测试代码的行为。上述示例中引入了 GoogleTest 的头文件并演示了一些基本的断言。
为了编译代码,请在相同目录下创建一个叫 `BUILD` 的文件,内容为:
```
cc_test(
name = "hello_test",
size = "small",
srcs = ["hello_test.cc"],
deps = ["@com_google_googletest//:gtest_main"],
)
```
`cc_test` 规则声明了你要建立的测试可执行文件,并通过在 `WORKSPACE` 文件中指定的前缀(`@com_google_googletest`)去链接 GoogleTest。更多关于 Bazel `BUILD`文件的内容,请参考 [Bazel C++ Tutorial](https://docs.bazel.build/versions/master/tutorial/cpp.html)。
现在你可以投建并运行你的测试了:
<pre>
<strong>my_workspace$ bazel test --test_output=all //:hello_test</strong>
INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
INFO: Found 1 test target...
INFO: From Testing //:hello_test:
==================== Test output for //:hello_test:
Running main() from gmock_main.cc
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from HelloTest
[ RUN ] HelloTest.BasicAssertions
[ OK ] HelloTest.BasicAssertions (0 ms)
[----------] 1 test from HelloTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
================================================================================
Target //:hello_test up-to-date:
bazel-bin/hello_test
INFO: Elapsed time: 4.190s, Critical Path: 3.05s
INFO: 27 processes: 8 internal, 19 linux-sandbox.
INFO: Build completed successfully, 27 total actions
//:hello_test PASSED in 0.1s
INFO: Build completed successfully, 27 total actions
</pre>
恭喜!你已经成功地使用 GoogleTest 构建并运行了一个测试。
## 下一步行动
* [查看 Primer](primer.md) 开始学习如何编写简单的测试。
* [看看更多例子](samples.md)学习如何使用 GoogleTest 的各种功能。

123
docs/quickstart-cmake-zh.md Normal file
View File

@ -0,0 +1,123 @@
# 快速入门:使用 CMake 构建
这个教程旨在让你使用 CMake 构建和运行 GoogleTest。如果你是第一次使用 GoogleTest或者需要复习一下我们建议将本教程作为起点。如果你的项目使用 Bazel请参阅 [快速入门:使用 Bazel 构建](quickstart-bazel-zh.md)
## 前提条件
为了完成这个教程,你需要的工具有:
+ 一个兼容的操作系统(例如 LinuxmacOSWindows
+ 一个兼容的 C++ 编译器,至少支持 C++11。
+ [CMake](https://cmake.org/) 以及一系列用于构建的工具。
+ 构建工具包括 [Make](https://www.gnu.org/software/make/)[Ninja](https://ninja-build.org/),和其他,更多信息请参考[CMake Generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html。
更多关于 GoogleTest 兼容平台的信息,请参见 [支持的平台](platforms-zh.md) 。
如果你没有安装 CMake参考 [CMake installation guide。](https://cmake.org/install)
{: .callout .note}
注意: 本教程中的终端命令显示的是 Unix shell但这些命令在 Windows 命令行是哪个也可以使用。
## 建立一个项目
CMake 使用一个叫 `CMakeLists.txt` 的文件来配置项目的构建系统。使用此文件来设置项目并声明对 GoogleTest 的依赖。
首先,为你的项目创建一个目录:
```
$ mkdir my_project && cd my_project
```
接着,创建 `CMakeLists.txt` 文件并声明对 GoogleTest 的依赖。在 CMake 系统中,有很多方法来表达依赖关系;在本教程中,你将使用 [`FetchContent` CMake 模块](https://cmake.org/cmake/help/latest/module/FetchContent.html)。为此,在工程目录下(`my_project`)创建一个名为 `CMakeLists.txt` 的文件,其内容为:
```cmake
cmake_minimum_required(VERSION 3.14)
project(my_project)
# GoogleTest requires at least C++11
set(CMAKE_CXX_STANDARD 11)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
```
上述配置声明了对 GoogleTest 的依赖,其中 GoogleTest 将从 Github 上下载。上述例子中,`609281088cfefc76f9d0ce82e1ff6c30cc3591e5` 即 GoogleTest 版本的 Git commit ID。建议经常更新该值以指向最新的版本。
关于如何创建 `CMakeLists.txt` 文件的更多信息,请参与 [CMake Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html)。
## 创建并运行
有了 GoogleTest 的依赖后,你就可以在项目中使用 GoogleTest 了。
举个例子,在 `my_project` 目录下创建 `hello_test.cc` 文件,内容为:
```cpp
#include <gtest/gtest.h>
// Demonstrate some basic assertions.
TEST(HelloTest, BasicAssertions) {
// Expect two strings not to be equal.
EXPECT_STRNE("hello", "world");
// Expect equality.
EXPECT_EQ(7 * 6, 42);
}
```
GoogleTest 提供了许多 [断言](primer.md#assertions),可以用它们来测试代码的行为。上述示例中引入了 GoogleTest 的头文件并演示了一些基本的断言。
为了编译代码,在 `CMakeLists.txt` 末尾添加以下内容:
```cmake
enable_testing()
add_executable(
hello_test
hello_test.cc
)
target_link_libraries(
hello_test
gtest_main
)
include(GoogleTest)
gtest_discover_tests(hello_test)
```
上述配置在 CMake 中启动了测试,声明了你想要建立的测试可执行文件(`hello_test`)并链接了 GoogleTest`gtest_main`)。最后两行使用 [`GoogleTest` CMake 模块](https://cmake.org/cmake/help/git-stage/module/GoogleTest.html) 让 CMake 的测试运行器能找到并执行测试。
现在你可以投建并运行你的测试了:
<pre>
<strong>my_project$ cmake -S . -B build</strong>
-- The C compiler identification is GNU 10.2.1
-- The CXX compiler identification is GNU 10.2.1
...
-- Build files have been written to: .../my_project/build
<strong>my_project$ cmake --build build</strong>
Scanning dependencies of target gtest
...
[100%] Built target gmock_main
<strong>my_project$ cd build && ctest</strong>
Test project .../my_project/build
Start 1: HelloTest.BasicAssertions
1/1 Test #1: HelloTest.BasicAssertions ........ Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.01 sec
</pre>
恭喜!你已经成功地使用 GoogleTest 构建并运行了一个测试。
## 下一步行动
* [查看 Primer](primer.md) 开始学习如何编写简单的测试。
* [看看更多例子](samples.md)学习如何使用 GoogleTest 的各种功能。

View File

@ -30,6 +30,8 @@
// Tests that Google Mock constructs can be used in a large number of
// threads concurrently.
#include <iterator>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@ -188,7 +190,7 @@ TEST(StressTest, CanUseGMockWithThreads) {
&TestPartiallyOrderedExpectationsWithThreads,
};
const int kRoutines = sizeof(test_routines) / sizeof(test_routines[0]);
const int kRoutines = std::size(test_routines);
const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
ThreadWithParam<Dummy>* threads[kTestThreads] = {};

View File

@ -945,13 +945,13 @@ template <typename T>
class [[nodiscard]] UniversalPrinter<std::optional<T>> {
public:
static void Print(const std::optional<T>& value, ::std::ostream* os) {
*os << '(';
if (!value) {
*os << "nullopt";
UniversalPrint(std::nullopt, os);
} else {
*os << '(';
UniversalPrint(*value, os);
*os << ')';
}
*os << ')';
}
};
@ -961,27 +961,38 @@ class [[nodiscard]] UniversalPrinter<std::nullopt_t> {
static void Print(std::nullopt_t, ::std::ostream* os) { *os << "(nullopt)"; }
};
struct UniversalPrinterVisitor {
template <typename T>
void operator()(const T& arg) const {
*os << "'" << GetTypeName<T>() << "(index = " << index << ")' with value ";
UniversalPrint(arg, os);
}
::std::ostream* os;
std::size_t index;
};
// Printer for std::variant
template <typename... T>
class [[nodiscard]] UniversalPrinter<std::variant<T...>> {
public:
static void Print(const std::variant<T...>& value, ::std::ostream* os) {
*os << '(';
std::visit(Visitor{os, value.index()}, value);
*os << ')';
}
private:
struct Visitor {
template <typename U>
void operator()(const U& u) const {
*os << "'" << GetTypeName<U>() << "(index = " << index
<< ")' with value ";
UniversalPrint(u, os);
if (value.valueless_by_exception()) {
*os << "(valueless)";
} else {
*os << '(';
std::visit(UniversalPrinterVisitor{os, value.index()}, value);
*os << ')';
}
::std::ostream* os;
std::size_t index;
};
}
};
// Printer for std::monostate
template <>
class [[nodiscard]] UniversalPrinter<std::monostate> {
public:
static void Print(std::monostate, ::std::ostream* os) {
*os << "(monostate)";
}
};
// UniversalPrintArray(begin, len, os) prints an array of 'len'

View File

@ -39,6 +39,8 @@
#include "sample2.h"
#include <iterator>
#include "gtest/gtest.h"
namespace {
// In this example, we test the MyString class (a simple string).
@ -78,7 +80,7 @@ const char kHelloString[] = "Hello, world!";
TEST(MyString, ConstructorFromCString) {
const MyString s(kHelloString);
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());
EXPECT_EQ(std::size(kHelloString) - 1, s.Length());
}
// Tests the copy c'tor.

View File

@ -587,7 +587,7 @@ class GTEST_API_ UnitTestImpl {
// total_test_suite_count() - 1. If i is not in that range, returns NULL.
const TestSuite* GetTestSuite(int i) const {
const int index = GetElementOr(test_suite_indices_, i, -1);
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
}
// Legacy API is deprecated but still available

View File

@ -32,6 +32,7 @@
// This file verifies Google Test event listeners receive events at the
// right times.
#include <iterator>
#include <string>
#include <vector>
@ -498,8 +499,7 @@ int main(int argc, char** argv) {
"1st.OnTestProgramEnd"};
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
VerifyResults(events, expected_events,
sizeof(expected_events) / sizeof(expected_events[0]));
VerifyResults(events, expected_events, std::size(expected_events));
// We need to check manually for ad hoc test failures that happen after
// RUN_ALL_TESTS finishes.

View File

@ -36,6 +36,7 @@
#include <stdlib.h>
#include <algorithm>
#include <iterator>
#include <string>
#include "gtest/gtest-spi.h"
@ -149,7 +150,7 @@ TEST(LoggingTest, InterleavingLoggingAndAssertions) {
static const int a[4] = {3, 9, 2, 6};
printf("(expecting 2 failures on (3) >= (a[i]))\n");
for (int i = 0; i < static_cast<int>(sizeof(a) / sizeof(*a)); i++) {
for (int i = 0; i < static_cast<int>(std::size(a)); i++) {
printf("i == %d\n", i);
EXPECT_GE(3, a[i]);
}

View File

@ -39,6 +39,7 @@
#include <cstdint>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <set>
#include <sstream>
@ -737,10 +738,7 @@ const int test_generation_params[] = {36, 42, 72};
class TestGenerationTest : public TestWithParam<int> {
public:
enum {
PARAMETER_COUNT =
sizeof(test_generation_params) / sizeof(test_generation_params[0])
};
enum { PARAMETER_COUNT = std::size(test_generation_params) };
typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;

View File

@ -39,6 +39,7 @@
#include <deque>
#include <forward_list>
#include <functional>
#include <iterator>
#include <limits>
#include <list>
#include <map>
@ -1784,7 +1785,7 @@ TEST(IsValidUTF8Test, IllFormedUTF8) {
// too.
{"\xEE\x80\x80", "\"\\xEE\\x80\\x80\"\n As Text: \"\""}};
for (int i = 0; i < int(sizeof(kTestdata) / sizeof(kTestdata[0])); ++i) {
for (int i = 0; i < int(std::size(kTestdata)); ++i) {
EXPECT_PRINT_TO_STRING_(kTestdata[i][0], kTestdata[i][1]);
}
}
@ -2029,6 +2030,26 @@ TEST(PrintOneofTest, Basic) {
PrintToString(Type(NonPrintable{})));
}
TEST(PrintVariantTest, Monostate) {
EXPECT_EQ("(monostate)", PrintToString(std::monostate()));
#if GTEST_HAS_EXCEPTIONS
struct ThrowOnMove {
ThrowOnMove() = default;
ThrowOnMove(ThrowOnMove&& other) { *this = std::move(other); }
ThrowOnMove& operator=(ThrowOnMove&&) {
(void)std::vector<bool>().at(0);
return *this;
}
};
std::variant<std::monostate, ThrowOnMove> v = std::monostate();
EXPECT_EQ("('std::monostate(index = 0)' with value (monostate))",
PrintToString(v));
EXPECT_THROW(v = ThrowOnMove(), std::out_of_range);
EXPECT_EQ("(valueless)", PrintToString(v));
#endif
}
#if GTEST_INTERNAL_HAS_COMPARE_LIB
TEST(PrintOrderingTest, Basic) {
EXPECT_EQ("(less)", PrintToString(std::strong_ordering::less));

View File

@ -33,6 +33,8 @@
#include "gtest/gtest.h"
#include <iterator>
// Verifies that the command line flag variables can be accessed in
// code once "gtest.h" has been #included.
// Do not move it after other gtest #includes.
@ -5853,9 +5855,8 @@ class ParseFlagsTest : public Test {
// to specify the array sizes.
#define GTEST_TEST_PARSING_FLAGS_(argv1, argv2, expected, should_print_help) \
TestParsingFlags(sizeof(argv1) / sizeof(*argv1) - 1, argv1, \
sizeof(argv2) / sizeof(*argv2) - 1, argv2, expected, \
should_print_help)
TestParsingFlags(std::size(argv1) - 1, argv1, std::size(argv2) - 1, argv2, \
expected, should_print_help)
};
// Tests parsing an empty command line.