diff options
-rw-r--r-- | .github/ISSUE_TEMPLATE/90-question.md | 7 | ||||
-rw-r--r-- | .github/ISSUE_TEMPLATE/config.yml | 2 | ||||
-rw-r--r-- | BUILD.bazel | 10 | ||||
-rw-r--r-- | docs/_data/navigation.yml | 4 | ||||
-rw-r--r-- | docs/advanced.md | 76 | ||||
-rw-r--r-- | docs/faq.md | 36 | ||||
-rw-r--r-- | docs/gmock_cheat_sheet.md | 33 | ||||
-rw-r--r-- | docs/gmock_cook_book.md | 22 | ||||
-rw-r--r-- | docs/quickstart-bazel.md | 161 | ||||
-rw-r--r-- | docs/quickstart-cmake.md | 156 | ||||
-rw-r--r-- | googletest/CMakeLists.txt | 5 | ||||
-rw-r--r-- | googletest/cmake/internal_utils.cmake | 3 | ||||
-rw-r--r-- | googletest/include/gtest/gtest-printers.h | 104 | ||||
-rw-r--r-- | googletest/include/gtest/gtest.h | 27 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-port.h | 13 | ||||
-rw-r--r-- | googletest/src/gtest-death-test.cc | 6 | ||||
-rw-r--r-- | googletest/src/gtest-printers.cc | 187 | ||||
-rw-r--r-- | googletest/test/BUILD.bazel | 5 | ||||
-rw-r--r-- | googletest/test/googletest-printers-test.cc | 257 | ||||
-rwxr-xr-x | googletest/test/gtest_xml_test_utils.py | 4 |
20 files changed, 840 insertions, 278 deletions
diff --git a/.github/ISSUE_TEMPLATE/90-question.md b/.github/ISSUE_TEMPLATE/90-question.md deleted file mode 100644 index 46ec8b0a..00000000 --- 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 0086358d..3ba13e0c 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 8099642a..965c518d 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -40,7 +40,15 @@ exports_files(["LICENSE"]) 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 b79f2505..355ebc8e 100644 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -3,6 +3,10 @@ nav: 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 4103507b..fa9e5bc2 100644 --- a/docs/advanced.md +++ b/docs/advanced.md @@ -813,7 +813,8 @@ initialized from the command-line flag `--gtest_death_test_style`). 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 @@ class FooTest : public testing::Test { } // 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 @@ First, you subclass the `::testing::Environment` class to define a test 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 @@ The following statement will instantiate tests from the `FooTest` test suite 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 @@ INSTANTIATE_TEST_SUITE_P(InstantiationName, 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: - -```c++ -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest); -``` +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. -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: +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: -* `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 @@ Here's an example: ```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 @@ Here's an example: } // 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 da443e33..40712321 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -60,9 +60,10 @@ the rule. ## 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 @@ and `ASSERT_XX()` macros. Therefore we only do it where it's most needed (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 @@ whether the code is under test. ## 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 723cb7e1..90be4a3e 100644 --- a/docs/gmock_cheat_sheet.md +++ b/docs/gmock_cheat_sheet.md @@ -123,7 +123,7 @@ TEST(BarTest, DoesThis) { .WillRepeatedly(Return("Category 5")); // ... other expectations ... - EXPECT_EQ("good", MyProductionFunction(&foo)); // #5 + EXPECT_EQ(MyProductionFunction(&foo), "good"); // #5 } // #6 ``` @@ -162,8 +162,8 @@ Example usage: 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 @@ messages, you can use: 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 @@ messages, you can use: | `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 8ba5c989..c6a99912 100644 --- a/docs/gmock_cook_book.md +++ b/docs/gmock_cook_book.md @@ -251,9 +251,9 @@ tests. ### 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 FileInterface { 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 @@ The trick is to redispatch the method in the mock class: 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 @@ behavior nondeterministic. A better way is to use gMock actions and `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 @@ TEST(EventQueueTest, EnqueueEventTest) { 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 00000000..362ee6d0 --- /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 00000000..420f1d3a --- /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 1379afb9..abdd98b7 100644 --- a/googletest/CMakeLists.txt +++ b/googletest/CMakeLists.txt @@ -92,10 +92,13 @@ include(cmake/internal_utils.cmake) 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 aadbab47..8d8d60a8 100644 --- a/googletest/cmake/internal_utils.cmake +++ b/googletest/cmake/internal_utils.cmake @@ -81,6 +81,8 @@ macro(config_compiler_and_linker) # 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 @@ function(cxx_library_with_type name type cxx_flags) # 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 a7e0a3c9..46fe8950 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -505,24 +505,21 @@ inline void PrintTo(unsigned char* s, ::std::ostream* os) { 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); -} -inline void PrintTo(const char32_t* s, ::std::ostream* os) { - PrintTo(ImplicitCast_<const void*>(s), os); + PrintTo(ImplicitCast_<const char16_t*>(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 @@ inline void PrintTo(const ::std::string& s, ::std::ostream* os) { 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 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { 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 @@ class UniversalTersePrinter<const char*> { } }; 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(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(char* str, ::std::ostream* os) { - UniversalTersePrinter<const char*>::Print(str, os); + 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 1088e110..681e9b77 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -1962,19 +1962,38 @@ class TestWithParam : public Test, public WithParamInterface<T> { // 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 f3b1c8c8..1c0deddd 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -1936,6 +1936,19 @@ inline bool IsUpper(char ch) { 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 c3d6dfcc..cbc395b2 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -953,12 +953,12 @@ int FuchsiaDeathTest::Wait() { 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 20ce1b86..1b68fcb5 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 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, *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 @@ enum CharFormat { // 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 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { *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 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { 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 @@ static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { *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); +} + +#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); } -// 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> +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 @@ void PrintCharAndCodeTo(Char c, ostream* os) { *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_HWADDRESS_ 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 @@ static CharFormat PrintCharsAsStringTo( // 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 @@ void UniversalPrintArray(const char* begin, size_t len, ostream* os) { 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 @@ void PrintTo(const char* s, ostream* os) { // 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 @@ void PrintStringTo(const ::std::string& s, ostream* os) { } } +#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 8f24988a..b06a00a1 100644 --- a/googletest/test/BUILD.bazel +++ b/googletest/test/BUILD.bazel @@ -83,6 +83,10 @@ cc_test( 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 @@ cc_test( 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 f037480b..04635e58 100644 --- a/googletest/test/googletest-printers-test.cc +++ b/googletest/test/googletest-printers-test.cc @@ -493,6 +493,92 @@ TEST(PrintCStringTest, EscapesProperly) { 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 @@ TEST(PrintCharPointerTest, ConstUnsignedChar) { 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,62 +789,68 @@ TEST(PrintArrayTest, CharArrayWithNoTerminatingNul) { 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. -TEST(PrintArrayTest, WCharArrayWithNoTerminatingNul) { +#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 wchar_t a[] = { L'H', L'\0', L'i' }; - EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a)); + const char8_t a[] = {u8'H', u8'\0', u8'i'}; + EXPECT_EQ("u8\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a)); } -// wchar_t array with terminating NUL. -TEST(PrintArrayTest, WConstCharArrayWithTerminatingNul) { - 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!"; +// char8_t array with terminating NUL. +TEST(PrintArrayTest, Char8ArrayWithTerminatingNul) { + const char8_t a[] = u8"\0世界"; 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 }", + "u8\"\\0\\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", 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)); +// 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)); } -// 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)); +// 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'}; + EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a)); +} + +// wchar_t array with terminating NUL. +TEST(PrintArrayTest, WCharArrayWithTerminatingNul) { + const wchar_t a[] = L"\0Hi"; + EXPECT_EQ("L\"\\0Hi\"", PrintArrayHelper(a)); } // Array of objects. @@ -872,41 +914,22 @@ TEST(PrintWideStringTest, StringAmbiguousHex) { #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 5dd0eb92..ec42c62c 100755 --- a/googletest/test/gtest_xml_test_utils.py +++ b/googletest/test/gtest_xml_test_utils.py @@ -70,7 +70,7 @@ class GTestXMLTestCase(gtest_test_utils.TestCase): 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 @@ class GTestXMLTestCase(gtest_test_utils.TestCase): 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' % |