Merge pull request #3319 from a-sully:patch-1
PiperOrigin-RevId: 367509099
diff --git a/.github/ISSUE_TEMPLATE/90-question.md b/.github/ISSUE_TEMPLATE/90-question.md
deleted file mode 100644
index 46ec8b0..0000000
--- a/.github/ISSUE_TEMPLATE/90-question.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: Question
-about: Can't find an answer to your question? Ask us!
-title: ''
-labels: 'question'
-assignees: ''
----
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 0086358..3ba13e0 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1 +1 @@
-blank_issues_enabled: true
+blank_issues_enabled: false
diff --git a/BUILD.bazel b/BUILD.bazel
index 8099642..965c518 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -40,7 +40,15 @@
config_setting(
name = "windows",
- constraint_values = ["@bazel_tools//platforms:windows"],
+ constraint_values = ["@platforms//os:windows"],
+)
+
+config_setting(
+ name = "msvc_compiler",
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "msvc-cl",
+ },
+ visibility = [":__subpackages__"],
)
config_setting(
diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml
index b79f250..355ebc8 100644
--- a/docs/_data/navigation.yml
+++ b/docs/_data/navigation.yml
@@ -3,6 +3,10 @@
items:
- title: "Supported Platforms"
url: "/platforms.html"
+ - title: "Quickstart: Bazel"
+ url: "/quickstart-bazel.html"
+ - title: "Quickstart: CMake"
+ url: "/quickstart-cmake.html"
- section: "Guides"
items:
- title: "GoogleTest Primer"
diff --git a/docs/advanced.md b/docs/advanced.md
index 4103507..fa9e5bc 100644
--- a/docs/advanced.md
+++ b/docs/advanced.md
@@ -813,7 +813,8 @@
consideration to be run - much like the `threadsafe` mode on POSIX.
Other values for the variable are illegal and will cause the death test to fail.
-Currently, the flag's default value is **"fast"**
+Currently, the flag's default value is
+**`"fast"`**.
1. the child's exit status satisfies the predicate, and
2. the child's stderr matches the regular expression.
@@ -1204,10 +1205,10 @@
}
// You can define per-test set-up logic as usual.
- virtual void SetUp() { ... }
+ void SetUp() override { ... }
// You can define per-test tear-down logic as usual.
- virtual void TearDown() { ... }
+ void TearDown() override { ... }
// Some expensive resource shared by all tests.
static T* shared_resource_;
@@ -1238,7 +1239,7 @@
environment, which knows how to set-up and tear-down:
```c++
-class Environment : public testing::Environment {
+class Environment : public ::testing::Environment {
public:
~Environment() override {}
@@ -1374,7 +1375,7 @@
each with parameter values `"meeny"`, `"miny"`, and `"moe"`.
```c++
-INSTANTIATE_TEST_SUITE_P(InstantiationName,
+INSTANTIATE_TEST_SUITE_P(MeenyMinyMoe,
FooTest,
testing::Values("meeny", "miny", "moe"));
```
@@ -1383,51 +1384,54 @@
NOTE: The code above must be placed at global or namespace scope, not at
function scope.
-Per default, every `TEST_P` without a corresponding `INSTANTIATE_TEST_SUITE_P`
-causes a failing test in test suite `GoogleTestVerification`. If you have a test
-suite where that omission is not an error, for example it is in a library that
-may be linked in for other reason or where the list of test cases is dynamic and
-may be empty, then this check can be suppressed by tagging the test suite:
+The first argument to `INSTANTIATE_TEST_SUITE_P` is a unique name for the
+instantiation of the test suite. The next argument is the name of the test
+pattern, and the last is the parameter generator.
-```c++
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest);
-```
+You can instantiate a test pattern more than once, so to distinguish different
+instances of the pattern, the instantiation name is added as a prefix to the
+actual test suite name. Remember to pick unique prefixes for different
+instantiations. The tests from the instantiation above will have these names:
-To distinguish different instances of the pattern (yes, you can instantiate it
-more than once), the first argument to `INSTANTIATE_TEST_SUITE_P` is a prefix
-that will be added to the actual test suite name. Remember to pick unique
-prefixes for different instantiations. The tests from the instantiation above
-will have these names:
-
-* `InstantiationName/FooTest.DoesBlah/0` for `"meeny"`
-* `InstantiationName/FooTest.DoesBlah/1` for `"miny"`
-* `InstantiationName/FooTest.DoesBlah/2` for `"moe"`
-* `InstantiationName/FooTest.HasBlahBlah/0` for `"meeny"`
-* `InstantiationName/FooTest.HasBlahBlah/1` for `"miny"`
-* `InstantiationName/FooTest.HasBlahBlah/2` for `"moe"`
+* `MeenyMinyMoe/FooTest.DoesBlah/0` for `"meeny"`
+* `MeenyMinyMoe/FooTest.DoesBlah/1` for `"miny"`
+* `MeenyMinyMoe/FooTest.DoesBlah/2` for `"moe"`
+* `MeenyMinyMoe/FooTest.HasBlahBlah/0` for `"meeny"`
+* `MeenyMinyMoe/FooTest.HasBlahBlah/1` for `"miny"`
+* `MeenyMinyMoe/FooTest.HasBlahBlah/2` for `"moe"`
You can use these names in [`--gtest_filter`](#running-a-subset-of-the-tests).
-This statement will instantiate all tests from `FooTest` again, each with
-parameter values `"cat"` and `"dog"`:
+The following statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"`:
```c++
const char* pets[] = {"cat", "dog"};
-INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest,
- testing::ValuesIn(pets));
+INSTANTIATE_TEST_SUITE_P(Pets, FooTest, testing::ValuesIn(pets));
```
The tests from the instantiation above will have these names:
-* `AnotherInstantiationName/FooTest.DoesBlah/0` for `"cat"`
-* `AnotherInstantiationName/FooTest.DoesBlah/1` for `"dog"`
-* `AnotherInstantiationName/FooTest.HasBlahBlah/0` for `"cat"`
-* `AnotherInstantiationName/FooTest.HasBlahBlah/1` for `"dog"`
+* `Pets/FooTest.DoesBlah/0` for `"cat"`
+* `Pets/FooTest.DoesBlah/1` for `"dog"`
+* `Pets/FooTest.HasBlahBlah/0` for `"cat"`
+* `Pets/FooTest.HasBlahBlah/1` for `"dog"`
Please note that `INSTANTIATE_TEST_SUITE_P` will instantiate *all* tests in the
given test suite, whether their definitions come before or *after* the
`INSTANTIATE_TEST_SUITE_P` statement.
+Additionally, by default, every `TEST_P` without a corresponding
+`INSTANTIATE_TEST_SUITE_P` causes a failing test in test suite
+`GoogleTestVerification`. If you have a test suite where that omission is not an
+error, for example it is in a library that may be linked in for other reasons or
+where the list of test cases is dynamic and may be empty, then this check can be
+suppressed by tagging the test suite:
+
+```c++
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest);
+```
+
You can see [sample7_unittest.cc] and [sample8_unittest.cc] for more examples.
[sample7_unittest.cc]: https://github.com/google/googletest/blob/master/googletest/samples/sample7_unittest.cc "Parameterized Test example"
@@ -1970,13 +1974,13 @@
```c++
class MinimalistPrinter : public testing::EmptyTestEventListener {
// Called before a test starts.
- virtual void OnTestStart(const testing::TestInfo& test_info) {
+ void OnTestStart(const testing::TestInfo& test_info) override {
printf("*** Test %s.%s starting.\n",
test_info.test_suite_name(), test_info.name());
}
// Called after a failed assertion or a SUCCESS().
- virtual void OnTestPartResult(const testing::TestPartResult& test_part_result) {
+ void OnTestPartResult(const testing::TestPartResult& test_part_result) override {
printf("%s in %s:%d\n%s\n",
test_part_result.failed() ? "*** Failure" : "Success",
test_part_result.file_name(),
@@ -1985,7 +1989,7 @@
}
// Called after a test ends.
- virtual void OnTestEnd(const testing::TestInfo& test_info) {
+ void OnTestEnd(const testing::TestInfo& test_info) override {
printf("*** Test %s.%s ending.\n",
test_info.test_suite_name(), test_info.name());
}
diff --git a/docs/faq.md b/docs/faq.md
index da443e3..4071232 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -60,9 +60,10 @@
## Why does googletest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`?
-First of all you can use `EXPECT_NE(nullptr, ptr)` and `ASSERT_NE(nullptr,
-ptr)`. This is the preferred syntax in the style guide because nullptr does not
-have the type problems that NULL does. Which is why NULL does not work.
+First of all, you can use `nullptr` with each of these macros, e.g.
+`EXPECT_EQ(ptr, nullptr)`, `EXPECT_NE(ptr, nullptr)`, `ASSERT_EQ(ptr, nullptr)`,
+`ASSERT_NE(ptr, nullptr)`. This is the preferred syntax in the style guide
+because `nullptr` does not have the type problems that `NULL` does.
Due to some peculiarity of C++, it requires some non-trivial template meta
programming tricks to support using `NULL` as an argument of the `EXPECT_XX()`
@@ -70,22 +71,21 @@
(otherwise we make the implementation of googletest harder to maintain and more
error-prone than necessary).
-The `EXPECT_EQ()` macro takes the *expected* value as its first argument and the
-*actual* value as the second. It's reasonable that someone wants to write
-`EXPECT_EQ(NULL, some_expression)`, and this indeed was requested several times.
-Therefore we implemented it.
+Historically, the `EXPECT_EQ()` macro took the *expected* value as its first
+argument and the *actual* value as the second, though this argument order is now
+discouraged. It was reasonable that someone wanted
+to write `EXPECT_EQ(NULL, some_expression)`, and this indeed was requested
+several times. Therefore we implemented it.
-The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the assertion
+The need for `EXPECT_NE(NULL, ptr)` wasn't nearly as strong. When the assertion
fails, you already know that `ptr` must be `NULL`, so it doesn't add any
information to print `ptr` in this case. That means `EXPECT_TRUE(ptr != NULL)`
works just as well.
-If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll have to
-support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`, we don't have a
-convention on the order of the two arguments for `EXPECT_NE`. This means using
-the template meta programming tricks twice in the implementation, making it even
-harder to understand and maintain. We believe the benefit doesn't justify the
-cost.
+If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'd have to
+support `EXPECT_NE(ptr, NULL)` as well. This means using the template meta
+programming tricks twice in the implementation, making it even harder to
+understand and maintain. We believe the benefit doesn't justify the cost.
Finally, with the growth of the gMock matcher library, we are encouraging people
to use the unified `EXPECT_THAT(value, matcher)` syntax more often in tests. One
@@ -706,12 +706,12 @@
## How do I temporarily disable a test?
If you have a broken test that you cannot fix right away, you can add the
-DISABLED_ prefix to its name. This will exclude it from execution. This is
-better than commenting out the code or using #if 0, as disabled tests are still
-compiled (and thus won't rot).
+`DISABLED_` prefix to its name. This will exclude it from execution. This is
+better than commenting out the code or using `#if 0`, as disabled tests are
+still compiled (and thus won't rot).
To include disabled tests in test execution, just invoke the test program with
-the --gtest_also_run_disabled_tests flag.
+the `--gtest_also_run_disabled_tests` flag.
## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces?
diff --git a/docs/gmock_cheat_sheet.md b/docs/gmock_cheat_sheet.md
index 723cb7e..90be4a3 100644
--- a/docs/gmock_cheat_sheet.md
+++ b/docs/gmock_cheat_sheet.md
@@ -123,7 +123,7 @@
.WillRepeatedly(Return("Category 5"));
// ... other expectations ...
- EXPECT_EQ("good", MyProductionFunction(&foo)); // #5
+ EXPECT_EQ(MyProductionFunction(&foo), "good"); // #5
} // #6
```
@@ -162,8 +162,8 @@
auto buzz1 = mock_buzzer_.MakeBuzz("hello");
auto buzz2 = mock_buzzer_.MakeBuzz("hello");
- EXPECT_NE(nullptr, buzz1);
- EXPECT_NE(nullptr, buzz2);
+ EXPECT_NE(buzz1, nullptr);
+ EXPECT_NE(buzz2, nullptr);
EXPECT_NE(buzz1, buzz2);
// Resets the default action for return type std::unique_ptr<Buzz>,
@@ -362,10 +362,11 @@
int len)` -- see [Multi-argument Matchers](#MultiArgMatchers)).
* The array being matched may be multi-dimensional (i.e. its elements can be
arrays).
-* `m` in `Pointwise(m, ...)` should be a matcher for `::std::tuple<T, U>`
- where `T` and `U` are the element type of the actual container and the
- expected container, respectively. For example, to compare two `Foo`
- containers where `Foo` doesn't support `operator==`, one might write:
+* `m` in `Pointwise(m, ...)` and `UnorderedPointwise(m, ...)` should be a
+ matcher for `::std::tuple<T, U>` where `T` and `U` are the element type of
+ the actual container and the expected container, respectively. For example,
+ to compare two `Foo` containers where `Foo` doesn't support `operator==`,
+ one might write:
```cpp
using ::std::get;
@@ -384,12 +385,28 @@
| `Field(field_name, &class::field, m)` | The same as the two-parameter version, but provides a better error message. |
| `Key(e)` | `argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`. |
| `Pair(m1, m2)` | `argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`. |
-| `FieldsAre(m...)` | `argument` is a compatible object where each field matches piecewise with `m...`. A compatible object is any that supports the `std::tuple_size<Obj>`+`get<I>(obj)` protocol. In C++17 and up this also supports types compatible with structured bindings, like aggregates. |
+| `FieldsAre(m...)` | `argument` is a compatible object where each field matches piecewise with the matchers `m...`. A compatible object is any that supports the `std::tuple_size<Obj>`+`get<I>(obj)` protocol. In C++17 and up this also supports types compatible with structured bindings, like aggregates. |
| `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. The method `property()` must take no argument and be declared as `const`. |
| `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message.
**Notes:**
+* You can use `FieldsAre()` to match any type that supports structured
+ bindings, such as `std::tuple`, `std::pair`, `std::array`, and aggregate
+ types. For example:
+
+ ```cpp
+ std::tuple<int, std::string> my_tuple{7, "hello world"};
+ EXPECT_THAT(my_tuple, FieldsAre(Ge(0), HasSubstr("hello")));
+
+ struct MyStruct {
+ int value = 42;
+ std::string greeting = "aloha";
+ };
+ MyStruct s;
+ EXPECT_THAT(s, FieldsAre(42, "aloha"));
+ ```
+
* Don't use `Property()` against member functions that you do not own, because
taking addresses of functions is fragile and generally not part of the
contract of the function.
diff --git a/docs/gmock_cook_book.md b/docs/gmock_cook_book.md
index 8ba5c98..c6a9991 100644
--- a/docs/gmock_cook_book.md
+++ b/docs/gmock_cook_book.md
@@ -251,9 +251,9 @@
### Mocking Free Functions
-It's possible to use gMock to mock a free function (i.e. a C-style function or a
-static method). You just need to rewrite your code to use an interface (abstract
-class).
+It is not possible to directly mock a free function (i.e. a C-style function or
+a static method). If you need to, you can rewrite your code to use an interface
+(abstract class).
Instead of calling a free function (say, `OpenFile`) directly, introduce an
interface for it and have a concrete subclass that calls the free function:
@@ -268,7 +268,7 @@
class File : public FileInterface {
public:
...
- virtual bool Open(const char* path, const char* mode) {
+ bool Open(const char* path, const char* mode) override {
return OpenFile(path, mode);
}
};
@@ -512,9 +512,9 @@
class ScopedMockLog : public LogSink {
public:
...
- virtual void send(LogSeverity severity, const char* full_filename,
+ void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line, const tm* tm_time,
- const char* message, size_t message_len) {
+ const char* message, size_t message_len) override {
// We are only interested in the log severity, full file name, and
// log message.
Log(severity, full_filename, std::string(message, message_len));
@@ -2705,18 +2705,10 @@
`Notification` objects to force your asynchronous test to behave synchronously.
```cpp
-using ::testing::DoAll;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Return;
-
class MockEventDispatcher : public EventDispatcher {
MOCK_METHOD(bool, DispatchEvent, (int32), (override));
};
-ACTION_P(Notify, notification) {
- notification->Notify();
-}
-
TEST(EventQueueTest, EnqueueEventTest) {
MockEventDispatcher mock_event_dispatcher;
EventQueue event_queue(&mock_event_dispatcher);
@@ -2724,7 +2716,7 @@
const int32 kEventId = 321;
absl::Notification done;
EXPECT_CALL(mock_event_dispatcher, DispatchEvent(kEventId))
- .WillOnce(Notify(&done));
+ .WillOnce([&done] { done.Notify(); });
event_queue.EnqueueEvent(kEventId);
done.WaitForNotification();
diff --git a/docs/quickstart-bazel.md b/docs/quickstart-bazel.md
new file mode 100644
index 0000000..362ee6d
--- /dev/null
+++ b/docs/quickstart-bazel.md
@@ -0,0 +1,161 @@
+# Quickstart: Building with Bazel
+
+This tutorial aims to get you up and running with GoogleTest using the Bazel
+build system. If you're using GoogleTest for the first time or need a refresher,
+we recommend this tutorial as a starting point.
+
+## Prerequisites
+
+To complete this tutorial, you'll need:
+
+* A compatible operating system (e.g. Linux, macOS, Windows).
+* A compatible C++ compiler that supports at least C++11.
+* [Bazel](https://bazel.build/), the preferred build system used by the
+ GoogleTest team.
+
+See [Supported Platforms](platforms.md) for more information about platforms
+compatible with GoogleTest.
+
+If you don't already have Bazel installed, see the
+[Bazel installation guide](https://docs.bazel.build/versions/master/install.html).
+
+{: .callout .note}
+Note: The terminal commands in this tutorial show a Unix shell prompt, but the
+commands work on the Windows command line as well.
+
+## Set up a Bazel workspace
+
+A
+[Bazel workspace](https://docs.bazel.build/versions/master/build-ref.html#workspace)
+is a directory on your filesystem that you use to manage source files for the
+software you want to build. Each workspace directory has a text file named
+`WORKSPACE` which may be empty, or may contain references to external
+dependencies required to build the outputs.
+
+First, create a directory for your workspace:
+
+```
+$ mkdir my_workspace && cd my_workspace
+```
+
+Next, you’ll create the `WORKSPACE` file to specify dependencies. A common and
+recommended way to depend on GoogleTest is to use a
+[Bazel external dependency](https://docs.bazel.build/versions/master/external.html)
+via the
+[`http_archive` rule](https://docs.bazel.build/versions/master/repo/http.html#http_archive).
+To do this, in the root directory of your workspace (`my_workspace/`), create a
+file named `WORKSPACE` with the following contents:
+
+```
+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",
+)
+```
+
+The above configuration declares a dependency on GoogleTest which is downloaded
+as a ZIP archive from GitHub. In the above example,
+`609281088cfefc76f9d0ce82e1ff6c30cc3591e5` is the Git commit hash of the
+GoogleTest version to use; we recommend updating the hash often to point to the
+latest version.
+
+Bazel also needs a dependency on the
+[`rules_cc` repository](https://github.com/bazelbuild/rules_cc) to build C++
+code, so add the following to the `WORKSPACE` file:
+
+```
+http_archive(
+ name = "rules_cc",
+ urls = ["https://github.com/bazelbuild/rules_cc/archive/40548a2974f1aea06215272d9c2b47a14a24e556.zip"],
+ strip_prefix = "rules_cc-40548a2974f1aea06215272d9c2b47a14a24e556",
+)
+```
+
+Now you're ready to build C++ code that uses GoogleTest.
+
+## Create and run a binary
+
+With your Bazel workspace set up, you can now use GoogleTest code within your
+own project.
+
+As an example, create a file named `hello_test.cc` in your `my_workspace`
+directory with the following contents:
+
+```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 provides [assertions](primer.md#assertions) that you use to test the
+behavior of your code. The above sample includes the main GoogleTest header file
+and demonstrates some basic assertions.
+
+To build the code, create a file named `BUILD` in the same directory with the
+following contents:
+
+```
+load("@rules_cc//cc:defs.bzl", "cc_test")
+
+cc_test(
+ name = "hello_test",
+ size = "small",
+ srcs = ["hello_test.cc"],
+ deps = ["@com_google_googletest//:gtest_main"],
+)
+```
+
+This `cc_test` rule declares the C++ test binary you want to build, and links to
+GoogleTest (`//:gtest_main`) using the prefix you specified in the `WORKSPACE`
+file (`@com_google_googletest`). For more information about Bazel `BUILD` files,
+see the
+[Bazel C++ Tutorial](https://docs.bazel.build/versions/master/tutorial/cpp.html).
+
+Now you can build and run your test:
+
+<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>
+
+Congratulations! You've successfully built and run a test binary using
+GoogleTest.
+
+## Next steps
+
+* [Check out the Primer](primer.md) to start learning how to write simple
+ tests.
+* [See the code samples](samples.md) for more examples showing how to use a
+ variety of GoogleTest features.
diff --git a/docs/quickstart-cmake.md b/docs/quickstart-cmake.md
new file mode 100644
index 0000000..420f1d3
--- /dev/null
+++ b/docs/quickstart-cmake.md
@@ -0,0 +1,156 @@
+# Quickstart: Building with CMake
+
+This tutorial aims to get you up and running with GoogleTest using CMake. If
+you're using GoogleTest for the first time or need a refresher, we recommend
+this tutorial as a starting point. If your project uses Bazel, see the
+[Quickstart for Bazel](quickstart-bazel.md) instead.
+
+## Prerequisites
+
+To complete this tutorial, you'll need:
+
+* A compatible operating system (e.g. Linux, macOS, Windows).
+* A compatible C++ compiler that supports at least C++11.
+* [CMake](https://cmake.org/) and a compatible build tool for building the
+ project.
+ * Compatible build tools include
+ [Make](https://www.gnu.org/software/make/),
+ [Ninja](https://ninja-build.org/), and others - see
+ [CMake Generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
+ for more information.
+
+See [Supported Platforms](platforms.md) for more information about platforms
+compatible with GoogleTest.
+
+If you don't already have CMake installed, see the
+[CMake installation guide](https://cmake.org/install).
+
+{: .callout .note}
+Note: The terminal commands in this tutorial show a Unix shell prompt, but the
+commands work on the Windows command line as well.
+
+## Set up a project
+
+CMake uses a file named `CMakeLists.txt` to configure the build system for a
+project. You'll use this file to set up your project and declare a dependency on
+GoogleTest.
+
+First, create a directory for your project:
+
+```
+$ mkdir my_project && cd my_project
+```
+
+Next, you'll create the `CMakeLists.txt` file and declare a dependency on
+GoogleTest. There are many ways to express dependencies in the CMake ecosystem;
+in this quickstart, you'll use the
+[`FetchContent` CMake module](https://cmake.org/cmake/help/latest/module/FetchContent.html).
+To do this, in your project directory (`my_project`), create a file named
+`CMakeLists.txt` with the following contents:
+
+```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)
+```
+
+The above configuration declares a dependency on GoogleTest which is downloaded
+from GitHub. In the above example, `609281088cfefc76f9d0ce82e1ff6c30cc3591e5` is
+the Git commit hash of the GoogleTest version to use; we recommend updating the
+hash often to point to the latest version.
+
+For more information about how to create `CMakeLists.txt` files, see the
+[CMake Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html).
+
+## Create and run a binary
+
+With GoogleTest declared as a dependency, you can use GoogleTest code within
+your own project.
+
+As an example, create a file named `hello_test.cc` in your `my_project`
+directory with the following contents:
+
+```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 provides [assertions](primer.md#assertions) that you use to test the
+behavior of your code. The above sample includes the main GoogleTest header file
+and demonstrates some basic assertions.
+
+To build the code, add the following to the end of your `CMakeLists.txt` file:
+
+```cmake
+enable_testing()
+
+add_executable(
+ hello_test
+ hello_test.cc
+)
+target_link_libraries(
+ hello_test
+ gtest_main
+)
+
+include(GoogleTest)
+gtest_discover_tests(hello_test)
+```
+
+The above configuration enables testing in CMake, declares the C++ test binary
+you want to build (`hello_test`), and links it to GoogleTest (`gtest_main`). The
+last two lines enable CMake's test runner to discover the tests included in the
+binary, using the
+[`GoogleTest` CMake module](https://cmake.org/cmake/help/git-stage/module/GoogleTest.html).
+
+Now you can build and run your test:
+
+<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>
+
+Congratulations! You've successfully built and run a test binary using
+GoogleTest.
+
+## Next steps
+
+* [Check out the Primer](primer.md) to start learning how to write simple
+ tests.
+* [See the code samples](samples.md) for more examples showing how to use a
+ variety of GoogleTest features.
diff --git a/googletest/CMakeLists.txt b/googletest/CMakeLists.txt
index 1379afb..abdd98b 100644
--- a/googletest/CMakeLists.txt
+++ b/googletest/CMakeLists.txt
@@ -92,10 +92,13 @@
config_compiler_and_linker() # Defined in internal_utils.cmake.
+# Needed to set the namespace for both the export targets and the
+# alias libraries
+set(cmake_package_name GTest CACHE INTERNAL "")
+
# Create the CMake package file descriptors.
if (INSTALL_GTEST)
include(CMakePackageConfigHelpers)
- set(cmake_package_name GTest)
set(targets_export_name ${cmake_package_name}Targets CACHE INTERNAL "")
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated" CACHE INTERNAL "")
set(cmake_files_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${cmake_package_name}")
diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake
index aadbab4..8d8d60a 100644
--- a/googletest/cmake/internal_utils.cmake
+++ b/googletest/cmake/internal_utils.cmake
@@ -81,6 +81,8 @@
# Suppress "unreachable code" warning
# http://stackoverflow.com/questions/3232669 explains the issue.
set(cxx_base_flags "${cxx_base_flags} -wd4702")
+ # Ensure MSVC treats source files as UTF-8 encoded.
+ set(cxx_base_flags "${cxx_base_flags} -utf-8")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(cxx_base_flags "-Wall -Wshadow -Werror -Wconversion")
set(cxx_exception_flags "-fexceptions")
@@ -148,6 +150,7 @@
# type can be either STATIC or SHARED to denote a static or shared library.
# ARGN refers to additional arguments after 'cxx_flags'.
add_library(${name} ${type} ${ARGN})
+ add_library(${cmake_package_name}::${name} ALIAS ${name})
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h
index a7e0a3c..46fe895 100644
--- a/googletest/include/gtest/gtest-printers.h
+++ b/googletest/include/gtest/gtest-printers.h
@@ -505,24 +505,21 @@
PrintTo(ImplicitCast_<const void*>(s), os);
}
#ifdef __cpp_char8_t
-inline void PrintTo(const char8_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
+// Overloads for u8 strings.
+void PrintTo(const char8_t* s, ::std::ostream* os);
inline void PrintTo(char8_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
+ PrintTo(ImplicitCast_<const char8_t*>(s), os);
}
#endif
-inline void PrintTo(const char16_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
+// Overloads for u16 strings.
+void PrintTo(const char16_t* s, ::std::ostream* os);
inline void PrintTo(char16_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
+ PrintTo(ImplicitCast_<const char16_t*>(s), os);
}
-inline void PrintTo(const char32_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
+// Overloads for u32 strings.
+void PrintTo(const char32_t* s, ::std::ostream* os);
inline void PrintTo(char32_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
+ PrintTo(ImplicitCast_<const char32_t*>(s), os);
}
// MSVC can be configured to define wchar_t as a typedef of unsigned
@@ -558,6 +555,26 @@
PrintStringTo(s, os);
}
+// Overloads for ::std::u8string
+#ifdef __cpp_char8_t
+GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
+ PrintU8StringTo(s, os);
+}
+#endif
+
+// Overloads for ::std::u16string
+GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
+ PrintU16StringTo(s, os);
+}
+
+// Overloads for ::std::u32string
+GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
+ PrintU32StringTo(s, os);
+}
+
// Overloads for ::std::wstring.
#if GTEST_HAS_STD_WSTRING
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
@@ -805,6 +822,20 @@
GTEST_API_ void UniversalPrintArray(
const char* begin, size_t len, ::std::ostream* os);
+#ifdef __cpp_char8_t
+// This overload prints a (const) char8_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len,
+ ::std::ostream* os);
+#endif
+
+// This overload prints a (const) char16_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len,
+ ::std::ostream* os);
+
+// This overload prints a (const) char32_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len,
+ ::std::ostream* os);
+
// This overload prints a (const) wchar_t array compactly.
GTEST_API_ void UniversalPrintArray(
const wchar_t* begin, size_t len, ::std::ostream* os);
@@ -877,12 +908,55 @@
}
};
template <>
-class UniversalTersePrinter<char*> {
+class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
+};
+
+#ifdef __cpp_char8_t
+template <>
+class UniversalTersePrinter<const char8_t*> {
public:
- static void Print(char* str, ::std::ostream* os) {
- UniversalTersePrinter<const char*>::Print(str, os);
+ static void Print(const char8_t* str, ::std::ostream* os) {
+ if (str == nullptr) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::u8string(str), os);
+ }
}
};
+template <>
+class UniversalTersePrinter<char8_t*>
+ : public UniversalTersePrinter<const char8_t*> {};
+#endif
+
+template <>
+class UniversalTersePrinter<const char16_t*> {
+ public:
+ static void Print(const char16_t* str, ::std::ostream* os) {
+ if (str == nullptr) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::u16string(str), os);
+ }
+ }
+};
+template <>
+class UniversalTersePrinter<char16_t*>
+ : public UniversalTersePrinter<const char16_t*> {};
+
+template <>
+class UniversalTersePrinter<const char32_t*> {
+ public:
+ static void Print(const char32_t* str, ::std::ostream* os) {
+ if (str == nullptr) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::u32string(str), os);
+ }
+ }
+};
+template <>
+class UniversalTersePrinter<char32_t*>
+ : public UniversalTersePrinter<const char32_t*> {};
#if GTEST_HAS_STD_WSTRING
template <>
diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h
index 1088e11..681e9b7 100644
--- a/googletest/include/gtest/gtest.h
+++ b/googletest/include/gtest/gtest.h
@@ -1962,19 +1962,38 @@
// Boolean assertions. Condition can be either a Boolean expression or an
// AssertionResult. For more information on how to use AssertionResult with
// these macros see comments on that class.
-#define EXPECT_TRUE(condition) \
+#define GTEST_EXPECT_TRUE(condition) \
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
GTEST_NONFATAL_FAILURE_)
-#define EXPECT_FALSE(condition) \
+#define GTEST_EXPECT_FALSE(condition) \
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
GTEST_NONFATAL_FAILURE_)
-#define ASSERT_TRUE(condition) \
+#define GTEST_ASSERT_TRUE(condition) \
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
GTEST_FATAL_FAILURE_)
-#define ASSERT_FALSE(condition) \
+#define GTEST_ASSERT_FALSE(condition) \
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
GTEST_FATAL_FAILURE_)
+// Define these macros to 1 to omit the definition of the corresponding
+// EXPECT or ASSERT, which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_EXPECT_TRUE
+#define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
+#endif
+
+#if !GTEST_DONT_DEFINE_EXPECT_FALSE
+#define EXPECT_FALSE(condition) GTEST_EXPECT_FALSE(condition)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_TRUE
+#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_FALSE
+#define ASSERT_FALSE(condition) GTEST_ASSERT_FALSE(condition)
+#endif
+
// Macros for testing equalities and inequalities.
//
// * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2
diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h
index f3b1c8c..1c0dedd 100644
--- a/googletest/include/gtest/internal/gtest-port.h
+++ b/googletest/include/gtest/internal/gtest-port.h
@@ -1936,6 +1936,19 @@
inline bool IsXDigit(char ch) {
return isxdigit(static_cast<unsigned char>(ch)) != 0;
}
+#ifdef __cpp_char8_t
+inline bool IsXDigit(char8_t ch) {
+ return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+#endif
+inline bool IsXDigit(char16_t ch) {
+ const unsigned char low_byte = static_cast<unsigned char>(ch);
+ return ch == low_byte && isxdigit(low_byte) != 0;
+}
+inline bool IsXDigit(char32_t ch) {
+ const unsigned char low_byte = static_cast<unsigned char>(ch);
+ return ch == low_byte && isxdigit(low_byte) != 0;
+}
inline bool IsXDigit(wchar_t ch) {
const unsigned char low_byte = static_cast<unsigned char>(ch);
return ch == low_byte && isxdigit(low_byte) != 0;
diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc
index c3d6dfc..cbc395b 100644
--- a/googletest/src/gtest-death-test.cc
+++ b/googletest/src/gtest-death-test.cc
@@ -953,12 +953,12 @@
ReadAndInterpretStatusByte();
- zx_info_process_t buffer;
+ zx_info_process_v2_t buffer;
status_zx = child_process_.get_info(
- ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
+ ZX_INFO_PROCESS_V2, &buffer, sizeof(buffer), nullptr, nullptr);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
- GTEST_DEATH_TEST_CHECK_(buffer.exited);
+ GTEST_DEATH_TEST_CHECK_(buffer.flags & ZX_INFO_PROCESS_FLAG_EXITED);
set_status(buffer.return_code);
return status();
}
diff --git a/googletest/src/gtest-printers.cc b/googletest/src/gtest-printers.cc
index 20ce1b8..1b68fcb 100644
--- a/googletest/src/gtest-printers.cc
+++ b/googletest/src/gtest-printers.cc
@@ -42,12 +42,16 @@
// defines Foo.
#include "gtest/gtest-printers.h"
+
#include <stdio.h>
+
#include <cctype>
#include <cstdint>
#include <cwchar>
#include <ostream> // NOLINT
#include <string>
+#include <type_traits>
+
#include "gtest/internal/gtest-port.h"
#include "src/gtest-internal-inl.h"
@@ -103,6 +107,16 @@
*os << ">";
}
+// Helpers for widening a character to char32_t. Since the standard does not
+// specify if char / wchar_t is signed or unsigned, it is important to first
+// convert it to the unsigned type of the same width before widening it to
+// char32_t.
+template <typename CharType>
+char32_t ToChar32(CharType in) {
+ return static_cast<char32_t>(
+ static_cast<typename std::make_unsigned<CharType>::type>(in));
+}
+
} // namespace
namespace internal {
@@ -131,18 +145,15 @@
// Returns true if c is a printable ASCII character. We test the
// value of c directly instead of calling isprint(), which is buggy on
// Windows Mobile.
-inline bool IsPrintableAscii(wchar_t c) {
- return 0x20 <= c && c <= 0x7E;
-}
+inline bool IsPrintableAscii(char32_t c) { return 0x20 <= c && c <= 0x7E; }
-// Prints a wide or narrow char c as a character literal without the
-// quotes, escaping it when necessary; returns how c was formatted.
-// The template argument UnsignedChar is the unsigned version of Char,
-// which is the type of c.
-template <typename UnsignedChar, typename Char>
+// Prints c (of type char, char8_t, char16_t, char32_t, or wchar_t) as a
+// character literal without the quotes, escaping it when necessary; returns how
+// c was formatted.
+template <typename Char>
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
- wchar_t w_c = static_cast<wchar_t>(c);
- switch (w_c) {
+ const char32_t u_c = ToChar32(c);
+ switch (u_c) {
case L'\0':
*os << "\\0";
break;
@@ -174,13 +185,12 @@
*os << "\\v";
break;
default:
- if (IsPrintableAscii(w_c)) {
+ if (IsPrintableAscii(u_c)) {
*os << static_cast<char>(c);
return kAsIs;
} else {
ostream::fmtflags flags = os->flags();
- *os << "\\x" << std::hex << std::uppercase
- << static_cast<int>(static_cast<UnsignedChar>(c));
+ *os << "\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
os->flags(flags);
return kHexEscape;
}
@@ -188,9 +198,9 @@
return kSpecialEscape;
}
-// Prints a wchar_t c as if it's part of a string literal, escaping it when
+// Prints a char32_t c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
-static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
switch (c) {
case L'\'':
*os << "'";
@@ -199,26 +209,68 @@
*os << "\\\"";
return kSpecialEscape;
default:
- return PrintAsCharLiteralTo<wchar_t>(c, os);
+ return PrintAsCharLiteralTo(c, os);
}
}
+static const char* GetCharWidthPrefix(char) {
+ return "";
+}
+
+static const char* GetCharWidthPrefix(signed char) {
+ return "";
+}
+
+static const char* GetCharWidthPrefix(unsigned char) {
+ return "";
+}
+
+#ifdef __cpp_char8_t
+static const char* GetCharWidthPrefix(char8_t) {
+ return "u8";
+}
+#endif
+
+static const char* GetCharWidthPrefix(char16_t) {
+ return "u";
+}
+
+static const char* GetCharWidthPrefix(char32_t) {
+ return "U";
+}
+
+static const char* GetCharWidthPrefix(wchar_t) {
+ return "L";
+}
+
// Prints a char c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
- return PrintAsStringLiteralTo(
- static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
+ return PrintAsStringLiteralTo(ToChar32(c), os);
}
-// Prints a wide or narrow character c and its code. '\0' is printed
-// as "'\\0'", other unprintable characters are also properly escaped
-// using the standard C++ escape sequence. The template argument
-// UnsignedChar is the unsigned version of Char, which is the type of c.
-template <typename UnsignedChar, typename Char>
+#ifdef __cpp_char8_t
+static CharFormat PrintAsStringLiteralTo(char8_t c, ostream* os) {
+ return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+#endif
+
+static CharFormat PrintAsStringLiteralTo(char16_t c, ostream* os) {
+ return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+ return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+// Prints a character c (of type char, char8_t, char16_t, char32_t, or wchar_t)
+// and its code. '\0' is printed as "'\\0'", other unprintable characters are
+// also properly escaped using the standard C++ escape sequence.
+template <typename Char>
void PrintCharAndCodeTo(Char c, ostream* os) {
// First, print c as a literal in the most readable form we can find.
- *os << ((sizeof(c) > 1) ? "L'" : "'");
- const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+ *os << GetCharWidthPrefix(c) << "'";
+ const CharFormat format = PrintAsCharLiteralTo(c, os);
*os << "'";
// To aid user debugging, we also print c's code in decimal, unless
@@ -239,26 +291,21 @@
*os << ")";
}
-void PrintTo(unsigned char c, ::std::ostream* os) {
- PrintCharAndCodeTo<unsigned char>(c, os);
-}
-void PrintTo(signed char c, ::std::ostream* os) {
- PrintCharAndCodeTo<unsigned char>(c, os);
-}
+void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
+void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
-void PrintTo(wchar_t wc, ostream* os) {
- PrintCharAndCodeTo<wchar_t>(wc, os);
-}
+void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
+// TODO(dcheng): Consider making this delegate to PrintCharAndCodeTo() as well.
void PrintTo(char32_t c, ::std::ostream* os) {
*os << std::hex << "U+" << std::uppercase << std::setfill('0') << std::setw(4)
<< static_cast<uint32_t>(c);
}
// Prints the given array of characters to the ostream. CharType must be either
-// char or wchar_t.
+// char, char8_t, char16_t, char32_t, or wchar_t.
// The array starts at begin, the length is len, it may include '\0' characters
// and may not be NUL-terminated.
template <typename CharType>
@@ -268,8 +315,8 @@
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static CharFormat PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) {
- const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
- *os << kQuoteBegin;
+ const char* const quote_prefix = GetCharWidthPrefix(*begin);
+ *os << quote_prefix << "\"";
bool is_previous_hex = false;
CharFormat print_format = kAsIs;
for (size_t index = 0; index < len; ++index) {
@@ -278,7 +325,7 @@
// Previous character is of '\x..' form and this character can be
// interpreted as another hexadecimal digit in its number. Break string to
// disambiguate.
- *os << "\" " << kQuoteBegin;
+ *os << "\" " << quote_prefix << "\"";
}
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
// Remember if any characters required hex escaping.
@@ -324,22 +371,57 @@
UniversalPrintCharArray(begin, len, os);
}
+#ifdef __cpp_char8_t
+// Prints a (const) char8_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char8_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+#endif
+
+// Prints a (const) char16_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char16_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) char32_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char32_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+
// Prints a (const) wchar_t array of 'len' elements, starting at address
// 'begin'.
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
UniversalPrintCharArray(begin, len, os);
}
-// Prints the given C string to the ostream.
-void PrintTo(const char* s, ostream* os) {
+namespace {
+
+// Prints a null-terminated C-style string to the ostream.
+template <typename Char>
+void PrintCStringTo(const Char* s, ostream* os) {
if (s == nullptr) {
*os << "NULL";
} else {
*os << ImplicitCast_<const void*>(s) << " pointing to ";
- PrintCharsAsStringTo(s, strlen(s), os);
+ PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
}
}
+} // anonymous namespace
+
+void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
+
+#ifdef __cpp_char8_t
+void PrintTo(const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
+#endif
+
+void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
+
+void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
+
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
@@ -348,14 +430,7 @@
// wchar_t is implemented as a native type.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Prints the given wide C string to the ostream.
-void PrintTo(const wchar_t* s, ostream* os) {
- if (s == nullptr) {
- *os << "NULL";
- } else {
- *os << ImplicitCast_<const void*>(s) << " pointing to ";
- PrintCharsAsStringTo(s, wcslen(s), os);
- }
-}
+void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
#endif // wchar_t is native
namespace {
@@ -433,6 +508,20 @@
}
}
+#ifdef __cpp_char8_t
+void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif
+
+void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
#if GTEST_HAS_STD_WSTRING
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
diff --git a/googletest/test/BUILD.bazel b/googletest/test/BUILD.bazel
index 8f24988..b06a00a 100644
--- a/googletest/test/BUILD.bazel
+++ b/googletest/test/BUILD.bazel
@@ -83,6 +83,10 @@
copts = select({
"//:windows": ["-DGTEST_USE_OWN_TR1_TUPLE=0"],
"//conditions:default": ["-DGTEST_USE_OWN_TR1_TUPLE=1"],
+ }) + select({
+ # Ensure MSVC treats source files as UTF-8 encoded.
+ "//:msvc_compiler": ["-utf-8"],
+ "//conditions:default": [],
}),
includes = [
"googletest",
@@ -146,7 +150,6 @@
name = "gtest_unittest",
size = "small",
srcs = ["gtest_unittest.cc"],
- args = ["--heap_check=strict"],
shard_count = 2,
deps = ["//:gtest_main"],
)
diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc
index f037480..04635e5 100644
--- a/googletest/test/googletest-printers-test.cc
+++ b/googletest/test/googletest-printers-test.cc
@@ -493,6 +493,92 @@
Print(p));
}
+#ifdef __cpp_char8_t
+// const char8_t*.
+TEST(PrintU8StringTest, Const) {
+ const char8_t* p = u8"界";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u8\"\\xE7\\x95\\x8C\"", Print(p));
+}
+
+// char8_t*.
+TEST(PrintU8StringTest, NonConst) {
+ char8_t p[] = u8"世";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u8\"\\xE4\\xB8\\x96\"",
+ Print(static_cast<char8_t*>(p)));
+}
+
+// NULL u8 string.
+TEST(PrintU8StringTest, Null) {
+ const char8_t* p = nullptr;
+ EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that u8 strings are escaped properly.
+TEST(PrintU8StringTest, EscapesProperly) {
+ const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
+ EXPECT_EQ(PrintPointer(p) +
+ " pointing to u8\"'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\x7F\\xFF "
+ "hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
+ Print(p));
+}
+#endif
+
+// const char16_t*.
+TEST(PrintU16StringTest, Const) {
+ const char16_t* p = u"界";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u\"\\x754C\"", Print(p));
+}
+
+// char16_t*.
+TEST(PrintU16StringTest, NonConst) {
+ char16_t p[] = u"世";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u\"\\x4E16\"",
+ Print(static_cast<char16_t*>(p)));
+}
+
+// NULL u16 string.
+TEST(PrintU16StringTest, Null) {
+ const char16_t* p = nullptr;
+ EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that u16 strings are escaped properly.
+TEST(PrintU16StringTest, EscapesProperly) {
+ const char16_t* p = u"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
+ EXPECT_EQ(PrintPointer(p) +
+ " pointing to u\"'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\x7F\\xFF "
+ "hello \\x4E16\\x754C\"",
+ Print(p));
+}
+
+// const char32_t*.
+TEST(PrintU32StringTest, Const) {
+ const char32_t* p = U"🗺️";
+ EXPECT_EQ(PrintPointer(p) + " pointing to U\"\\x1F5FA\\xFE0F\"", Print(p));
+}
+
+// char32_t*.
+TEST(PrintU32StringTest, NonConst) {
+ char32_t p[] = U"🌌";
+ EXPECT_EQ(PrintPointer(p) + " pointing to U\"\\x1F30C\"",
+ Print(static_cast<char32_t*>(p)));
+}
+
+// NULL u32 string.
+TEST(PrintU32StringTest, Null) {
+ const char32_t* p = nullptr;
+ EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that u32 strings are escaped properly.
+TEST(PrintU32StringTest, EscapesProperly) {
+ const char32_t* p = U"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 🗺️";
+ EXPECT_EQ(PrintPointer(p) +
+ " pointing to U\"'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\x7F\\xFF "
+ "hello \\x1F5FA\\xFE0F\"",
+ Print(p));
+}
+
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
@@ -564,56 +650,6 @@
EXPECT_EQ("NULL", Print(p));
}
-#ifdef __cpp_char8_t
-// char8_t*
-TEST(PrintCharPointerTest, Char8) {
- char8_t* p = reinterpret_cast<char8_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const char8_t*
-TEST(PrintCharPointerTest, ConstChar8) {
- const char8_t* p = reinterpret_cast<const char8_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-#endif
-
-// char16_t*
-TEST(PrintCharPointerTest, Char16) {
- char16_t* p = reinterpret_cast<char16_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const char16_t*
-TEST(PrintCharPointerTest, ConstChar16) {
- const char16_t* p = reinterpret_cast<const char16_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// char32_t*
-TEST(PrintCharPointerTest, Char32) {
- char32_t* p = reinterpret_cast<char32_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const char32_t*
-TEST(PrintCharPointerTest, ConstChar32) {
- const char32_t* p = reinterpret_cast<const char32_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
// Tests printing pointers to simple, built-in types.
// bool*.
@@ -753,64 +789,70 @@
EXPECT_EQ("\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
}
-// const char array with terminating NUL.
-TEST(PrintArrayTest, ConstCharArrayWithTerminatingNul) {
+// char array with terminating NUL.
+TEST(PrintArrayTest, CharArrayWithTerminatingNul) {
const char a[] = "\0Hi";
EXPECT_EQ("\"\\0Hi\"", PrintArrayHelper(a));
}
-// const wchar_t array without terminating NUL.
+#ifdef __cpp_char8_t
+// char_t array without terminating NUL.
+TEST(PrintArrayTest, Char8ArrayWithNoTerminatingNul) {
+ // Array a contains '\0' in the middle and doesn't end with '\0'.
+ const char8_t a[] = {u8'H', u8'\0', u8'i'};
+ EXPECT_EQ("u8\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
+}
+
+// char8_t array with terminating NUL.
+TEST(PrintArrayTest, Char8ArrayWithTerminatingNul) {
+ const char8_t a[] = u8"\0世界";
+ EXPECT_EQ(
+ "u8\"\\0\\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
+ PrintArrayHelper(a));
+}
+#endif
+
+// const char16_t array without terminating NUL.
+TEST(PrintArrayTest, Char16ArrayWithNoTerminatingNul) {
+ // Array a contains '\0' in the middle and doesn't end with '\0'.
+ const char16_t a[] = {u'こ', u'\0', u'ん', u'に', u'ち', u'は'};
+ EXPECT_EQ("u\"\\x3053\\0\\x3093\\x306B\\x3061\\x306F\" (no terminating NUL)",
+ PrintArrayHelper(a));
+}
+
+// char16_t array with terminating NUL.
+TEST(PrintArrayTest, Char16ArrayWithTerminatingNul) {
+ const char16_t a[] = u"\0こんにちは";
+ EXPECT_EQ("u\"\\0\\x3053\\x3093\\x306B\\x3061\\x306F\"", PrintArrayHelper(a));
+}
+
+// char32_t array without terminating NUL.
+TEST(PrintArrayTest, Char32ArrayWithNoTerminatingNul) {
+ // Array a contains '\0' in the middle and doesn't end with '\0'.
+ const char32_t a[] = {U'👋', U'\0', U'🌌'};
+ EXPECT_EQ("U\"\\x1F44B\\0\\x1F30C\" (no terminating NUL)",
+ PrintArrayHelper(a));
+}
+
+// char32_t array with terminating NUL.
+TEST(PrintArrayTest, Char32ArrayWithTerminatingNul) {
+ const char32_t a[] = U"\0👋🌌";
+ EXPECT_EQ("U\"\\0\\x1F44B\\x1F30C\"", PrintArrayHelper(a));
+}
+
+// wchar_t array without terminating NUL.
TEST(PrintArrayTest, WCharArrayWithNoTerminatingNul) {
// Array a contains '\0' in the middle and doesn't end with '\0'.
- const wchar_t a[] = { L'H', L'\0', L'i' };
+ const wchar_t a[] = {L'H', L'\0', L'i'};
EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
}
// wchar_t array with terminating NUL.
-TEST(PrintArrayTest, WConstCharArrayWithTerminatingNul) {
+TEST(PrintArrayTest, WCharArrayWithTerminatingNul) {
const wchar_t a[] = L"\0Hi";
EXPECT_EQ("L\"\\0Hi\"", PrintArrayHelper(a));
}
-#ifdef __cpp_char8_t
-// char8_t array.
-TEST(PrintArrayTest, Char8Array) {
- const char8_t a[] = u8"Hello, world!";
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+0077, "
- "U+006F, U+0072, U+006C, U+0064, U+0021, U+0000 }",
- PrintArrayHelper(a));
-}
-#endif
-
-// char16_t array.
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintArrayTest, DISABLED_Char16Array) {
-#else
-TEST(PrintArrayTest, Char16Array) {
-#endif
- const char16_t a[] = u"Hello, 世界";
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C, U+0000 }",
- PrintArrayHelper(a));
-}
-
-// char32_t array.
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintArrayTest, DISABLED_Char32Array) {
-#else
-TEST(PrintArrayTest, Char32Array) {
-#endif
- const char32_t a[] = U"Hello, 世界";
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C, U+0000 }",
- PrintArrayHelper(a));
-}
-
// Array of objects.
TEST(PrintArrayTest, ObjectArray) {
std::string a[3] = {"Hi", "Hello", "Ni hao"};
@@ -872,41 +914,22 @@
#ifdef __cpp_char8_t
TEST(PrintStringTest, U8String) {
- std::u8string str = u8"Hello, world!";
+ std::u8string str = u8"Hello, 世界";
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+0077, "
- "U+006F, U+0072, U+006C, U+0064, U+0021 }",
- Print(str));
+ EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
}
#endif
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintStringTest, DISABLED_U16String) {
-#else
TEST(PrintStringTest, U16String) {
-#endif
std::u16string str = u"Hello, 世界";
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C }",
- Print(str));
+ EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
}
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintStringTest, DISABLED_U32String) {
-#else
TEST(PrintStringTest, U32String) {
-#endif
- std::u32string str = U"Hello, 世界";
- EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C }",
- Print(str));
+ std::u32string str = U"Hello, 🗺️";
+ EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
+ EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
}
// Tests printing types that support generic streaming (i.e. streaming
diff --git a/googletest/test/gtest_xml_test_utils.py b/googletest/test/gtest_xml_test_utils.py
index 5dd0eb9..ec42c62 100755
--- a/googletest/test/gtest_xml_test_utils.py
+++ b/googletest/test/gtest_xml_test_utils.py
@@ -70,7 +70,7 @@
self.assertEquals(expected_node.tagName, actual_node.tagName)
expected_attributes = expected_node.attributes
- actual_attributes = actual_node .attributes
+ actual_attributes = actual_node.attributes
self.assertEquals(
expected_attributes.length, actual_attributes.length,
'attribute numbers differ in element %s:\nExpected: %r\nActual: %r' % (
@@ -78,7 +78,7 @@
actual_attributes.keys()))
for i in range(expected_attributes.length):
expected_attr = expected_attributes.item(i)
- actual_attr = actual_attributes.get(expected_attr.name)
+ actual_attr = actual_attributes.get(expected_attr.name)
self.assert_(
actual_attr is not None,
'expected attribute %s not found in element %s' %