diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..05df2ca
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,25 @@
+name: Build and test cpu
+on:
+  push:
+    paths-ignore:
+      - '**.md'
+      - 'LICENSE'
+  pull_request:
+    paths:
+      - '**.md'
+      - 'LICENSE'
+
+jobs:
+  build:
+    name: Build
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v3
+      with:
+        submodules: recursive
+
+    - name: Build
+      run: make
+
+    - name: Test cpu
+      run: make test-cpp
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..98e980a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,46 @@
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+build/
+build_debug/
+
+.vscode/
+
+# python
+*.egg-info
+*.pyc
+
+# onnx model
+*.onnx
+*.pb
+*.npy
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..82cff62
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "3rd-party/googletest"]
+	path = 3rd-party/googletest
+	url = git@github.com:google/googletest.git
+[submodule "3rd-party/nlohmann_json_cmake_fetchcontent"]
+	path = 3rd-party/nlohmann_json_cmake_fetchcontent
+	url = git@github.com:ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git
diff --git a/3rd-party/googletest/.clang-format b/3rd-party/googletest/.clang-format
new file mode 100644
index 0000000..5b9bfe6
--- /dev/null
+++ b/3rd-party/googletest/.clang-format
@@ -0,0 +1,4 @@
+# Run manually to reformat a file:
+# clang-format -i --style=file <file>
+Language:        Cpp
+BasedOnStyle:  Google
diff --git a/3rd-party/googletest/.github/ISSUE_TEMPLATE/00-bug_report.yml b/3rd-party/googletest/.github/ISSUE_TEMPLATE/00-bug_report.yml
new file mode 100644
index 0000000..586779a
--- /dev/null
+++ b/3rd-party/googletest/.github/ISSUE_TEMPLATE/00-bug_report.yml
@@ -0,0 +1,53 @@
+name: Bug Report
+description: Let us know that something does not work as expected.
+title: "[Bug]: Please title this bug report"
+body:
+  - type: textarea
+    id: what-happened
+    attributes:
+      label: Describe the issue
+      description: What happened, and what did you expect to happen?
+    validations:
+      required: true
+  - type: textarea
+    id: steps
+    attributes:
+      label: Steps to reproduce the problem
+      description: It is important that we are able to reproduce the problem that you are experiencing. Please provide all code and relevant steps to reproduce the problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the problem are also helpful.
+    validations:
+      required: true
+  - type: textarea
+    id: version
+    attributes:
+      label: What version of GoogleTest are you using?
+      description: Please include the output of `git rev-parse HEAD` or the GoogleTest release version number that you are using.
+    validations:
+      required: true
+  - type: textarea
+    id: os
+    attributes:
+      label: What operating system and version are you using?
+      description: If you are using a Linux distribution please include the name and version of the distribution as well.
+    validations:
+      required: true
+  - type: textarea
+    id: compiler
+    attributes:
+      label: What compiler and version are you using?
+      description: Please include the output of `gcc -v` or `clang -v`, or the equivalent for your compiler.
+    validations:
+      required: true
+  - type: textarea
+    id: buildsystem
+    attributes:
+      label: What build system are you using?
+      description: Please include the output of `bazel --version` or `cmake --version`, or the equivalent for your build system.
+    validations:
+      required: true
+  - type: textarea
+    id: additional
+    attributes:
+      label: Additional context
+      description: Add any other context about the problem here.
+    validations:
+      required: false
diff --git a/3rd-party/googletest/.github/ISSUE_TEMPLATE/10-feature_request.yml b/3rd-party/googletest/.github/ISSUE_TEMPLATE/10-feature_request.yml
new file mode 100644
index 0000000..f3bbc09
--- /dev/null
+++ b/3rd-party/googletest/.github/ISSUE_TEMPLATE/10-feature_request.yml
@@ -0,0 +1,33 @@
+name: Feature request
+description: Propose a new feature.
+title: "[FR]: Please title this feature request"
+labels: "enhancement"
+body:
+  - type: textarea
+    id: version
+    attributes:
+      label: Does the feature exist in the most recent commit?
+      description: We recommend using the latest commit from GitHub in your projects.
+    validations:
+      required: true
+  - type: textarea
+    id: why
+    attributes:
+      label: Why do we need this feature?
+      description: Ideally, explain why a combination of existing features cannot be used instead.
+    validations:
+      required: true
+  - type: textarea
+    id: proposal
+    attributes:
+      label: Describe the proposal.
+      description: Include a detailed description of the feature, with usage examples.
+    validations:
+      required: true
+  - type: textarea
+    id: platform
+    attributes:
+      label: Is the feature specific to an operating system, compiler, or build system version?
+      description: If it is, please specify which versions.
+    validations:
+      required: true
diff --git a/3rd-party/googletest/.github/ISSUE_TEMPLATE/config.yml b/3rd-party/googletest/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..65170d1
--- /dev/null
+++ b/3rd-party/googletest/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+    - name: Get Help
+      url: https://github.com/google/googletest/discussions
+      about: Please ask and answer questions here.
diff --git a/3rd-party/googletest/.gitignore b/3rd-party/googletest/.gitignore
new file mode 100644
index 0000000..f0df39d
--- /dev/null
+++ b/3rd-party/googletest/.gitignore
@@ -0,0 +1,89 @@
+# Ignore CI build directory
+build/
+xcuserdata
+cmake-build-debug/
+.idea/
+bazel-bin
+bazel-genfiles
+bazel-googletest
+bazel-out
+bazel-testlogs
+MODULE.bazel.lock
+# python
+*.pyc
+
+# Visual Studio files
+.vs
+*.sdf
+*.opensdf
+*.VC.opendb
+*.suo
+*.user
+_ReSharper.Caches/
+Win32-Debug/
+Win32-Release/
+x64-Debug/
+x64-Release/
+
+# VSCode files
+.cache/
+cmake-variants.yaml
+
+# Ignore autoconf / automake files
+Makefile.in
+aclocal.m4
+configure
+build-aux/
+autom4te.cache/
+googletest/m4/libtool.m4
+googletest/m4/ltoptions.m4
+googletest/m4/ltsugar.m4
+googletest/m4/ltversion.m4
+googletest/m4/lt~obsolete.m4
+googlemock/m4
+
+# Ignore generated directories.
+googlemock/fused-src/
+googletest/fused-src/
+
+# macOS files
+.DS_Store
+googletest/.DS_Store
+googletest/xcode/.DS_Store
+
+# Ignore cmake generated directories and files.
+CMakeFiles
+CTestTestfile.cmake
+Makefile
+cmake_install.cmake
+googlemock/CMakeFiles
+googlemock/CTestTestfile.cmake
+googlemock/Makefile
+googlemock/cmake_install.cmake
+googlemock/gtest
+/bin
+/googlemock/gmock.dir
+/googlemock/gmock_main.dir
+/googlemock/RUN_TESTS.vcxproj.filters
+/googlemock/RUN_TESTS.vcxproj
+/googlemock/INSTALL.vcxproj.filters
+/googlemock/INSTALL.vcxproj
+/googlemock/gmock_main.vcxproj.filters
+/googlemock/gmock_main.vcxproj
+/googlemock/gmock.vcxproj.filters
+/googlemock/gmock.vcxproj
+/googlemock/gmock.sln
+/googlemock/ALL_BUILD.vcxproj.filters
+/googlemock/ALL_BUILD.vcxproj
+/lib
+/Win32
+/ZERO_CHECK.vcxproj.filters
+/ZERO_CHECK.vcxproj
+/RUN_TESTS.vcxproj.filters
+/RUN_TESTS.vcxproj
+/INSTALL.vcxproj.filters
+/INSTALL.vcxproj
+/googletest-distribution.sln
+/CMakeCache.txt
+/ALL_BUILD.vcxproj.filters
+/ALL_BUILD.vcxproj
diff --git a/3rd-party/googletest/BUILD.bazel b/3rd-party/googletest/BUILD.bazel
new file mode 100644
index 0000000..0306468
--- /dev/null
+++ b/3rd-party/googletest/BUILD.bazel
@@ -0,0 +1,236 @@
+# Copyright 2017 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#   Bazel Build for Google C++ Testing Framework(Google Test)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+exports_files(["LICENSE"])
+
+config_setting(
+    name = "qnx",
+    constraint_values = ["@platforms//os:qnx"],
+)
+
+config_setting(
+    name = "windows",
+    constraint_values = ["@platforms//os:windows"],
+)
+
+config_setting(
+    name = "freebsd",
+    constraint_values = ["@platforms//os:freebsd"],
+)
+
+config_setting(
+    name = "openbsd",
+    constraint_values = ["@platforms//os:openbsd"],
+)
+
+# NOTE: Fuchsia is not an officially supported platform.
+config_setting(
+    name = "fuchsia",
+    constraint_values = ["@platforms//os:fuchsia"],
+)
+
+config_setting(
+    name = "msvc_compiler",
+    flag_values = {
+        "@bazel_tools//tools/cpp:compiler": "msvc-cl",
+    },
+    visibility = [":__subpackages__"],
+)
+
+config_setting(
+    name = "has_absl",
+    values = {"define": "absl=1"},
+)
+
+# Library that defines the FRIEND_TEST macro.
+cc_library(
+    name = "gtest_prod",
+    hdrs = ["googletest/include/gtest/gtest_prod.h"],
+    includes = ["googletest/include"],
+)
+
+# Google Test including Google Mock
+cc_library(
+    name = "gtest",
+    srcs = glob(
+        include = [
+            "googletest/src/*.cc",
+            "googletest/src/*.h",
+            "googletest/include/gtest/**/*.h",
+            "googlemock/src/*.cc",
+            "googlemock/include/gmock/**/*.h",
+        ],
+        exclude = [
+            "googletest/src/gtest-all.cc",
+            "googletest/src/gtest_main.cc",
+            "googlemock/src/gmock-all.cc",
+            "googlemock/src/gmock_main.cc",
+        ],
+    ),
+    hdrs = glob([
+        "googletest/include/gtest/*.h",
+        "googlemock/include/gmock/*.h",
+    ]),
+    copts = select({
+        ":qnx": [],
+        ":windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
+    defines = select({
+        ":has_absl": ["GTEST_HAS_ABSL=1"],
+        "//conditions:default": [],
+    }),
+    features = select({
+        ":windows": ["windows_export_all_symbols"],
+        "//conditions:default": [],
+    }),
+    includes = [
+        "googlemock",
+        "googlemock/include",
+        "googletest",
+        "googletest/include",
+    ],
+    linkopts = select({
+        ":qnx": ["-lregex"],
+        ":windows": [],
+        ":freebsd": [
+            "-lm",
+            "-pthread",
+        ],
+        ":openbsd": [
+            "-lm",
+            "-pthread",
+        ],
+        "//conditions:default": ["-pthread"],
+    }),
+    deps = select({
+        ":has_absl": [
+            "@abseil-cpp//absl/container:flat_hash_set",
+            "@abseil-cpp//absl/debugging:failure_signal_handler",
+            "@abseil-cpp//absl/debugging:stacktrace",
+            "@abseil-cpp//absl/debugging:symbolize",
+            "@abseil-cpp//absl/flags:flag",
+            "@abseil-cpp//absl/flags:parse",
+            "@abseil-cpp//absl/flags:reflection",
+            "@abseil-cpp//absl/flags:usage",
+            "@abseil-cpp//absl/strings",
+            "@abseil-cpp//absl/types:any",
+            "@abseil-cpp//absl/types:optional",
+            "@abseil-cpp//absl/types:variant",
+            "@re2//:re2",
+        ],
+        "//conditions:default": [],
+    }) + select({
+        # `gtest-death-test.cc` has `EXPECT_DEATH` that spawns a process,
+        # expects it to crash and inspects its logs with the given matcher,
+        # so that's why these libraries are needed.
+        # Otherwise, builds targeting Fuchsia would fail to compile.
+        ":fuchsia": [
+            "@fuchsia_sdk//pkg/fdio",
+            "@fuchsia_sdk//pkg/syslog",
+            "@fuchsia_sdk//pkg/zx",
+        ],
+        "//conditions:default": [],
+    }),
+)
+
+cc_library(
+    name = "gtest_main",
+    srcs = ["googlemock/src/gmock_main.cc"],
+    features = select({
+        ":windows": ["windows_export_all_symbols"],
+        "//conditions:default": [],
+    }),
+    deps = [":gtest"],
+)
+
+# The following rules build samples of how to use gTest.
+cc_library(
+    name = "gtest_sample_lib",
+    srcs = [
+        "googletest/samples/sample1.cc",
+        "googletest/samples/sample2.cc",
+        "googletest/samples/sample4.cc",
+    ],
+    hdrs = [
+        "googletest/samples/prime_tables.h",
+        "googletest/samples/sample1.h",
+        "googletest/samples/sample2.h",
+        "googletest/samples/sample3-inl.h",
+        "googletest/samples/sample4.h",
+    ],
+    features = select({
+        ":windows": ["windows_export_all_symbols"],
+        "//conditions:default": [],
+    }),
+)
+
+cc_test(
+    name = "gtest_samples",
+    size = "small",
+    # All Samples except:
+    #   sample9 (main)
+    #   sample10 (main and takes a command line option and needs to be separate)
+    srcs = [
+        "googletest/samples/sample1_unittest.cc",
+        "googletest/samples/sample2_unittest.cc",
+        "googletest/samples/sample3_unittest.cc",
+        "googletest/samples/sample4_unittest.cc",
+        "googletest/samples/sample5_unittest.cc",
+        "googletest/samples/sample6_unittest.cc",
+        "googletest/samples/sample7_unittest.cc",
+        "googletest/samples/sample8_unittest.cc",
+    ],
+    linkstatic = 0,
+    deps = [
+        "gtest_sample_lib",
+        ":gtest_main",
+    ],
+)
+
+cc_test(
+    name = "sample9_unittest",
+    size = "small",
+    srcs = ["googletest/samples/sample9_unittest.cc"],
+    deps = [":gtest"],
+)
+
+cc_test(
+    name = "sample10_unittest",
+    size = "small",
+    srcs = ["googletest/samples/sample10_unittest.cc"],
+    deps = [":gtest"],
+)
diff --git a/3rd-party/googletest/CMakeLists.txt b/3rd-party/googletest/CMakeLists.txt
new file mode 100644
index 0000000..737b720
--- /dev/null
+++ b/3rd-party/googletest/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Note: CMake support is community-based. The maintainers do not use CMake
+# internally.
+
+cmake_minimum_required(VERSION 3.13)
+
+project(googletest-distribution)
+set(GOOGLETEST_VERSION 1.15.0)
+
+if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+enable_testing()
+
+include(CMakeDependentOption)
+include(GNUInstallDirs)
+
+# Note that googlemock target already builds googletest.
+option(BUILD_GMOCK "Builds the googlemock subproject" ON)
+option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
+option(GTEST_HAS_ABSL "Use Abseil and RE2. Requires Abseil and RE2 to be separately added to the build." OFF)
+
+if(GTEST_HAS_ABSL)
+  if(NOT TARGET absl::base)
+    find_package(absl REQUIRED)
+  endif()
+  if(NOT TARGET re2::re2)
+    find_package(re2 REQUIRED)
+  endif()
+endif()
+
+if(BUILD_GMOCK)
+  add_subdirectory( googlemock )
+else()
+  add_subdirectory( googletest )
+endif()
diff --git a/3rd-party/googletest/CONTRIBUTING.md b/3rd-party/googletest/CONTRIBUTING.md
new file mode 100644
index 0000000..ab5a47b
--- /dev/null
+++ b/3rd-party/googletest/CONTRIBUTING.md
@@ -0,0 +1,141 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your patches! Before we can take them, we have to jump a
+couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement
+(CLA).
+
+*   If you are an individual writing original source code and you're sure you
+    own the intellectual property, then you'll need to sign an
+    [individual CLA](https://developers.google.com/open-source/cla/individual).
+*   If you work for a company that wants to allow you to contribute your work,
+    then you'll need to sign a
+    [corporate CLA](https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Are you a Googler?
+
+If you are a Googler, please make an attempt to submit an internal contribution
+rather than a GitHub Pull Request. If you are not able to submit internally, a
+PR is acceptable as an alternative.
+
+## Contributing A Patch
+
+1.  Submit an issue describing your proposed change to the
+    [issue tracker](https://github.com/google/googletest/issues).
+2.  Please don't mix more than one logical change per submittal, because it
+    makes the history hard to follow. If you want to make a change that doesn't
+    have a corresponding issue in the issue tracker, please create one.
+3.  Also, coordinate with team members that are listed on the issue in question.
+    This ensures that work isn't being duplicated and communicating your plan
+    early also generally leads to better patches.
+4.  If your proposed change is accepted, and you haven't already done so, sign a
+    Contributor License Agreement
+    ([see details above](#contributor-license-agreements)).
+5.  Fork the desired repo, develop and test your code changes.
+6.  Ensure that your code adheres to the existing style in the sample to which
+    you are contributing.
+7.  Ensure that your code has an appropriate set of unit tests which all pass.
+8.  Submit a pull request.
+
+## The Google Test and Google Mock Communities
+
+The Google Test community exists primarily through the
+[discussion group](https://groups.google.com/group/googletestframework) and the
+GitHub repository. Likewise, the Google Mock community exists primarily through
+their own [discussion group](https://groups.google.com/group/googlemock). You
+are definitely encouraged to contribute to the discussion and you can also help
+us to keep the effectiveness of the group high by following and promoting the
+guidelines listed here.
+
+### Please Be Friendly
+
+Showing courtesy and respect to others is a vital part of the Google culture,
+and we strongly encourage everyone participating in Google Test development to
+join us in accepting nothing less. Of course, being courteous is not the same as
+failing to constructively disagree with each other, but it does mean that we
+should be respectful of each other when enumerating the 42 technical reasons
+that a particular proposal may not be the best choice. There's never a reason to
+be antagonistic or dismissive toward anyone who is sincerely trying to
+contribute to a discussion.
+
+Sure, C++ testing is serious business and all that, but it's also a lot of fun.
+Let's keep it that way. Let's strive to be one of the friendliest communities in
+all of open source.
+
+As always, discuss Google Test in the official GoogleTest discussion group. You
+don't have to actually submit code in order to sign up. Your participation
+itself is a valuable contribution.
+
+## Style
+
+To keep the source consistent, readable, diffable and easy to merge, we use a
+fairly rigid coding style, as defined by the
+[google-styleguide](https://github.com/google/styleguide) project. All patches
+will be expected to conform to the style outlined
+[here](https://google.github.io/styleguide/cppguide.html). Use
+[.clang-format](https://github.com/google/googletest/blob/main/.clang-format) to
+check your formatting.
+
+## Requirements for Contributors
+
+If you plan to contribute a patch, you need to build Google Test, Google Mock,
+and their own tests from a git checkout, which has further requirements:
+
+*   [Python](https://www.python.org/) v3.6 or newer (for running some of the
+    tests and re-generating certain source files from templates)
+*   [CMake](https://cmake.org/) v2.8.12 or newer
+
+## Developing Google Test and Google Mock
+
+This section discusses how to make your own changes to the Google Test project.
+
+### Testing Google Test and Google Mock Themselves
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test and GoogleMock's own
+tests. For that you can use CMake:
+
+```
+mkdir mybuild
+cd mybuild
+cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR}
+```
+
+To choose between building only Google Test or Google Mock, you may modify your
+cmake command to be one of each
+
+```
+cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests
+cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests
+```
+
+Make sure you have Python installed, as some of Google Test's tests are written
+in Python. If the cmake command complains about not being able to find Python
+(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it
+explicitly where your Python executable can be found:
+
+```
+cmake -DPYTHON_EXECUTABLE=path/to/python ...
+```
+
+Next, you can build Google Test and / or Google Mock and all desired tests. On
+\*nix, this is usually done by
+
+```
+make
+```
+
+To run the tests, do
+
+```
+make test
+```
+
+All tests should pass.
diff --git a/3rd-party/googletest/CONTRIBUTORS b/3rd-party/googletest/CONTRIBUTORS
new file mode 100644
index 0000000..ccea41e
--- /dev/null
+++ b/3rd-party/googletest/CONTRIBUTORS
@@ -0,0 +1,66 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Testing Framework project.  People
+# who commit code to the project are encouraged to add their names
+# here.  Please keep the list sorted by first names.
+
+Ajay Joshi <jaj@google.com>
+Balázs Dán <balazs.dan@gmail.com>
+Benoit Sigoure <tsuna@google.com>
+Bharat Mediratta <bharat@menalto.com>
+Bogdan Piloca <boo@google.com>
+Chandler Carruth <chandlerc@google.com>
+Chris Prince <cprince@google.com>
+Chris Taylor <taylorc@google.com>
+Dan Egnor <egnor@google.com>
+Dave MacLachlan <dmaclach@gmail.com>
+David Anderson <danderson@google.com>
+Dean Sturtevant
+Eric Roman <eroman@chromium.org>
+Gene Volovich <gv@cite.com>
+Hady Zalek <hady.zalek@gmail.com>
+Hal Burch <gmock@hburch.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jim Keller <jimkeller@google.com>
+Joe Walnes <joe@truemesh.com>
+Jon Wray <jwray@google.com>
+Jói Sigurðsson <joi@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kenton Varda <kenton@google.com>
+Kostya Serebryany <kcc@google.com>
+Krystian Kuzniarek <krystian.kuzniarek@gmail.com>
+Lev Makhlis
+Manuel Klimek <klimek@google.com>
+Mario Tanev <radix@google.com>
+Mark Paskin
+Markus Heule <markus.heule@gmail.com>
+Martijn Vels <mvels@google.com>
+Matthew Simmons <simmonmt@acm.org>
+Mika Raento <mikie@iki.fi>
+Mike Bland <mbland@google.com>
+Miklós Fazekas <mfazekas@szemafor.com>
+Neal Norwitz <nnorwitz@gmail.com>
+Nermin Ozkiranartli <nermin@google.com>
+Owen Carlsen <ocarlsen@google.com>
+Paneendra Ba <paneendra@google.com>
+Pasi Valminen <pasi.valminen@gmail.com>
+Patrick Hanna <phanna@google.com>
+Patrick Riley <pfr@google.com>
+Paul Menage <menage@google.com>
+Peter Kaminski <piotrk@google.com>
+Piotr Kaminski <piotrk@google.com>
+Preston Jackson <preston.a.jackson@gmail.com>
+Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
+Russ Cox <rsc@google.com>
+Russ Rufer <russ@pentad.com>
+Sean Mcafee <eefacm@gmail.com>
+Sigurður Ásgeirsson <siggi@google.com>
+Soyeon Kim <sxshx818@naver.com>
+Sverre Sundsdal <sundsdal@gmail.com>
+Szymon Sobik <sobik.szymon@gmail.com>
+Takeshi Yoshino <tyoshino@google.com>
+Tracy Bialik <tracy@pentad.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Wolfgang Klier <wklier@google.com>
+Zhanyong Wan <wan@google.com>
diff --git a/3rd-party/googletest/LICENSE b/3rd-party/googletest/LICENSE
new file mode 100644
index 0000000..1941a11
--- /dev/null
+++ b/3rd-party/googletest/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/3rd-party/googletest/MODULE.bazel b/3rd-party/googletest/MODULE.bazel
new file mode 100644
index 0000000..8df73fb
--- /dev/null
+++ b/3rd-party/googletest/MODULE.bazel
@@ -0,0 +1,59 @@
+# Copyright 2024 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# https://bazel.build/external/overview#bzlmod
+
+module(
+    name = "googletest",
+    version = "head",
+    compatibility_level = 1,
+)
+
+# Only direct dependencies need to be listed below.
+# Please keep the versions in sync with the versions in the WORKSPACE file.
+
+bazel_dep(name = "abseil-cpp",
+          version = "20240116.2")
+
+bazel_dep(name = "platforms",
+          version = "0.0.10")
+
+bazel_dep(name = "re2",
+          version = "2024-07-02")
+
+bazel_dep(name = "rules_python",
+          version = "0.29.0")
+
+
+fake_fuchsia_sdk = use_repo_rule("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
+fake_fuchsia_sdk(name = "fuchsia_sdk")
+
+# https://github.com/bazelbuild/rules_python/blob/main/BZLMOD_SUPPORT.md#default-toolchain-is-not-the-local-system-python
+register_toolchains("@bazel_tools//tools/python:autodetecting_toolchain")
diff --git a/3rd-party/googletest/README.md b/3rd-party/googletest/README.md
new file mode 100644
index 0000000..f50c670
--- /dev/null
+++ b/3rd-party/googletest/README.md
@@ -0,0 +1,142 @@
+# GoogleTest
+
+### Announcements
+
+#### Live at Head
+
+GoogleTest now follows the
+[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
+We recommend
+[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
+We do publish occasional semantic versions, tagged with
+`v${major}.${minor}.${patch}` (e.g. `v1.15.0`).
+
+#### Documentation Updates
+
+Our documentation is now live on GitHub Pages at
+https://google.github.io/googletest/. We recommend browsing the documentation on
+GitHub Pages rather than directly in the repository.
+
+#### Release 1.15.0
+
+[Release 1.15.0](https://github.com/google/googletest/releases/tag/v1.15.0) is
+now available.
+
+The 1.15.x branch requires at least C++14.
+
+#### Continuous Integration
+
+We use Google's internal systems for continuous integration.
+
+#### Coming Soon
+
+*   We are planning to take a dependency on
+    [Abseil](https://github.com/abseil/abseil-cpp).
+
+## Welcome to **GoogleTest**, Google's C++ test framework!
+
+This repository is a merger of the formerly separate GoogleTest and GoogleMock
+projects. These were so closely related that it makes sense to maintain and
+release them together.
+
+### Getting Started
+
+See the [GoogleTest User's Guide](https://google.github.io/googletest/) for
+documentation. We recommend starting with the
+[GoogleTest Primer](https://google.github.io/googletest/primer.html).
+
+More information about building GoogleTest can be found at
+[googletest/README.md](googletest/README.md).
+
+## Features
+
+*   xUnit test framework: \
+    Googletest is based on the [xUnit](https://en.wikipedia.org/wiki/XUnit)
+    testing framework, a popular architecture for unit testing
+*   Test discovery: \
+    Googletest automatically discovers and runs your tests, eliminating the need
+    to manually register your tests
+*   Rich set of assertions: \
+    Googletest provides a variety of assertions, such as equality, inequality,
+    exceptions, and more, making it easy to test your code
+*   User-defined assertions: \
+    You can define your own assertions with Googletest, making it simple to
+    write tests that are specific to your code
+*   Death tests: \
+    Googletest supports death tests, which verify that your code exits in a
+    certain way, making it useful for testing error-handling code
+*   Fatal and non-fatal failures: \
+    You can specify whether a test failure should be treated as fatal or
+    non-fatal with Googletest, allowing tests to continue running even if a
+    failure occurs
+*   Value-parameterized tests: \
+    Googletest supports value-parameterized tests, which run multiple times with
+    different input values, making it useful for testing functions that take
+    different inputs
+*   Type-parameterized tests: \
+    Googletest also supports type-parameterized tests, which run with different
+    data types, making it useful for testing functions that work with different
+    data types
+*   Various options for running tests: \
+    Googletest provides many options for running tests including running
+    individual tests, running tests in a specific order and running tests in
+    parallel
+
+## Supported Platforms
+
+GoogleTest follows Google's
+[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support).
+See
+[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md)
+for a list of currently supported versions of compilers, platforms, and build
+tools.
+
+## Who Is Using GoogleTest?
+
+In addition to many internal projects at Google, GoogleTest is also used by the
+following notable projects:
+
+*   The [Chromium projects](https://www.chromium.org/) (behind the Chrome
+    browser and Chrome OS).
+*   The [LLVM](https://llvm.org/) compiler.
+*   [Protocol Buffers](https://github.com/google/protobuf), Google's data
+    interchange format.
+*   The [OpenCV](https://opencv.org/) computer vision library.
+
+## Related Open Source Projects
+
+[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
+automated test-runner and Graphical User Interface with powerful features for
+Windows and Linux platforms.
+
+[GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that
+runs your test binary, allows you to track its progress via a progress bar, and
+displays a list of test failures. Clicking on one shows failure text. GoogleTest
+UI is written in C#.
+
+[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
+listener for GoogleTest that implements the
+[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
+result output. If your test runner understands TAP, you may find it useful.
+
+[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
+runs tests from your binary in parallel to provide significant speed-up.
+
+[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
+is a VS Code extension allowing to view GoogleTest in a tree view and run/debug
+your tests.
+
+[C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS
+Code extension allowing to view GoogleTest in a tree view and run/debug your
+tests.
+
+[Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser
+that generates stub code for GoogleTest.
+
+## Contributing Changes
+
+Please read
+[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/main/CONTRIBUTING.md)
+for details on how to contribute to this project.
+
+Happy testing!
diff --git a/3rd-party/googletest/WORKSPACE b/3rd-party/googletest/WORKSPACE
new file mode 100644
index 0000000..63f7681
--- /dev/null
+++ b/3rd-party/googletest/WORKSPACE
@@ -0,0 +1,62 @@
+# Copyright 2024 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+workspace(name = "googletest")
+
+load("//:googletest_deps.bzl", "googletest_deps")
+googletest_deps()
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+  name = "rules_python",
+  sha256 = "d71d2c67e0bce986e1c5a7731b4693226867c45bfe0b7c5e0067228a536fc580",
+  strip_prefix = "rules_python-0.29.0",
+  urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.29.0/rules_python-0.29.0.tar.gz"],
+)
+
+# https://github.com/bazelbuild/rules_python/releases/tag/0.29.0
+load("@rules_python//python:repositories.bzl", "py_repositories")
+py_repositories()
+
+http_archive(
+  name = "bazel_skylib",
+  sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
+  urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
+)
+
+http_archive(
+    name = "platforms",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
+        "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
+    ],
+    sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
+)
diff --git a/3rd-party/googletest/WORKSPACE.bzlmod b/3rd-party/googletest/WORKSPACE.bzlmod
new file mode 100644
index 0000000..381432c
--- /dev/null
+++ b/3rd-party/googletest/WORKSPACE.bzlmod
@@ -0,0 +1,35 @@
+# Copyright 2024 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# https://bazel.build/external/migration#workspace.bzlmod
+#
+# This file is intentionally empty. When bzlmod is enabled and this
+# file exists, the content of WORKSPACE is ignored. This prevents
+# bzlmod builds from unintentionally depending on the WORKSPACE file.
diff --git a/3rd-party/googletest/ci/linux-presubmit.sh b/3rd-party/googletest/ci/linux-presubmit.sh
new file mode 100644
index 0000000..6d2b3fb
--- /dev/null
+++ b/3rd-party/googletest/ci/linux-presubmit.sh
@@ -0,0 +1,139 @@
+#!/bin/bash
+#
+# Copyright 2020, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -euox pipefail
+
+readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20240523"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20230120"
+
+if [[ -z ${GTEST_ROOT:-} ]]; then
+  GTEST_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+  STD="c++14 c++17 c++20"
+fi
+
+# Test the CMake build
+for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
+  for cmake_off_on in OFF ON; do
+    time docker run \
+      --volume="${GTEST_ROOT}:/src:ro" \
+      --tmpfs="/build:exec" \
+      --workdir="/build" \
+      --rm \
+      --env="CC=${cc}" \
+      --env=CXXFLAGS="-Werror -Wdeprecated" \
+      ${LINUX_LATEST_CONTAINER} \
+      /bin/bash -c "
+        cmake /src \
+          -DCMAKE_CXX_STANDARD=14 \
+          -Dgtest_build_samples=ON \
+          -Dgtest_build_tests=ON \
+          -Dgmock_build_tests=ON \
+          -Dcxx_no_exception=${cmake_off_on} \
+          -Dcxx_no_rtti=${cmake_off_on} && \
+        make -j$(nproc) && \
+        ctest -j$(nproc) --output-on-failure"
+  done
+done
+
+# Do one test with an older version of GCC
+# TODO(googletest-team): This currently uses Bazel 5. When upgrading to a
+# version of Bazel that supports Bzlmod, add --enable_bzlmod=false to keep test
+# coverage for the old WORKSPACE dependency management.
+time docker run \
+  --volume="${GTEST_ROOT}:/src:ro" \
+  --workdir="/src" \
+  --rm \
+  --env="CC=/usr/local/bin/gcc" \
+  --env="BAZEL_CXXOPTS=-std=c++14" \
+  ${LINUX_GCC_FLOOR_CONTAINER} \
+    /usr/local/bin/bazel test ... \
+      --copt="-Wall" \
+      --copt="-Werror" \
+      --copt="-Wuninitialized" \
+      --copt="-Wundef" \
+      --copt="-Wno-error=pragmas" \
+      --features=external_include_paths \
+      --keep_going \
+      --show_timestamps \
+      --test_output=errors
+
+# Test GCC
+for std in ${STD}; do
+  for absl in 0 1; do
+    time docker run \
+      --volume="${GTEST_ROOT}:/src:ro" \
+      --workdir="/src" \
+      --rm \
+      --env="CC=/usr/local/bin/gcc" \
+      --env="BAZEL_CXXOPTS=-std=${std}" \
+      ${LINUX_LATEST_CONTAINER} \
+      /usr/local/bin/bazel test ... \
+        --copt="-Wall" \
+        --copt="-Werror" \
+        --copt="-Wuninitialized" \
+        --copt="-Wundef" \
+        --define="absl=${absl}" \
+        --enable_bzlmod=true \
+        --features=external_include_paths \
+        --keep_going \
+        --show_timestamps \
+        --test_output=errors
+  done
+done
+
+# Test Clang
+for std in ${STD}; do
+  for absl in 0 1; do
+    time docker run \
+      --volume="${GTEST_ROOT}:/src:ro" \
+      --workdir="/src" \
+      --rm \
+      --env="CC=/opt/llvm/clang/bin/clang" \
+      --env="BAZEL_CXXOPTS=-std=${std}" \
+      ${LINUX_LATEST_CONTAINER} \
+      /usr/local/bin/bazel test ... \
+        --copt="--gcc-toolchain=/usr/local" \
+        --copt="-Wall" \
+        --copt="-Werror" \
+        --copt="-Wuninitialized" \
+        --copt="-Wundef" \
+        --define="absl=${absl}" \
+        --enable_bzlmod=true \
+        --features=external_include_paths \
+        --keep_going \
+        --linkopt="--gcc-toolchain=/usr/local" \
+        --show_timestamps \
+        --test_output=errors
+  done
+done
diff --git a/3rd-party/googletest/ci/macos-presubmit.sh b/3rd-party/googletest/ci/macos-presubmit.sh
new file mode 100644
index 0000000..70eaa74
--- /dev/null
+++ b/3rd-party/googletest/ci/macos-presubmit.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+#
+# Copyright 2020, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -euox pipefail
+
+if [[ -z ${GTEST_ROOT:-} ]]; then
+  GTEST_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+# Test the CMake build
+for cmake_off_on in OFF ON; do
+  BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
+  cd ${BUILD_DIR}
+  time cmake ${GTEST_ROOT} \
+    -DCMAKE_CXX_STANDARD=14 \
+    -Dgtest_build_samples=ON \
+    -Dgtest_build_tests=ON \
+    -Dgmock_build_tests=ON \
+    -Dcxx_no_exception=${cmake_off_on} \
+    -Dcxx_no_rtti=${cmake_off_on}
+  time make
+  time ctest -j$(nproc) --output-on-failure
+done
+
+# Test the Bazel build
+
+# If we are running on Kokoro, check for a versioned Bazel binary.
+KOKORO_GFILE_BAZEL_BIN="bazel-7.0.0-darwin-x86_64"
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
+  BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
+  chmod +x ${BAZEL_BIN}
+else
+  BAZEL_BIN="bazel"
+fi
+
+cd ${GTEST_ROOT}
+for absl in 0 1; do
+  ${BAZEL_BIN} test ... \
+    --copt="-Wall" \
+    --copt="-Werror" \
+    --copt="-Wundef" \
+    --cxxopt="-std=c++14" \
+    --define="absl=${absl}" \
+    --enable_bzlmod=true \
+    --features=external_include_paths \
+    --keep_going \
+    --show_timestamps \
+    --test_output=errors
+done
diff --git a/3rd-party/googletest/ci/windows-presubmit.bat b/3rd-party/googletest/ci/windows-presubmit.bat
new file mode 100644
index 0000000..9753f9c
--- /dev/null
+++ b/3rd-party/googletest/ci/windows-presubmit.bat
@@ -0,0 +1,58 @@
+SETLOCAL ENABLEDELAYEDEXPANSION
+
+SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-7.0.0-windows-x86_64.exe
+
+SET PATH=C:\Python34;%PATH%
+SET BAZEL_PYTHON=C:\python34\python.exe
+SET BAZEL_SH=C:\tools\msys64\usr\bin\bash.exe
+SET CMAKE_BIN="cmake.exe"
+SET CTEST_BIN="ctest.exe"
+SET CTEST_OUTPUT_ON_FAILURE=1
+SET CMAKE_BUILD_PARALLEL_LEVEL=16
+SET CTEST_PARALLEL_LEVEL=16
+
+IF EXIST git\googletest (
+  CD git\googletest
+) ELSE IF EXIST github\googletest (
+  CD github\googletest
+)
+
+IF %errorlevel% neq 0 EXIT /B 1
+
+:: ----------------------------------------------------------------------------
+:: CMake
+MKDIR cmake_msvc2022
+CD cmake_msvc2022
+
+%CMAKE_BIN% .. ^
+  -G "Visual Studio 17 2022" ^
+  -DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
+  -DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
+  -DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
+  -Dgtest_build_samples=ON ^
+  -Dgtest_build_tests=ON ^
+  -Dgmock_build_tests=ON
+IF %errorlevel% neq 0 EXIT /B 1
+
+%CMAKE_BIN% --build . --target ALL_BUILD --config Debug -- -maxcpucount
+IF %errorlevel% neq 0 EXIT /B 1
+
+%CTEST_BIN% -C Debug --timeout 600
+IF %errorlevel% neq 0 EXIT /B 1
+
+CD ..
+RMDIR /S /Q cmake_msvc2022
+
+:: ----------------------------------------------------------------------------
+:: Bazel
+
+SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
+%BAZEL_EXE% test ... ^
+  --compilation_mode=dbg ^
+  --copt=/std:c++14 ^
+  --copt=/WX ^
+  --enable_bzlmod=true ^
+  --keep_going ^
+  --test_output=errors ^
+  --test_tag_filters=-no_test_msvc2017
+IF %errorlevel% neq 0 EXIT /B 1
diff --git a/3rd-party/googletest/docs/_config.yml b/3rd-party/googletest/docs/_config.yml
new file mode 100644
index 0000000..d12867e
--- /dev/null
+++ b/3rd-party/googletest/docs/_config.yml
@@ -0,0 +1 @@
+title: GoogleTest
diff --git a/3rd-party/googletest/docs/_data/navigation.yml b/3rd-party/googletest/docs/_data/navigation.yml
new file mode 100644
index 0000000..9f33327
--- /dev/null
+++ b/3rd-party/googletest/docs/_data/navigation.yml
@@ -0,0 +1,43 @@
+nav:
+- section: "Get Started"
+  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"
+    url: "/primer.html"
+  - title: "Advanced Topics"
+    url: "/advanced.html"
+  - title: "Mocking for Dummies"
+    url: "/gmock_for_dummies.html"
+  - title: "Mocking Cookbook"
+    url: "/gmock_cook_book.html"
+  - title: "Mocking Cheat Sheet"
+    url: "/gmock_cheat_sheet.html"
+- section: "References"
+  items:
+  - title: "Testing Reference"
+    url: "/reference/testing.html"
+  - title: "Mocking Reference"
+    url: "/reference/mocking.html"
+  - title: "Assertions"
+    url: "/reference/assertions.html"
+  - title: "Matchers"
+    url: "/reference/matchers.html"
+  - title: "Actions"
+    url: "/reference/actions.html"
+  - title: "Testing FAQ"
+    url: "/faq.html"
+  - title: "Mocking FAQ"
+    url: "/gmock_faq.html"
+  - title: "Code Samples"
+    url: "/samples.html"
+  - title: "Using pkg-config"
+    url: "/pkgconfig.html"
+  - title: "Community Documentation"
+    url: "/community_created_documentation.html"
diff --git a/3rd-party/googletest/docs/_layouts/default.html b/3rd-party/googletest/docs/_layouts/default.html
new file mode 100644
index 0000000..c7f331b
--- /dev/null
+++ b/3rd-party/googletest/docs/_layouts/default.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="{{ site.lang | default: "en-US" }}">
+  <head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+{% seo %}
+    <link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
+    <script>
+      window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
+      ga('create', 'UA-197576187-1', { 'storage': 'none' });
+      ga('set', 'referrer', document.referrer.split('?')[0]);
+      ga('set', 'location', window.location.href.split('?')[0]);
+      ga('set', 'anonymizeIp', true);
+      ga('send', 'pageview');
+    </script>
+    <script async src='https://www.google-analytics.com/analytics.js'></script>
+  </head>
+  <body>
+    <div class="sidebar">
+      <div class="header">
+        <h1><a href="{{ "/" | relative_url }}">{{ site.title | default: "Documentation" }}</a></h1>
+      </div>
+      <input type="checkbox" id="nav-toggle" class="nav-toggle">
+      <label for="nav-toggle" class="expander">
+        <span class="arrow"></span>
+      </label>
+      <nav>
+        {% for item in site.data.navigation.nav %}
+        <h2>{{ item.section }}</h2>
+        <ul>
+          {% for subitem in item.items %}
+          <a href="{{subitem.url | relative_url }}">
+            <li class="{% if subitem.url == page.url %}active{% endif %}">
+              {{ subitem.title }}
+            </li>
+          </a>
+          {% endfor %}
+        </ul>
+        {% endfor %}
+      </nav>
+    </div>
+    <div class="main markdown-body">
+      <div class="main-inner">
+        {{ content }}
+      </div>
+      <div class="footer">
+        GoogleTest &middot;
+        <a href="https://github.com/google/googletest">GitHub Repository</a> &middot;
+        <a href="https://github.com/google/googletest/blob/main/LICENSE">License</a> &middot;
+        <a href="https://policies.google.com/privacy">Privacy Policy</a>
+      </div>
+    </div>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js" integrity="sha256-lZaRhKri35AyJSypXXs4o6OPFTbTmUoltBbDCbdzegg=" crossorigin="anonymous"></script>
+    <script>anchors.add('.main h2, .main h3, .main h4, .main h5, .main h6');</script>
+  </body>
+</html>
diff --git a/3rd-party/googletest/docs/_sass/main.scss b/3rd-party/googletest/docs/_sass/main.scss
new file mode 100644
index 0000000..92edc87
--- /dev/null
+++ b/3rd-party/googletest/docs/_sass/main.scss
@@ -0,0 +1,200 @@
+// Styles for GoogleTest docs website on GitHub Pages.
+// Color variables are defined in
+// https://github.com/pages-themes/primer/tree/master/_sass/primer-support/lib/variables
+
+$sidebar-width: 260px;
+
+body {
+  display: flex;
+  margin: 0;
+}
+
+.sidebar {
+  background: $black;
+  color: $text-white;
+  flex-shrink: 0;
+  height: 100vh;
+  overflow: auto;
+  position: sticky;
+  top: 0;
+  width: $sidebar-width;
+}
+
+.sidebar h1 {
+  font-size: 1.5em;
+}
+
+.sidebar h2 {
+  color: $gray-light;
+  font-size: 0.8em;
+  font-weight: normal;
+  margin-bottom: 0.8em;
+  padding-left: 2.5em;
+  text-transform: uppercase;
+}
+
+.sidebar .header {
+  background: $black;
+  padding: 2em;
+  position: sticky;
+  top: 0;
+  width: 100%;
+}
+
+.sidebar .header a {
+  color: $text-white;
+  text-decoration: none;
+}
+
+.sidebar .nav-toggle {
+  display: none;
+}
+
+.sidebar .expander {
+  cursor: pointer;
+  display: none;
+  height: 3em;
+  position: absolute;
+  right: 1em;
+  top: 1.5em;
+  width: 3em;
+}
+
+.sidebar .expander .arrow {
+  border: solid $white;
+  border-width: 0 3px 3px 0;
+  display: block;
+  height: 0.7em;
+  margin: 1em auto;
+  transform: rotate(45deg);
+  transition: transform 0.5s;
+  width: 0.7em;
+}
+
+.sidebar nav {
+  width: 100%;
+}
+
+.sidebar nav ul {
+  list-style-type: none;
+  margin-bottom: 1em;
+  padding: 0;
+
+  &:last-child {
+    margin-bottom: 2em;
+  }
+
+  a {
+   text-decoration: none;
+  }
+
+  li {
+    color: $text-white;
+    padding-left: 2em;
+    text-decoration: none;
+  }
+
+  li.active {
+    background: $border-gray-darker;
+    font-weight: bold;
+  }
+
+  li:hover {
+    background: $border-gray-darker;
+  }
+}
+
+.main {
+  background-color: $bg-gray;
+  width: calc(100% - #{$sidebar-width});
+}
+
+.main .main-inner {
+  background-color: $white;
+  padding: 2em;
+}
+
+.main .footer {
+  margin: 0;
+  padding: 2em;
+}
+
+.main table th {
+  text-align: left;
+}
+
+.main .callout {
+  border-left: 0.25em solid $white;
+  padding: 1em;
+
+  a {
+    text-decoration: underline;
+  }
+
+  &.important {
+    background-color: $bg-yellow-light;
+    border-color: $bg-yellow;
+    color: $black;
+  }
+
+  &.note {
+    background-color: $bg-blue-light;
+    border-color: $text-blue;
+    color: $text-blue;
+  }
+
+  &.tip {
+    background-color: $green-000;
+    border-color: $green-700;
+    color: $green-700;
+  }
+
+  &.warning {
+    background-color: $red-000;
+    border-color: $text-red;
+    color: $text-red;
+  }
+}
+
+.main .good pre {
+  background-color: $bg-green-light;
+}
+
+.main .bad pre {
+  background-color: $red-000;
+}
+
+@media all and (max-width: 768px) {
+  body {
+    flex-direction: column;
+  }
+
+  .sidebar {
+    height: auto;
+    position: relative;
+    width: 100%;
+  }
+
+  .sidebar .expander {
+    display: block;
+  }
+
+  .sidebar nav {
+    height: 0;
+    overflow: hidden;
+  }
+
+  .sidebar .nav-toggle:checked {
+    & ~ nav {
+      height: auto;
+    }
+
+    & + .expander .arrow {
+      transform: rotate(-135deg);
+    }
+  }
+
+  .main {
+    width: 100%;
+  }
+}
diff --git a/3rd-party/googletest/docs/advanced.md b/3rd-party/googletest/docs/advanced.md
new file mode 100644
index 0000000..240588a
--- /dev/null
+++ b/3rd-party/googletest/docs/advanced.md
@@ -0,0 +1,2446 @@
+# Advanced GoogleTest Topics
+
+## Introduction
+
+Now that you have read the [GoogleTest Primer](primer.md) and learned how to
+write tests using GoogleTest, it's time to learn some new tricks. This document
+will show you more assertions as well as how to construct complex failure
+messages, propagate fatal failures, reuse and speed up your test fixtures, and
+use various flags with your tests.
+
+## More Assertions
+
+This section covers some less frequently used, but still significant,
+assertions.
+
+### Explicit Success and Failure
+
+See [Explicit Success and Failure](reference/assertions.md#success-failure) in
+the Assertions Reference.
+
+### Exception Assertions
+
+See [Exception Assertions](reference/assertions.md#exceptions) in the Assertions
+Reference.
+
+### Predicate Assertions for Better Error Messages
+
+Even though GoogleTest has a rich set of assertions, they can never be complete,
+as it's impossible (nor a good idea) to anticipate all scenarios a user might
+run into. Therefore, sometimes a user has to use `EXPECT_TRUE()` to check a
+complex expression, for lack of a better macro. This has the problem of not
+showing you the values of the parts of the expression, making it hard to
+understand what went wrong. As a workaround, some users choose to construct the
+failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
+is awkward especially when the expression has side-effects or is expensive to
+evaluate.
+
+GoogleTest gives you three different options to solve this problem:
+
+#### Using an Existing Boolean Function
+
+If you already have a function or functor that returns `bool` (or a type that
+can be implicitly converted to `bool`), you can use it in a *predicate
+assertion* to get the function arguments printed for free. See
+[`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the Assertions
+Reference for details.
+
+#### Using a Function That Returns an AssertionResult
+
+While `EXPECT_PRED*()` and friends are handy for a quick job, the syntax is not
+satisfactory: you have to use different macros for different arities, and it
+feels more like Lisp than C++. The `::testing::AssertionResult` class solves
+this problem.
+
+An `AssertionResult` object represents the result of an assertion (whether it's
+a success or a failure, and an associated message). You can create an
+`AssertionResult` using one of these factory functions:
+
+```c++
+namespace testing {
+
+// Returns an AssertionResult object to indicate that an assertion has
+// succeeded.
+AssertionResult AssertionSuccess();
+
+// Returns an AssertionResult object to indicate that an assertion has
+// failed.
+AssertionResult AssertionFailure();
+
+}
+```
+
+You can then use the `<<` operator to stream messages to the `AssertionResult`
+object.
+
+To provide more readable messages in Boolean assertions (e.g. `EXPECT_TRUE()`),
+write a predicate function that returns `AssertionResult` instead of `bool`. For
+example, if you define `IsEven()` as:
+
+```c++
+testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return testing::AssertionSuccess();
+  else
+    return testing::AssertionFailure() << n << " is odd";
+}
+```
+
+instead of:
+
+```c++
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+```
+
+the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
+
+```none
+Value of: IsEven(Fib(4))
+  Actual: false (3 is odd)
+Expected: true
+```
+
+instead of a more opaque
+
+```none
+Value of: IsEven(Fib(4))
+  Actual: false
+Expected: true
+```
+
+If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE` as well
+(one third of Boolean assertions in the Google code base are negative ones), and
+are fine with making the predicate slower in the success case, you can supply a
+success message:
+
+```c++
+testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return testing::AssertionSuccess() << n << " is even";
+  else
+    return testing::AssertionFailure() << n << " is odd";
+}
+```
+
+Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
+
+```none
+  Value of: IsEven(Fib(6))
+     Actual: true (8 is even)
+  Expected: false
+```
+
+#### Using a Predicate-Formatter
+
+If you find the default message generated by
+[`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) and
+[`EXPECT_TRUE`](reference/assertions.md#EXPECT_TRUE) unsatisfactory, or some
+arguments to your predicate do not support streaming to `ostream`, you can
+instead use *predicate-formatter assertions* to *fully* customize how the
+message is formatted. See
+[`EXPECT_PRED_FORMAT*`](reference/assertions.md#EXPECT_PRED_FORMAT) in the
+Assertions Reference for details.
+
+### Floating-Point Comparison
+
+See [Floating-Point Comparison](reference/assertions.md#floating-point) in the
+Assertions Reference.
+
+#### Floating-Point Predicate-Format Functions
+
+Some floating-point operations are useful, but not that often used. In order to
+avoid an explosion of new macros, we provide them as predicate-format functions
+that can be used in the predicate assertion macro
+[`EXPECT_PRED_FORMAT2`](reference/assertions.md#EXPECT_PRED_FORMAT), for
+example:
+
+```c++
+using ::testing::FloatLE;
+using ::testing::DoubleLE;
+...
+EXPECT_PRED_FORMAT2(FloatLE, val1, val2);
+EXPECT_PRED_FORMAT2(DoubleLE, val1, val2);
+```
+
+The above code verifies that `val1` is less than, or approximately equal to,
+`val2`.
+
+### Asserting Using gMock Matchers
+
+See [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) in the Assertions
+Reference.
+
+### More String Assertions
+
+(Please read the [previous](#asserting-using-gmock-matchers) section first if
+you haven't.)
+
+You can use the gMock [string matchers](reference/matchers.md#string-matchers)
+with [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) to do more string
+comparison tricks (sub-string, prefix, suffix, regular expression, and etc). For
+example,
+
+```c++
+using ::testing::HasSubstr;
+using ::testing::MatchesRegex;
+...
+  ASSERT_THAT(foo_string, HasSubstr("needle"));
+  EXPECT_THAT(bar_string, MatchesRegex("\\w*\\d+"));
+```
+
+### Windows HRESULT assertions
+
+See [Windows HRESULT Assertions](reference/assertions.md#HRESULT) in the
+Assertions Reference.
+
+### Type Assertions
+
+You can call the function
+
+```c++
+::testing::StaticAssertTypeEq<T1, T2>();
+```
+
+to assert that types `T1` and `T2` are the same. The function does nothing if
+the assertion is satisfied. If the types are different, the function call will
+fail to compile, the compiler error message will say that `T1 and T2 are not the
+same type` and most likely (depending on the compiler) show you the actual
+values of `T1` and `T2`. This is mainly useful inside template code.
+
+**Caveat**: When used inside a member function of a class template or a function
+template, `StaticAssertTypeEq<T1, T2>()` is effective only if the function is
+instantiated. For example, given:
+
+```c++
+template <typename T> class Foo {
+ public:
+  void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+};
+```
+
+the code:
+
+```c++
+void Test1() { Foo<bool> foo; }
+```
+
+will not generate a compiler error, as `Foo<bool>::Bar()` is never actually
+instantiated. Instead, you need:
+
+```c++
+void Test2() { Foo<bool> foo; foo.Bar(); }
+```
+
+to cause a compiler error.
+
+### Assertion Placement
+
+You can use assertions in any C++ function. In particular, it doesn't have to be
+a method of the test fixture class. The one constraint is that assertions that
+generate a fatal failure (`FAIL*` and `ASSERT_*`) can only be used in
+void-returning functions. This is a consequence of Google's not using
+exceptions. By placing it in a non-void function you'll get a confusing compile
+error like `"error: void value not ignored as it ought to be"` or `"cannot
+initialize return object of type 'bool' with an rvalue of type 'void'"` or
+`"error: no viable conversion from 'void' to 'string'"`.
+
+If you need to use fatal assertions in a function that returns non-void, one
+option is to make the function return the value in an out parameter instead. For
+example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
+need to make sure that `*result` contains some sensible value even when the
+function returns prematurely. As the function now returns `void`, you can use
+any assertion inside of it.
+
+If changing the function's type is not an option, you should just use assertions
+that generate non-fatal failures, such as `ADD_FAILURE*` and `EXPECT_*`.
+
+{: .callout .note}
+NOTE: Constructors and destructors are not considered void-returning functions,
+according to the C++ language specification, and so you may not use fatal
+assertions in them; you'll get a compilation error if you try. Instead, either
+call `abort` and crash the entire test executable, or put the fatal assertion in
+a `SetUp`/`TearDown` function; see
+[constructor/destructor vs. `SetUp`/`TearDown`](faq.md#CtorVsSetUp)
+
+{: .callout .warning}
+WARNING: A fatal assertion in a helper function (private void-returning method)
+called from a constructor or destructor does not terminate the current test, as
+your intuition might suggest: it merely returns from the constructor or
+destructor early, possibly leaving your object in a partially-constructed or
+partially-destructed state! You almost certainly want to `abort` or use
+`SetUp`/`TearDown` instead.
+
+## Skipping test execution
+
+Related to the assertions `SUCCEED()` and `FAIL()`, you can prevent further test
+execution at runtime with the `GTEST_SKIP()` macro. This is useful when you need
+to check for preconditions of the system under test during runtime and skip
+tests in a meaningful way.
+
+`GTEST_SKIP()` can be used in individual test cases or in the `SetUp()` methods
+of classes derived from either `::testing::Environment` or `::testing::Test`.
+For example:
+
+```c++
+TEST(SkipTest, DoesSkip) {
+  GTEST_SKIP() << "Skipping single test";
+  EXPECT_EQ(0, 1);  // Won't fail; it won't be executed
+}
+
+class SkipFixture : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    GTEST_SKIP() << "Skipping all tests for this fixture";
+  }
+};
+
+// Tests for SkipFixture won't be executed.
+TEST_F(SkipFixture, SkipsOneTest) {
+  EXPECT_EQ(5, 7);  // Won't fail
+}
+```
+
+As with assertion macros, you can stream a custom message into `GTEST_SKIP()`.
+
+## Teaching GoogleTest How to Print Your Values
+
+When a test assertion such as `EXPECT_EQ` fails, GoogleTest prints the argument
+values to help you debug. It does this using a user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator. For other types, it
+prints the raw bytes in the value and hopes that you the user can figure it out.
+
+As mentioned earlier, the printer is *extensible*. That means you can teach it
+to do a better job at printing your particular type than to dump the bytes. To
+do that, define an `AbslStringify()` overload as a `friend` function template
+for your type:
+
+```cpp
+namespace foo {
+
+class Point {  // We want GoogleTest to be able to print instances of this.
+  ...
+  // Provide a friend overload.
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const Point& point) {
+    absl::Format(&sink, "(%d, %d)", point.x, point.y);
+  }
+
+  int x;
+  int y;
+};
+
+// If you can't declare the function in the class it's important that the
+// AbslStringify overload is defined in the SAME namespace that defines Point.
+// C++'s look-up rules rely on that.
+enum class EnumWithStringify { kMany = 0, kChoices = 1 };
+
+template <typename Sink>
+void AbslStringify(Sink& sink, EnumWithStringify e) {
+  absl::Format(&sink, "%s", e == EnumWithStringify::kMany ? "Many" : "Choices");
+}
+
+}  // namespace foo
+```
+
+{: .callout .note}
+Note: `AbslStringify()` utilizes a generic "sink" buffer to construct its
+string. For more information about supported operations on `AbslStringify()`'s
+sink, see go/abslstringify.
+
+`AbslStringify()` can also use `absl::StrFormat`'s catch-all `%v` type specifier
+within its own format strings to perform type deduction. `Point` above could be
+formatted as `"(%v, %v)"` for example, and deduce the `int` values as `%d`.
+
+Sometimes, `AbslStringify()` might not be an option: your team may wish to print
+types with extra debugging information for testing purposes only. If so, you can
+instead define a `PrintTo()` function like this:
+
+```c++
+#include <ostream>
+
+namespace foo {
+
+class Point {
+  ...
+  friend void PrintTo(const Point& point, std::ostream* os) {
+    *os << "(" << point.x << "," << point.y << ")";
+  }
+
+  int x;
+  int y;
+};
+
+// If you can't declare the function in the class it's important that PrintTo()
+// is defined in the SAME namespace that defines Point.  C++'s look-up rules
+// rely on that.
+void PrintTo(const Point& point, std::ostream* os) {
+    *os << "(" << point.x << "," << point.y << ")";
+}
+
+}  // namespace foo
+```
+
+If you have defined both `AbslStringify()` and `PrintTo()`, the latter will be
+used by GoogleTest. This allows you to customize how the value appears in
+GoogleTest's output without affecting code that relies on the behavior of
+`AbslStringify()`.
+
+If you have an existing `<<` operator and would like to define an
+`AbslStringify()`, the latter will be used for GoogleTest printing.
+
+If you want to print a value `x` using GoogleTest's value printer yourself, just
+call `::testing::PrintToString(x)`, which returns an `std::string`:
+
+```c++
+vector<pair<Point, int> > point_ints = GetPointIntVector();
+
+EXPECT_TRUE(IsCorrectPointIntVector(point_ints))
+    << "point_ints = " << testing::PrintToString(point_ints);
+```
+
+For more details regarding `AbslStringify()` and its integration with other
+libraries, see go/abslstringify.
+
+## Death Tests
+
+In many applications, there are assertions that can cause application failure if
+a condition is not met. These consistency checks, which ensure that the program
+is in a known good state, are there to fail at the earliest possible time after
+some program state is corrupted. If the assertion checks the wrong condition,
+then the program may proceed in an erroneous state, which could lead to memory
+corruption, security holes, or worse. Hence it is vitally important to test that
+such assertion statements work as expected.
+
+Since these precondition checks cause the processes to die, we call such tests
+_death tests_. More generally, any test that checks that a program terminates
+(except by throwing an exception) in an expected fashion is also a death test.
+
+Note that if a piece of code throws an exception, we don't consider it "death"
+for the purpose of death tests, as the caller of the code could catch the
+exception and avoid the crash. If you want to verify exceptions thrown by your
+code, see [Exception Assertions](#ExceptionAssertions).
+
+If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see
+["Catching" Failures](#catching-failures).
+
+### How to Write a Death Test
+
+GoogleTest provides assertion macros to support death tests. See
+[Death Assertions](reference/assertions.md#death) in the Assertions Reference
+for details.
+
+To write a death test, simply use one of the macros inside your test function.
+For example,
+
+```c++
+TEST(MyDeathTest, Foo) {
+  // This death test uses a compound statement.
+  ASSERT_DEATH({
+    int n = 5;
+    Foo(&n);
+  }, "Error on line .* of Foo()");
+}
+
+TEST(MyDeathTest, NormalExit) {
+  EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success");
+}
+
+TEST(MyDeathTest, KillProcess) {
+  EXPECT_EXIT(KillProcess(), testing::KilledBySignal(SIGKILL),
+              "Sending myself unblockable signal");
+}
+```
+
+verifies that:
+
+*   calling `Foo(5)` causes the process to die with the given error message,
+*   calling `NormalExit()` causes the process to print `"Success"` to stderr and
+    exit with exit code 0, and
+*   calling `KillProcess()` kills the process with signal `SIGKILL`.
+
+The test function body may contain other assertions and statements as well, if
+necessary.
+
+Note that a death test only cares about three things:
+
+1.  does `statement` abort or exit the process?
+2.  (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status
+    satisfy `predicate`? Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`)
+    is the exit status non-zero? And
+3.  does the stderr output match `matcher`?
+
+In particular, if `statement` generates an `ASSERT_*` or `EXPECT_*` failure, it
+will **not** cause the death test to fail, as GoogleTest assertions don't abort
+the process.
+
+### Death Test Naming
+
+{: .callout .important}
+IMPORTANT: We strongly recommend you to follow the convention of naming your
+**test suite** (not test) `*DeathTest` when it contains a death test, as
+demonstrated in the above example. The
+[Death Tests And Threads](#death-tests-and-threads) section below explains why.
+
+If a test fixture class is shared by normal tests and death tests, you can use
+`using` or `typedef` to introduce an alias for the fixture class and avoid
+duplicating its code:
+
+```c++
+class FooTest : public testing::Test { ... };
+
+using FooDeathTest = FooTest;
+
+TEST_F(FooTest, DoesThis) {
+  // normal test
+}
+
+TEST_F(FooDeathTest, DoesThat) {
+  // death test
+}
+```
+
+### Regular Expression Syntax
+
+When built with Bazel and using Abseil, GoogleTest uses the
+[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
+systems (Linux, Cygwin, Mac), GoogleTest uses the
+[POSIX extended regular expression](https://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax. To learn about POSIX syntax, you may want to read this
+[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
+
+On Windows, GoogleTest uses its own simple regular expression implementation. It
+lacks many features. For example, we don't support union (`"x|y"`), grouping
+(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
+others. Below is what we do support (`A` denotes a literal character, period
+(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
+expressions.):
+
+Expression | Meaning
+---------- | --------------------------------------------------------------
+`c`        | matches any literal character `c`
+`\\d`      | matches any decimal digit
+`\\D`      | matches any character that's not a decimal digit
+`\\f`      | matches `\f`
+`\\n`      | matches `\n`
+`\\r`      | matches `\r`
+`\\s`      | matches any ASCII whitespace, including `\n`
+`\\S`      | matches any character that's not a whitespace
+`\\t`      | matches `\t`
+`\\v`      | matches `\v`
+`\\w`      | matches any letter, `_`, or decimal digit
+`\\W`      | matches any character that `\\w` doesn't match
+`\\c`      | matches any literal character `c`, which must be a punctuation
+`.`        | matches any single character except `\n`
+`A?`       | matches 0 or 1 occurrences of `A`
+`A*`       | matches 0 or many occurrences of `A`
+`A+`       | matches 1 or many occurrences of `A`
+`^`        | matches the beginning of a string (not that of each line)
+`$`        | matches the end of a string (not that of each line)
+`xy`       | matches `x` followed by `y`
+
+To help you determine which capability is available on your system, GoogleTest
+defines macros to govern which regular expression it is using. The macros are:
+`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
+tests to work in all cases, you can either `#if` on these macros or use the more
+limited syntax only.
+
+### How It Works
+
+See [Death Assertions](reference/assertions.md#death) in the Assertions
+Reference.
+
+### Death Tests And Threads
+
+The reason for the two death test styles has to do with thread safety. Due to
+well-known problems with forking in the presence of threads, death tests should
+be run in a single-threaded context. Sometimes, however, it isn't feasible to
+arrange that kind of environment. For example, statically-initialized modules
+may start threads before main is ever reached. Once threads have been created,
+it may be difficult or impossible to clean them up.
+
+GoogleTest has three features intended to raise awareness of threading issues.
+
+1.  A warning is emitted if multiple threads are running when a death test is
+    encountered.
+2.  Test suites with a name ending in "DeathTest" are run before all other
+    tests.
+3.  It uses `clone()` instead of `fork()` to spawn the child process on Linux
+    (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely
+    to cause the child to hang when the parent process has multiple threads.
+
+It's perfectly fine to create threads inside a death test statement; they are
+executed in a separate process and cannot affect the parent.
+
+### Death Test Styles
+
+The "threadsafe" death test style was introduced in order to help mitigate the
+risks of testing in a possibly multithreaded environment. It trades increased
+test execution time (potentially dramatically so) for improved thread safety.
+
+The automated testing framework does not set the style flag. You can choose a
+particular style of death tests by setting the flag programmatically:
+
+```c++
+GTEST_FLAG_SET(death_test_style, "threadsafe");
+```
+
+You can do this in `main()` to set the style for all death tests in the binary,
+or in individual tests. Recall that flags are saved before running each test and
+restored afterwards, so you need not do that yourself. For example:
+
+```c++
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  GTEST_FLAG_SET(death_test_style, "fast");
+  return RUN_ALL_TESTS();
+}
+
+TEST(MyDeathTest, TestOne) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  // This test is run in the "threadsafe" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+TEST(MyDeathTest, TestTwo) {
+  // This test is run in the "fast" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+```
+
+### Caveats
+
+The `statement` argument of `ASSERT_EXIT()` can be any valid C++ statement. If
+it leaves the current function via a `return` statement or by throwing an
+exception, the death test is considered to have failed. Some GoogleTest macros
+may return from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid
+them in `statement`.
+
+Since `statement` runs in the child process, any in-memory side effect (e.g.
+modifying a variable, releasing memory, etc) it causes will *not* be observable
+in the parent process. In particular, if you release memory in a death test,
+your program will fail the heap check as the parent process will never see the
+memory reclaimed. To solve this problem, you can
+
+1.  try not to free memory in a death test;
+2.  free the memory again in the parent process; or
+3.  do not use the heap checker in your program.
+
+Due to an implementation detail, you cannot place multiple death test assertions
+on the same line; otherwise, compilation will fail with an unobvious error
+message.
+
+Despite the improved thread safety afforded by the "threadsafe" style of death
+test, thread problems such as deadlock are still possible in the presence of
+handlers registered with `pthread_atfork(3)`.
+
+## Using Assertions in Sub-routines
+
+{: .callout .note}
+Note: If you want to put a series of test assertions in a subroutine to check
+for a complex condition, consider using
+[a custom GMock matcher](gmock_cook_book.md#NewMatchers) instead. This lets you
+provide a more readable error message in case of failure and avoid all of the
+issues described below.
+
+### Adding Traces to Assertions
+
+If a test sub-routine is called from several places, when an assertion inside it
+fails, it can be hard to tell which invocation of the sub-routine the failure is
+from. You can alleviate this problem using extra logging or custom failure
+messages, but that usually clutters up your tests. A better solution is to use
+the `SCOPED_TRACE` macro or the `ScopedTrace` utility:
+
+```c++
+SCOPED_TRACE(message);
+```
+
+```c++
+ScopedTrace trace("file_path", line_number, message);
+```
+
+where `message` can be anything streamable to `std::ostream`. `SCOPED_TRACE`
+macro will cause the current file name, line number, and the given message to be
+added in every failure message. `ScopedTrace` accepts explicit file name and
+line number in arguments, which is useful for writing test helpers. The effect
+will be undone when the control leaves the current lexical scope.
+
+For example,
+
+```c++
+10: void Sub1(int n) {
+11:   EXPECT_EQ(Bar(n), 1);
+12:   EXPECT_EQ(Bar(n + 1), 2);
+13: }
+14:
+15: TEST(FooTest, Bar) {
+16:   {
+17:     SCOPED_TRACE("A");  // This trace point will be included in
+18:                         // every failure in this scope.
+19:     Sub1(1);
+20:   }
+21:   // Now it won't.
+22:   Sub1(9);
+23: }
+```
+
+could result in messages like these:
+
+```none
+path/to/foo_test.cc:11: Failure
+Value of: Bar(n)
+Expected: 1
+  Actual: 2
+Google Test trace:
+path/to/foo_test.cc:17: A
+
+path/to/foo_test.cc:12: Failure
+Value of: Bar(n + 1)
+Expected: 2
+  Actual: 3
+```
+
+Without the trace, it would've been difficult to know which invocation of
+`Sub1()` the two failures come from respectively. (You could add an extra
+message to each assertion in `Sub1()` to indicate the value of `n`, but that's
+tedious.)
+
+Some tips on using `SCOPED_TRACE`:
+
+1.  With a suitable message, it's often enough to use `SCOPED_TRACE` at the
+    beginning of a sub-routine, instead of at each call site.
+2.  When calling sub-routines inside a loop, make the loop iterator part of the
+    message in `SCOPED_TRACE` such that you can know which iteration the failure
+    is from.
+3.  Sometimes the line number of the trace point is enough for identifying the
+    particular invocation of a sub-routine. In this case, you don't have to
+    choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
+4.  You can use `SCOPED_TRACE` in an inner scope when there is one in the outer
+    scope. In this case, all active trace points will be included in the failure
+    messages, in reverse order they are encountered.
+5.  The trace dump is clickable in Emacs - hit `return` on a line number and
+    you'll be taken to that line in the source file!
+
+### Propagating Fatal Failures
+
+A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
+when they fail they only abort the _current function_, not the entire test. For
+example, the following test will segfault:
+
+```c++
+void Subroutine() {
+  // Generates a fatal failure and aborts the current function.
+  ASSERT_EQ(1, 2);
+
+  // The following won't be executed.
+  ...
+}
+
+TEST(FooTest, Bar) {
+  Subroutine();  // The intended behavior is for the fatal failure
+                 // in Subroutine() to abort the entire test.
+
+  // The actual behavior: the function goes on after Subroutine() returns.
+  int* p = nullptr;
+  *p = 3;  // Segfault!
+}
+```
+
+To alleviate this, GoogleTest provides three different solutions. You could use
+either exceptions, the `(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
+`HasFatalFailure()` function. They are described in the following two
+subsections.
+
+#### Asserting on Subroutines with an exception
+
+The following code can turn ASSERT-failure into an exception:
+
+```c++
+class ThrowListener : public testing::EmptyTestEventListener {
+  void OnTestPartResult(const testing::TestPartResult& result) override {
+    if (result.type() == testing::TestPartResult::kFatalFailure) {
+      throw testing::AssertionException(result);
+    }
+  }
+};
+int main(int argc, char** argv) {
+  ...
+  testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
+  return RUN_ALL_TESTS();
+}
+```
+
+This listener should be added after other listeners if you have any, otherwise
+they won't see failed `OnTestPartResult`.
+
+#### Asserting on Subroutines
+
+As shown above, if your test calls a subroutine that has an `ASSERT_*` failure
+in it, the test will continue after the subroutine returns. This may not be what
+you want.
+
+Often people want fatal failures to propagate like exceptions. For that
+GoogleTest offers the following macros:
+
+Fatal assertion                       | Nonfatal assertion                    | Verifies
+------------------------------------- | ------------------------------------- | --------
+`ASSERT_NO_FATAL_FAILURE(statement);` | `EXPECT_NO_FATAL_FAILURE(statement);` | `statement` doesn't generate any new fatal failures in the current thread.
+
+Only failures in the thread that executes the assertion are checked to determine
+the result of this type of assertions. If `statement` creates new threads,
+failures in these threads are ignored.
+
+Examples:
+
+```c++
+ASSERT_NO_FATAL_FAILURE(Foo());
+
+int i;
+EXPECT_NO_FATAL_FAILURE({
+  i = Bar();
+});
+```
+
+Assertions from multiple threads are currently not supported on Windows.
+
+#### Checking for Failures in the Current Test
+
+`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
+assertion in the current test has suffered a fatal failure. This allows
+functions to catch fatal failures in a sub-routine and return early.
+
+```c++
+class Test {
+ public:
+  ...
+  static bool HasFatalFailure();
+};
+```
+
+The typical usage, which basically simulates the behavior of a thrown exception,
+is:
+
+```c++
+TEST(FooTest, Bar) {
+  Subroutine();
+  // Aborts if Subroutine() had a fatal failure.
+  if (HasFatalFailure()) return;
+
+  // The following won't be executed.
+  ...
+}
+```
+
+If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
+fixture, you must add the `::testing::Test::` prefix, as in:
+
+```c++
+if (testing::Test::HasFatalFailure()) return;
+```
+
+Similarly, `HasNonfatalFailure()` returns `true` if the current test has at
+least one non-fatal failure, and `HasFailure()` returns `true` if the current
+test has at least one failure of either kind.
+
+## Logging Additional Information
+
+In your test code, you can call `RecordProperty("key", value)` to log additional
+information, where `value` can be either a string or an `int`. The *last* value
+recorded for a key will be emitted to the
+[XML output](#generating-an-xml-report) if you specify one. For example, the
+test
+
+```c++
+TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
+  RecordProperty("MaximumWidgets", ComputeMaxUsage());
+  RecordProperty("MinimumWidgets", ComputeMinUsage());
+}
+```
+
+will output XML like this:
+
+```xml
+  ...
+    <testcase name="MinAndMaxWidgets" file="test.cpp" line="1" status="run" time="0.006" classname="WidgetUsageTest" MaximumWidgets="12" MinimumWidgets="9" />
+  ...
+```
+
+{: .callout .note}
+> NOTE:
+>
+> *   `RecordProperty()` is a static member of the `Test` class. Therefore it
+>     needs to be prefixed with `::testing::Test::` if used outside of the
+>     `TEST` body and the test fixture class.
+> *   *`key`* must be a valid XML attribute name, and cannot conflict with the
+>     ones already used by GoogleTest (`name`, `status`, `time`, `classname`,
+>     `type_param`, and `value_param`).
+> *   Calling `RecordProperty()` outside of the lifespan of a test is allowed.
+>     If it's called outside of a test but between a test suite's
+>     `SetUpTestSuite()` and `TearDownTestSuite()` methods, it will be
+>     attributed to the XML element for the test suite. If it's called outside
+>     of all test suites (e.g. in a test environment), it will be attributed to
+>     the top-level XML element.
+
+## Sharing Resources Between Tests in the Same Test Suite
+
+GoogleTest creates a new test fixture object for each test in order to make
+tests independent and easier to debug. However, sometimes tests use resources
+that are expensive to set up, making the one-copy-per-test model prohibitively
+expensive.
+
+If the tests don't change the resource, there's no harm in their sharing a
+single resource copy. So, in addition to per-test set-up/tear-down, GoogleTest
+also supports per-test-suite set-up/tear-down. To use it:
+
+1.  In your test fixture class (say `FooTest` ), declare as `static` some member
+    variables to hold the shared resources.
+2.  Outside your test fixture class (typically just below it), define those
+    member variables, optionally giving them initial values.
+3.  In the same test fixture class, define a public member function `static void
+    SetUpTestSuite()` (remember not to spell it as **`SetupTestSuite`** with a
+    small `u`!) to set up the shared resources and a `static void
+    TearDownTestSuite()` function to tear them down.
+
+That's it! GoogleTest automatically calls `SetUpTestSuite()` before running the
+*first test* in the `FooTest` test suite (i.e. before creating the first
+`FooTest` object), and calls `TearDownTestSuite()` after running the *last test*
+in it (i.e. after deleting the last `FooTest` object). In between, the tests can
+use the shared resources.
+
+Remember that the test order is undefined, so your code can't depend on a test
+preceding or following another. Also, the tests must either not modify the state
+of any shared resource, or, if they do modify the state, they must restore the
+state to its original value before passing control to the next test.
+
+Note that `SetUpTestSuite()` may be called multiple times for a test fixture
+class that has derived classes, so you should not expect code in the function
+body to be run only once. Also, derived classes still have access to shared
+resources defined as static members, so careful consideration is needed when
+managing shared resources to avoid memory leaks if shared resources are not
+properly cleaned up in `TearDownTestSuite()`.
+
+Here's an example of per-test-suite set-up and tear-down:
+
+```c++
+class FooTest : public testing::Test {
+ protected:
+  // Per-test-suite set-up.
+  // Called before the first test in this test suite.
+  // Can be omitted if not needed.
+  static void SetUpTestSuite() {
+    shared_resource_ = new ...;
+
+    // If `shared_resource_` is **not deleted** in `TearDownTestSuite()`,
+    // reallocation should be prevented because `SetUpTestSuite()` may be called
+    // in subclasses of FooTest and lead to memory leak.
+    //
+    // if (shared_resource_ == nullptr) {
+    //   shared_resource_ = new ...;
+    // }
+  }
+
+  // Per-test-suite tear-down.
+  // Called after the last test in this test suite.
+  // Can be omitted if not needed.
+  static void TearDownTestSuite() {
+    delete shared_resource_;
+    shared_resource_ = nullptr;
+  }
+
+  // You can define per-test set-up logic as usual.
+  void SetUp() override { ... }
+
+  // You can define per-test tear-down logic as usual.
+  void TearDown() override { ... }
+
+  // Some expensive resource shared by all tests.
+  static T* shared_resource_;
+};
+
+T* FooTest::shared_resource_ = nullptr;
+
+TEST_F(FooTest, Test1) {
+  ... you can refer to shared_resource_ here ...
+}
+
+TEST_F(FooTest, Test2) {
+  ... you can refer to shared_resource_ here ...
+}
+```
+
+{: .callout .note}
+NOTE: Though the above code declares `SetUpTestSuite()` protected, it may
+sometimes be necessary to declare it public, such as when using it with
+`TEST_P`.
+
+## Global Set-Up and Tear-Down
+
+Just as you can do set-up and tear-down at the test level and the test suite
+level, you can also do it at the test program level. Here's how.
+
+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 {
+ public:
+  ~Environment() override {}
+
+  // Override this to define how to set up the environment.
+  void SetUp() override {}
+
+  // Override this to define how to tear down the environment.
+  void TearDown() override {}
+};
+```
+
+Then, you register an instance of your environment class with GoogleTest by
+calling the `::testing::AddGlobalTestEnvironment()` function:
+
+```c++
+Environment* AddGlobalTestEnvironment(Environment* env);
+```
+
+Now, when `RUN_ALL_TESTS()` is invoked, it first calls the `SetUp()` method. The
+tests are then executed, provided that none of the environments have reported
+fatal failures and `GTEST_SKIP()` has not been invoked. Finally, `TearDown()` is
+called.
+
+Note that `SetUp()` and `TearDown()` are only invoked if there is at least one
+test to be performed. Importantly, `TearDown()` is executed even if the test is
+not run due to a fatal failure or `GTEST_SKIP()`.
+
+Calling `SetUp()` and `TearDown()` for each iteration depends on the flag
+`gtest_recreate_environments_when_repeating`. `SetUp()` and `TearDown()` are
+called for each environment object when the object is recreated for each
+iteration. However, if test environments are not recreated for each iteration,
+`SetUp()` is called only on the first iteration, and `TearDown()` is called only
+on the last iteration.
+
+It's OK to register multiple environment objects. In this suite, their `SetUp()`
+will be called in the order they are registered, and their `TearDown()` will be
+called in the reverse order.
+
+Note that GoogleTest takes ownership of the registered environment objects.
+Therefore **do not delete them** by yourself.
+
+You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is called,
+probably in `main()`. If you use `gtest_main`, you need to call this before
+`main()` starts for it to take effect. One way to do this is to define a global
+variable like this:
+
+```c++
+testing::Environment* const foo_env =
+    testing::AddGlobalTestEnvironment(new FooEnvironment);
+```
+
+However, we strongly recommend you to write your own `main()` and call
+`AddGlobalTestEnvironment()` there, as relying on initialization of global
+variables makes the code harder to read and may cause problems when you register
+multiple environments from different translation units and the environments have
+dependencies among them (remember that the compiler doesn't guarantee the order
+in which global variables from different translation units are initialized).
+
+## Value-Parameterized Tests
+
+*Value-parameterized tests* allow you to test your code with different
+parameters without writing multiple copies of the same test. This is useful in a
+number of situations, for example:
+
+*   You have a piece of code whose behavior is affected by one or more
+    command-line flags. You want to make sure your code performs correctly for
+    various values of those flags.
+*   You want to test different implementations of an OO interface.
+*   You want to test your code over various inputs (a.k.a. data-driven testing).
+    This feature is easy to abuse, so please exercise your good sense when doing
+    it!
+
+### How to Write Value-Parameterized Tests
+
+To write value-parameterized tests, first you should define a fixture class. It
+must be derived from both `testing::Test` and `testing::WithParamInterface<T>`
+(the latter is a pure interface), where `T` is the type of your parameter
+values. For convenience, you can just derive the fixture class from
+`testing::TestWithParam<T>`, which itself is derived from both `testing::Test`
+and `testing::WithParamInterface<T>`. `T` can be any copyable type. If it's a
+raw pointer, you are responsible for managing the lifespan of the pointed
+values.
+
+{: .callout .note}
+NOTE: If your test fixture defines `SetUpTestSuite()` or `TearDownTestSuite()`
+they must be declared **public** rather than **protected** in order to use
+`TEST_P`.
+
+```c++
+class FooTest :
+    public testing::TestWithParam<absl::string_view> {
+  // You can implement all the usual fixture class members here.
+  // To access the test parameter, call GetParam() from class
+  // TestWithParam<T>.
+};
+
+// Or, when you want to add parameters to a pre-existing fixture class:
+class BaseTest : public testing::Test {
+  ...
+};
+class BarTest : public BaseTest,
+                public testing::WithParamInterface<absl::string_view> {
+  ...
+};
+```
+
+Then, use the `TEST_P` macro to define as many test patterns using this fixture
+as you want. The `_P` suffix is for "parameterized" or "pattern", whichever you
+prefer to think.
+
+```c++
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+```
+
+Finally, you can use the `INSTANTIATE_TEST_SUITE_P` macro to instantiate the
+test suite with any set of parameters you want. GoogleTest defines a number of
+functions for generating test parameters—see details at
+[`INSTANTIATE_TEST_SUITE_P`](reference/testing.md#INSTANTIATE_TEST_SUITE_P) in
+the Testing Reference.
+
+For example, the following statement will instantiate tests from the `FooTest`
+test suite each with parameter values `"meeny"`, `"miny"`, and `"moe"` using the
+[`Values`](reference/testing.md#param-generators) parameter generator:
+
+```c++
+INSTANTIATE_TEST_SUITE_P(MeenyMinyMoe,
+                         FooTest,
+                         testing::Values("meeny", "miny", "moe"));
+```
+
+{: .callout .note}
+NOTE: The code above must be placed at global or namespace scope, not at
+function scope.
+
+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](reference/testing.md#param-generators).
+
+The parameter generator expression is not evaluated until GoogleTest is
+initialized (via `InitGoogleTest()`). Any prior initialization done in the
+`main` function will be accessible from the parameter generator, for example,
+the results of flag parsing.
+
+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:
+
+*   `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).
+
+The following statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"` using the
+[`ValuesIn`](reference/testing.md#param-generators) parameter generator:
+
+```c++
+constexpr absl::string_view kPets[] = {"cat", "dog"};
+INSTANTIATE_TEST_SUITE_P(Pets, FooTest, testing::ValuesIn(kPets));
+```
+
+The tests from the instantiation above will have these names:
+
+*   `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/main/googletest/samples/sample7_unittest.cc "Parameterized Test example"
+[sample8_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample8_unittest.cc "Parameterized Test example with multiple parameters"
+
+### Creating Value-Parameterized Abstract Tests
+
+In the above, we define and instantiate `FooTest` in the *same* source file.
+Sometimes you may want to define value-parameterized tests in a library and let
+other people instantiate them later. This pattern is known as *abstract tests*.
+As an example of its application, when you are designing an interface you can
+write a standard suite of abstract tests (perhaps using a factory function as
+the test parameter) that all implementations of the interface are expected to
+pass. When someone implements the interface, they can instantiate your suite to
+get all the interface-conformance tests for free.
+
+To define abstract tests, you should organize your code like this:
+
+1.  Put the definition of the parameterized test fixture class (e.g. `FooTest`)
+    in a header file, say `foo_param_test.h`. Think of this as *declaring* your
+    abstract tests.
+2.  Put the `TEST_P` definitions in `foo_param_test.cc`, which includes
+    `foo_param_test.h`. Think of this as *implementing* your abstract tests.
+
+Once they are defined, you can instantiate them by including `foo_param_test.h`,
+invoking `INSTANTIATE_TEST_SUITE_P()`, and depending on the library target that
+contains `foo_param_test.cc`. You can instantiate the same abstract test suite
+multiple times, possibly in different source files.
+
+### Specifying Names for Value-Parameterized Test Parameters
+
+The optional last argument to `INSTANTIATE_TEST_SUITE_P()` allows the user to
+specify a function or functor that generates custom test name suffixes based on
+the test parameters. The function should accept one argument of type
+`testing::TestParamInfo<class ParamType>`, and return `std::string`.
+
+`testing::PrintToStringParamName` is a builtin test suffix generator that
+returns the value of `testing::PrintToString(GetParam())`. It does not work for
+`std::string` or C strings.
+
+{: .callout .note}
+NOTE: test names must be non-empty, unique, and may only contain ASCII
+alphanumeric characters. In particular, they
+[should not contain underscores](faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore)
+
+```c++
+class MyTestSuite : public testing::TestWithParam<int> {};
+
+TEST_P(MyTestSuite, MyTest)
+{
+  std::cout << "Example Test Param: " << GetParam() << std::endl;
+}
+
+INSTANTIATE_TEST_SUITE_P(MyGroup, MyTestSuite, testing::Range(0, 10),
+                         testing::PrintToStringParamName());
+```
+
+Providing a custom functor allows for more control over test parameter name
+generation, especially for types where the automatic conversion does not
+generate helpful parameter names (e.g. strings as demonstrated above). The
+following example illustrates this for multiple parameters, an enumeration type
+and a string, and also demonstrates how to combine generators. It uses a lambda
+for conciseness:
+
+```c++
+enum class MyType { MY_FOO = 0, MY_BAR = 1 };
+
+class MyTestSuite : public testing::TestWithParam<std::tuple<MyType, std::string>> {
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    MyGroup, MyTestSuite,
+    testing::Combine(
+        testing::Values(MyType::MY_FOO, MyType::MY_BAR),
+        testing::Values("A", "B")),
+    [](const testing::TestParamInfo<MyTestSuite::ParamType>& info) {
+      std::string name = absl::StrCat(
+          std::get<0>(info.param) == MyType::MY_FOO ? "Foo" : "Bar",
+          std::get<1>(info.param));
+      absl::c_replace_if(name, [](char c) { return !std::isalnum(c); }, '_');
+      return name;
+    });
+```
+
+## Typed Tests
+
+Suppose you have multiple implementations of the same interface and want to make
+sure that all of them satisfy some common requirements. Or, you may have defined
+several types that are supposed to conform to the same "concept" and you want to
+verify it. In both cases, you want the same test logic repeated for different
+types.
+
+While you can write one `TEST` or `TEST_F` for each type you want to test (and
+you may even factor the test logic into a function template that you invoke from
+the `TEST`), it's tedious and doesn't scale: if you want `m` tests over `n`
+types, you'll end up writing `m*n` `TEST`s.
+
+*Typed tests* allow you to repeat the same test logic over a list of types. You
+only need to write the test logic once, although you must know the type list
+when writing typed tests. Here's how you do it:
+
+First, define a fixture class template. It should be parameterized by a type.
+Remember to derive it from `::testing::Test`:
+
+```c++
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  using List = std::list<T>;
+  static T shared_;
+  T value_;
+};
+```
+
+Next, associate a list of types with the test suite, which will be repeated for
+each type in the list:
+
+```c++
+using MyTypes = ::testing::Types<char, int, unsigned int>;
+TYPED_TEST_SUITE(FooTest, MyTypes);
+```
+
+The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE`
+macro to parse correctly. Otherwise the compiler will think that each comma in
+the type list introduces a new macro argument.
+
+Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test for this
+test suite. You can repeat this as many times as you want:
+
+```c++
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the 'TestFixture::'
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+  // prefix.  The 'typename' is required to satisfy the compiler.
+  typename TestFixture::List values;
+
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+```
+
+You can see [sample6_unittest.cc] for a complete example.
+
+[sample6_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample6_unittest.cc "Typed Test example"
+
+## Type-Parameterized Tests
+
+*Type-parameterized tests* are like typed tests, except that they don't require
+you to know the list of types ahead of time. Instead, you can define the test
+logic first and instantiate it with different type lists later. You can even
+instantiate it more than once in the same program.
+
+If you are designing an interface or concept, you can define a suite of
+type-parameterized tests to verify properties that any valid implementation of
+the interface/concept should have. Then, the author of each implementation can
+just instantiate the test suite with their type to verify that it conforms to
+the requirements, without having to write similar tests repeatedly. Here's an
+example:
+
+First, define a fixture class template, as we did with typed tests:
+
+```c++
+template <typename T>
+class FooTest : public testing::Test {
+  void DoSomethingInteresting();
+  ...
+};
+```
+
+Next, declare that you will define a type-parameterized test suite:
+
+```c++
+TYPED_TEST_SUITE_P(FooTest);
+```
+
+Then, use `TYPED_TEST_P()` to define a type-parameterized test. You can repeat
+this as many times as you want:
+
+```c++
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+
+  // You will need to use `this` explicitly to refer to fixture members.
+  this->DoSomethingInteresting()
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+```
+
+Now the tricky part: you need to register all test patterns using the
+`REGISTER_TYPED_TEST_SUITE_P` macro before you can instantiate them. The first
+argument of the macro is the test suite name; the rest are the names of the
+tests in this test suite:
+
+```c++
+REGISTER_TYPED_TEST_SUITE_P(FooTest,
+                            DoesBlah, HasPropertyA);
+```
+
+Finally, you are free to instantiate the pattern with the types you want. If you
+put the above code in a header file, you can `#include` it in multiple C++
+source files and instantiate it multiple times.
+
+```c++
+using MyTypes = ::testing::Types<char, int, unsigned int>;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
+```
+
+To distinguish different instances of the pattern, the first argument to the
+`INSTANTIATE_TYPED_TEST_SUITE_P` macro is a prefix that will be added to the
+actual test suite name. Remember to pick unique prefixes for different
+instances.
+
+In the special case where the type list contains only one type, you can write
+that type directly without `::testing::Types<...>`, like this:
+
+```c++
+INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
+```
+
+You can see [sample6_unittest.cc] for a complete example.
+
+## Testing Private Code
+
+If you change your software's internal implementation, your tests should not
+break as long as the change is not observable by users. Therefore, **per the
+black-box testing principle, most of the time you should test your code through
+its public interfaces.**
+
+**If you still find yourself needing to test internal implementation code,
+consider if there's a better design.** The desire to test internal
+implementation is often a sign that the class is doing too much. Consider
+extracting an implementation class, and testing it. Then use that implementation
+class in the original class.
+
+If you absolutely have to test non-public interface code though, you can. There
+are two cases to consider:
+
+*   Static functions ( *not* the same as static member functions!) or unnamed
+    namespaces, and
+*   Private or protected class members
+
+To test them, we use the following special techniques:
+
+*   Both static functions and definitions/declarations in an unnamed namespace
+    are only visible within the same translation unit. To test them, you can
+    `#include` the entire `.cc` file being tested in your `*_test.cc` file.
+    (#including `.cc` files is not a good way to reuse code - you should not do
+    this in production code!)
+
+    However, a better approach is to move the private code into the
+    `foo::internal` namespace, where `foo` is the namespace your project
+    normally uses, and put the private declarations in a `*-internal.h` file.
+    Your production `.cc` files and your tests are allowed to include this
+    internal header, but your clients are not. This way, you can fully test your
+    internal implementation without leaking it to your clients.
+
+*   Private class members are only accessible from within the class or by
+    friends. To access a class' private members, you can declare your test
+    fixture as a friend to the class and define accessors in your fixture. Tests
+    using the fixture can then access the private members of your production
+    class via the accessors in the fixture. Note that even though your fixture
+    is a friend to your production class, your tests are not automatically
+    friends to it, as they are technically defined in sub-classes of the
+    fixture.
+
+    Another way to test private members is to refactor them into an
+    implementation class, which is then declared in a `*-internal.h` file. Your
+    clients aren't allowed to include this header but your tests can. Such is
+    called the
+    [Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/)
+    (Private Implementation) idiom.
+
+    Or, you can declare an individual test as a friend of your class by adding
+    this line in the class body:
+
+    ```c++
+        FRIEND_TEST(TestSuiteName, TestName);
+    ```
+
+    For example,
+
+    ```c++
+    // foo.h
+    class Foo {
+      ...
+     private:
+      FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
+
+      int Bar(void* x);
+    };
+
+    // foo_test.cc
+    ...
+    TEST(FooTest, BarReturnsZeroOnNull) {
+      Foo foo;
+      EXPECT_EQ(foo.Bar(NULL), 0);  // Uses Foo's private member Bar().
+    }
+    ```
+
+    Pay special attention when your class is defined in a namespace. If you want
+    your test fixtures and tests to be friends of your class, then they must be
+    defined in the exact same namespace (no anonymous or inline namespaces).
+
+    For example, if the code to be tested looks like:
+
+    ```c++
+    namespace my_namespace {
+
+    class Foo {
+      friend class FooTest;
+      FRIEND_TEST(FooTest, Bar);
+      FRIEND_TEST(FooTest, Baz);
+      ... definition of the class Foo ...
+    };
+
+    }  // namespace my_namespace
+    ```
+
+    Your test code should be something like:
+
+    ```c++
+    namespace my_namespace {
+
+    class FooTest : public testing::Test {
+     protected:
+      ...
+    };
+
+    TEST_F(FooTest, Bar) { ... }
+    TEST_F(FooTest, Baz) { ... }
+
+    }  // namespace my_namespace
+    ```
+
+## "Catching" Failures
+
+If you are building a testing utility on top of GoogleTest, you'll want to test
+your utility. What framework would you use to test it? GoogleTest, of course.
+
+The challenge is to verify that your testing utility reports failures correctly.
+In frameworks that report a failure by throwing an exception, you could catch
+the exception and assert on it. But GoogleTest doesn't use exceptions, so how do
+we test that a piece of code generates an expected failure?
+
+`"gtest/gtest-spi.h"` contains some constructs to do this.
+After #including this header, you can use
+
+```c++
+  EXPECT_FATAL_FAILURE(statement, substring);
+```
+
+to assert that `statement` generates a fatal (e.g. `ASSERT_*`) failure in the
+current thread whose message contains the given `substring`, or use
+
+```c++
+  EXPECT_NONFATAL_FAILURE(statement, substring);
+```
+
+if you are expecting a non-fatal (e.g. `EXPECT_*`) failure.
+
+Only failures in the current thread are checked to determine the result of this
+type of expectations. If `statement` creates new threads, failures in these
+threads are also ignored. If you want to catch failures in other threads as
+well, use one of the following macros instead:
+
+```c++
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substring);
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substring);
+```
+
+{: .callout .note}
+NOTE: Assertions from multiple threads are currently not supported on Windows.
+
+For technical reasons, there are some caveats:
+
+1.  You cannot stream a failure message to either macro.
+
+2.  `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()` cannot reference
+    local non-static variables or non-static members of `this` object.
+
+3.  `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()` cannot return a
+    value.
+
+## Registering tests programmatically
+
+The `TEST` macros handle the vast majority of all use cases, but there are few
+where runtime registration logic is required. For those cases, the framework
+provides the `::testing::RegisterTest` that allows callers to register arbitrary
+tests dynamically.
+
+This is an advanced API only to be used when the `TEST` macros are insufficient.
+The macros should be preferred when possible, as they avoid most of the
+complexity of calling this function.
+
+It provides the following signature:
+
+```c++
+template <typename Factory>
+TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
+                       const char* type_param, const char* value_param,
+                       const char* file, int line, Factory factory);
+```
+
+The `factory` argument is a factory callable (move-constructible) object or
+function pointer that creates a new instance of the Test object. It handles
+ownership to the caller. The signature of the callable is `Fixture*()`, where
+`Fixture` is the test fixture class for the test. All tests registered with the
+same `test_suite_name` must return the same fixture type. This is checked at
+runtime.
+
+The framework will infer the fixture class from the factory and will call the
+`SetUpTestSuite` and `TearDownTestSuite` for it.
+
+Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is
+undefined.
+
+Use case example:
+
+```c++
+class MyFixture : public testing::Test {
+ public:
+  // All of these optional, just like in regular macro usage.
+  static void SetUpTestSuite() { ... }
+  static void TearDownTestSuite() { ... }
+  void SetUp() override { ... }
+  void TearDown() override { ... }
+};
+
+class MyTest : public MyFixture {
+ public:
+  explicit MyTest(int data) : data_(data) {}
+  void TestBody() override { ... }
+
+ private:
+  int data_;
+};
+
+void RegisterMyTests(const std::vector<int>& values) {
+  for (int v : values) {
+    testing::RegisterTest(
+        "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr,
+        std::to_string(v).c_str(),
+        __FILE__, __LINE__,
+        // Important to use the fixture type as the return type here.
+        [=]() -> MyFixture* { return new MyTest(v); });
+  }
+}
+...
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  std::vector<int> values_to_test = LoadValuesFromConfig();
+  RegisterMyTests(values_to_test);
+  ...
+  return RUN_ALL_TESTS();
+}
+```
+
+## Getting the Current Test's Name
+
+Sometimes a function may need to know the name of the currently running test.
+For example, you may be using the `SetUp()` method of your test fixture to set
+the golden file name based on which test is running. The
+[`TestInfo`](reference/testing.md#TestInfo) class has this information.
+
+To obtain a `TestInfo` object for the currently running test, call
+`current_test_info()` on the [`UnitTest`](reference/testing.md#UnitTest)
+singleton object:
+
+```c++
+  // Gets information about the currently running test.
+  // Do NOT delete the returned object - it's managed by the UnitTest class.
+  const testing::TestInfo* const test_info =
+      testing::UnitTest::GetInstance()->current_test_info();
+
+  printf("We are in test %s of test suite %s.\n",
+         test_info->name(),
+         test_info->test_suite_name());
+```
+
+`current_test_info()` returns a null pointer if no test is running. In
+particular, you cannot find the test suite name in `SetUpTestSuite()`,
+`TearDownTestSuite()` (where you know the test suite name implicitly), or
+functions called from them.
+
+## Extending GoogleTest by Handling Test Events
+
+GoogleTest provides an **event listener API** to let you receive notifications
+about the progress of a test program and test failures. The events you can
+listen to include the start and end of the test program, a test suite, or a test
+method, among others. You may use this API to augment or replace the standard
+console output, replace the XML output, or provide a completely different form
+of output, such as a GUI or a database. You can also use test events as
+checkpoints to implement a resource leak checker, for example.
+
+### Defining Event Listeners
+
+To define a event listener, you subclass either
+[`testing::TestEventListener`](reference/testing.md#TestEventListener) or
+[`testing::EmptyTestEventListener`](reference/testing.md#EmptyTestEventListener)
+The former is an (abstract) interface, where *each pure virtual method can be
+overridden to handle a test event* (For example, when a test starts, the
+`OnTestStart()` method will be called.). The latter provides an empty
+implementation of all methods in the interface, such that a subclass only needs
+to override the methods it cares about.
+
+When an event is fired, its context is passed to the handler function as an
+argument. The following argument types are used:
+
+*   UnitTest reflects the state of the entire test program,
+*   TestSuite has information about a test suite, which can contain one or more
+    tests,
+*   TestInfo contains the state of a test, and
+*   TestPartResult represents the result of a test assertion.
+
+An event handler function can examine the argument it receives to find out
+interesting information about the event and the test program's state.
+
+Here's an example:
+
+```c++
+  class MinimalistPrinter : public testing::EmptyTestEventListener {
+    // Called before a test starts.
+    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().
+    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(),
+             test_part_result.line_number(),
+             test_part_result.summary());
+    }
+
+    // Called after a test ends.
+    void OnTestEnd(const testing::TestInfo& test_info) override {
+      printf("*** Test %s.%s ending.\n",
+             test_info.test_suite_name(), test_info.name());
+    }
+  };
+```
+
+### Using Event Listeners
+
+To use the event listener you have defined, add an instance of it to the
+GoogleTest event listener list (represented by class
+[`TestEventListeners`](reference/testing.md#TestEventListeners) - note the "s"
+at the end of the name) in your `main()` function, before calling
+`RUN_ALL_TESTS()`:
+
+```c++
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  // Gets hold of the event listener list.
+  testing::TestEventListeners& listeners =
+      testing::UnitTest::GetInstance()->listeners();
+  // Adds a listener to the end.  GoogleTest takes the ownership.
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+}
+```
+
+There's only one problem: the default test result printer is still in effect, so
+its output will mingle with the output from your minimalist printer. To suppress
+the default printer, just release it from the event listener list and delete it.
+You can do so by adding one line:
+
+```c++
+  ...
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+```
+
+Now, sit back and enjoy a completely different output from your tests. For more
+details, see [sample9_unittest.cc].
+
+[sample9_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample9_unittest.cc "Event listener example"
+
+You may append more than one listener to the list. When an `On*Start()` or
+`OnTestPartResult()` event is fired, the listeners will receive it in the order
+they appear in the list (since new listeners are added to the end of the list,
+the default text printer and the default XML generator will receive the event
+first). An `On*End()` event will be received by the listeners in the *reverse*
+order. This allows output by listeners added later to be framed by output from
+listeners added earlier.
+
+### Generating Failures in Listeners
+
+You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`, `FAIL()`, etc)
+when processing an event. There are some restrictions:
+
+1.  You cannot generate any failure in `OnTestPartResult()` (otherwise it will
+    cause `OnTestPartResult()` to be called recursively).
+2.  A listener that handles `OnTestPartResult()` is not allowed to generate any
+    failure.
+
+When you add listeners to the listener list, you should put listeners that
+handle `OnTestPartResult()` *before* listeners that can generate failures. This
+ensures that failures generated by the latter are attributed to the right test
+by the former.
+
+See [sample10_unittest.cc] for an example of a failure-raising listener.
+
+[sample10_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample10_unittest.cc "Failure-raising listener example"
+
+## Running Test Programs: Advanced Options
+
+GoogleTest test programs are ordinary executables. Once built, you can run them
+directly and affect their behavior via the following environment variables
+and/or command line flags. For the flags to work, your programs must call
+`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
+
+To see a list of supported flags and their usage, please run your test program
+with the `--help` flag.
+
+If an option is specified both by an environment variable and by a flag, the
+latter takes precedence.
+
+### Selecting Tests
+
+#### Listing Test Names
+
+Sometimes it is necessary to list the available tests in a program before
+running them so that a filter may be applied if needed. Including the flag
+`--gtest_list_tests` overrides all other flags and lists tests in the following
+format:
+
+```none
+TestSuite1.
+  TestName1
+  TestName2
+TestSuite2.
+  TestName
+```
+
+None of the tests listed are actually run if the flag is provided. There is no
+corresponding environment variable for this flag.
+
+#### Running a Subset of the Tests
+
+By default, a GoogleTest program runs all tests the user has defined. Sometimes,
+you want to run only a subset of the tests (e.g. for debugging or quickly
+verifying a change). If you set the `GTEST_FILTER` environment variable or the
+`--gtest_filter` flag to a filter string, GoogleTest will only run the tests
+whose full names (in the form of `TestSuiteName.TestName`) match the filter.
+
+The format of a filter is a '`:`'-separated list of wildcard patterns (called
+the *positive patterns*) optionally followed by a '`-`' and another
+'`:`'-separated pattern list (called the *negative patterns*). A test matches
+the filter if and only if it matches any of the positive patterns but does not
+match any of the negative patterns.
+
+A pattern may contain `'*'` (matches any string) or `'?'` (matches any single
+character). For convenience, the filter `'*-NegativePatterns'` can be also
+written as `'-NegativePatterns'`.
+
+For example:
+
+*   `./foo_test` Has no flag, and thus runs all its tests.
+*   `./foo_test --gtest_filter=*` Also runs everything, due to the single
+    match-everything `*` value.
+*   `./foo_test --gtest_filter=FooTest.*` Runs everything in test suite
+    `FooTest` .
+*   `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full
+    name contains either `"Null"` or `"Constructor"` .
+*   `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests.
+*   `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test
+    suite `FooTest` except `FooTest.Bar`.
+*   `./foo_test --gtest_filter=FooTest.*:BarTest.*-FooTest.Bar:BarTest.Foo` Runs
+    everything in test suite `FooTest` except `FooTest.Bar` and everything in
+    test suite `BarTest` except `BarTest.Foo`.
+
+#### Stop test execution upon first failure
+
+By default, a GoogleTest program runs all tests the user has defined. In some
+cases (e.g. iterative test development & execution) it may be desirable stop
+test execution upon first failure (trading improved latency for completeness).
+If `GTEST_FAIL_FAST` environment variable or `--gtest_fail_fast` flag is set,
+the test runner will stop execution as soon as the first test failure is found.
+
+#### Temporarily Disabling Tests
+
+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).
+
+If you need to disable all tests in a test suite, you can either add `DISABLED_`
+to the front of the name of each test, or alternatively add it to the front of
+the test suite name.
+
+For example, the following tests won't be run by GoogleTest, even though they
+will still be compiled:
+
+```c++
+// Tests that Foo does Abc.
+TEST(FooTest, DISABLED_DoesAbc) { ... }
+
+class DISABLED_BarTest : public testing::Test { ... };
+
+// Tests that Bar does Xyz.
+TEST_F(DISABLED_BarTest, DoesXyz) { ... }
+```
+
+{: .callout .note}
+NOTE: This feature should only be used for temporary pain-relief. You still have
+to fix the disabled tests at a later date. As a reminder, GoogleTest will print
+a banner warning you if a test program contains any disabled tests.
+
+{: .callout .tip}
+TIP: You can easily count the number of disabled tests you have using
+`grep`. This number can be used as a metric for
+improving your test quality.
+
+#### Temporarily Enabling Disabled Tests
+
+To include disabled tests in test execution, just invoke the test program with
+the `--gtest_also_run_disabled_tests` flag or set the
+`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other than `0`.
+You can combine this with the `--gtest_filter` flag to further select which
+disabled tests to run.
+
+### Repeating the Tests
+
+Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
+will fail only 1% of the time, making it rather hard to reproduce the bug under
+a debugger. This can be a major source of frustration.
+
+The `--gtest_repeat` flag allows you to repeat all (or selected) test methods in
+a program many times. Hopefully, a flaky test will eventually fail and give you
+a chance to debug. Here's how to use it:
+
+```none
+$ foo_test --gtest_repeat=1000
+Repeat foo_test 1000 times and don't stop at failures.
+
+$ foo_test --gtest_repeat=-1
+A negative count means repeating forever.
+
+$ foo_test --gtest_repeat=1000 --gtest_break_on_failure
+Repeat foo_test 1000 times, stopping at the first failure.  This
+is especially useful when running under a debugger: when the test
+fails, it will drop into the debugger and you can then inspect
+variables and stacks.
+
+$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar.*
+Repeat the tests whose name matches the filter 1000 times.
+```
+
+If your test program contains
+[global set-up/tear-down](#global-set-up-and-tear-down) code, it will be
+repeated in each iteration as well, as the flakiness may be in it. To avoid
+repeating global set-up/tear-down, specify
+`--gtest_recreate_environments_when_repeating=false`{.nowrap}.
+
+You can also specify the repeat count by setting the `GTEST_REPEAT` environment
+variable.
+
+### Shuffling the Tests
+
+You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE`
+environment variable to `1`) to run the tests in a program in a random order.
+This helps to reveal bad dependencies between tests.
+
+By default, GoogleTest uses a random seed calculated from the current time.
+Therefore you'll get a different order every time. The console output includes
+the random seed value, such that you can reproduce an order-related test failure
+later. To specify the random seed explicitly, use the `--gtest_random_seed=SEED`
+flag (or set the `GTEST_RANDOM_SEED` environment variable), where `SEED` is an
+integer in the range [0, 99999]. The seed value 0 is special: it tells
+GoogleTest to do the default behavior of calculating the seed from the current
+time.
+
+If you combine this with `--gtest_repeat=N`, GoogleTest will pick a different
+random seed and re-shuffle the tests in each iteration.
+
+### Distributing Test Functions to Multiple Machines
+
+If you have more than one machine you can use to run a test program, you might
+want to run the test functions in parallel and get the result faster. We call
+this technique *sharding*, where each machine is called a *shard*.
+
+GoogleTest is compatible with test sharding. To take advantage of this feature,
+your test runner (not part of GoogleTest) needs to do the following:
+
+1.  Allocate a number of machines (shards) to run the tests.
+1.  On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total
+    number of shards. It must be the same for all shards.
+1.  On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index
+    of the shard. Different shards must be assigned different indices, which
+    must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`.
+1.  Run the same test program on all shards. When GoogleTest sees the above two
+    environment variables, it will select a subset of the test functions to run.
+    Across all shards, each test function in the program will be run exactly
+    once.
+1.  Wait for all shards to finish, then collect and report the results.
+
+Your project may have tests that were written without GoogleTest and thus don't
+understand this protocol. In order for your test runner to figure out which test
+supports sharding, it can set the environment variable `GTEST_SHARD_STATUS_FILE`
+to a non-existent file path. If a test program supports sharding, it will create
+this file to acknowledge that fact; otherwise it will not create it. The actual
+contents of the file are not important at this time, although we may put some
+useful information in it in the future.
+
+Here's an example to make it clear. Suppose you have a test program `foo_test`
+that contains the following 5 test functions:
+
+```
+TEST(A, V)
+TEST(A, W)
+TEST(B, X)
+TEST(B, Y)
+TEST(B, Z)
+```
+
+Suppose you have 3 machines at your disposal. To run the test functions in
+parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and set
+`GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively. Then you would
+run the same `foo_test` on each machine.
+
+GoogleTest reserves the right to change how the work is distributed across the
+shards, but here's one possible scenario:
+
+*   Machine #0 runs `A.V` and `B.X`.
+*   Machine #1 runs `A.W` and `B.Y`.
+*   Machine #2 runs `B.Z`.
+
+### Controlling Test Output
+
+#### Colored Terminal Output
+
+GoogleTest can use colors in its terminal output to make it easier to spot the
+important information:
+
+<pre>...
+<font color="green">[----------]</font> 1 test from FooTest
+<font color="green">[ RUN      ]</font> FooTest.DoesAbc
+<font color="green">[       OK ]</font> FooTest.DoesAbc
+<font color="green">[----------]</font> 2 tests from BarTest
+<font color="green">[ RUN      ]</font> BarTest.HasXyzProperty
+<font color="green">[       OK ]</font> BarTest.HasXyzProperty
+<font color="green">[ RUN      ]</font> BarTest.ReturnsTrueOnSuccess
+... some error messages ...
+<font color="red">[   FAILED ]</font> BarTest.ReturnsTrueOnSuccess
+...
+<font color="green">[==========]</font> 30 tests from 14 test suites ran.
+<font color="green">[   PASSED ]</font> 28 tests.
+<font color="red">[   FAILED ]</font> 2 tests, listed below:
+<font color="red">[   FAILED ]</font> BarTest.ReturnsTrueOnSuccess
+<font color="red">[   FAILED ]</font> AnotherTest.DoesXyz
+
+ 2 FAILED TESTS
+</pre>
+
+You can set the `GTEST_COLOR` environment variable or the `--gtest_color`
+command line flag to `yes`, `no`, or `auto` (the default) to enable colors,
+disable colors, or let GoogleTest decide. When the value is `auto`, GoogleTest
+will use colors if and only if the output goes to a terminal and (on non-Windows
+platforms) the `TERM` environment variable is set to `xterm` or `xterm-color`.
+
+#### Suppressing test passes
+
+By default, GoogleTest prints 1 line of output for each test, indicating if it
+passed or failed. To show only test failures, run the test program with
+`--gtest_brief=1`, or set the GTEST_BRIEF environment variable to `1`.
+
+#### Suppressing the Elapsed Time
+
+By default, GoogleTest prints the time it takes to run each test. To disable
+that, run the test program with the `--gtest_print_time=0` command line flag, or
+set the GTEST_PRINT_TIME environment variable to `0`.
+
+#### Suppressing UTF-8 Text Output
+
+In case of assertion failures, GoogleTest prints expected and actual values of
+type `string` both as hex-encoded strings as well as in readable UTF-8 text if
+they contain valid non-ASCII UTF-8 characters. If you want to suppress the UTF-8
+text because, for example, you don't have an UTF-8 compatible output medium, run
+the test program with `--gtest_print_utf8=0` or set the `GTEST_PRINT_UTF8`
+environment variable to `0`.
+
+#### Generating an XML Report
+
+GoogleTest can emit a detailed XML report to a file in addition to its normal
+textual output. The report contains the duration of each test, and thus can help
+you identify slow tests.
+
+To generate the XML report, set the `GTEST_OUTPUT` environment variable or the
+`--gtest_output` flag to the string `"xml:path_to_output_file"`, which will
+create the file at the given location. You can also just use the string `"xml"`,
+in which case the output can be found in the `test_detail.xml` file in the
+current directory.
+
+If you specify a directory (for example, `"xml:output/directory/"` on Linux or
+`"xml:output\directory\"` on Windows), GoogleTest will create the XML file in
+that directory, named after the test executable (e.g. `foo_test.xml` for test
+program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left
+over from a previous run), GoogleTest will pick a different name (e.g.
+`foo_test_1.xml`) to avoid overwriting it.
+
+The report is based on the `junitreport` Ant task. Since that format was
+originally intended for Java, a little interpretation is required to make it
+apply to GoogleTest tests, as shown here:
+
+```xml
+<testsuites name="AllTests" ...>
+  <testsuite name="test_case_name" ...>
+    <testcase    name="test_name" ...>
+      <failure message="..."/>
+      <failure message="..."/>
+      <failure message="..."/>
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+*   The root `<testsuites>` element corresponds to the entire test program.
+*   `<testsuite>` elements correspond to GoogleTest test suites.
+*   `<testcase>` elements correspond to GoogleTest test functions.
+
+For instance, the following program
+
+```c++
+TEST(MathTest, Addition) { ... }
+TEST(MathTest, Subtraction) { ... }
+TEST(LogicTest, NonContradiction) { ... }
+```
+
+could generate this report:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="3" failures="1" errors="0" time="0.035" timestamp="2011-10-31T18:52:42" name="AllTests">
+  <testsuite name="MathTest" tests="2" failures="1" errors="0" time="0.015">
+    <testcase name="Addition" file="test.cpp" line="1" status="run" time="0.007" classname="">
+      <failure message="Value of: add(1, 1)&#x0A;  Actual: 3&#x0A;Expected: 2" type="">...</failure>
+      <failure message="Value of: add(1, -1)&#x0A;  Actual: 1&#x0A;Expected: 0" type="">...</failure>
+    </testcase>
+    <testcase name="Subtraction" file="test.cpp" line="2" status="run" time="0.005" classname="">
+    </testcase>
+  </testsuite>
+  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="0.005">
+    <testcase name="NonContradiction" file="test.cpp" line="3" status="run" time="0.005" classname="">
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+Things to note:
+
+*   The `tests` attribute of a `<testsuites>` or `<testsuite>` element tells how
+    many test functions the GoogleTest program or test suite contains, while the
+    `failures` attribute tells how many of them failed.
+
+*   The `time` attribute expresses the duration of the test, test suite, or
+    entire test program in seconds.
+
+*   The `timestamp` attribute records the local date and time of the test
+    execution.
+
+*   The `file` and `line` attributes record the source file location, where the
+    test was defined.
+
+*   Each `<failure>` element corresponds to a single failed GoogleTest
+    assertion.
+
+#### Generating a JSON Report
+
+GoogleTest can also emit a JSON report as an alternative format to XML. To
+generate the JSON report, set the `GTEST_OUTPUT` environment variable or the
+`--gtest_output` flag to the string `"json:path_to_output_file"`, which will
+create the file at the given location. You can also just use the string
+`"json"`, in which case the output can be found in the `test_detail.json` file
+in the current directory.
+
+The report format conforms to the following JSON Schema:
+
+```json
+{
+  "$schema": "https://json-schema.org/schema#",
+  "type": "object",
+  "definitions": {
+    "TestCase": {
+      "type": "object",
+      "properties": {
+        "name": { "type": "string" },
+        "tests": { "type": "integer" },
+        "failures": { "type": "integer" },
+        "disabled": { "type": "integer" },
+        "time": { "type": "string" },
+        "testsuite": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/TestInfo"
+          }
+        }
+      }
+    },
+    "TestInfo": {
+      "type": "object",
+      "properties": {
+        "name": { "type": "string" },
+        "file": { "type": "string" },
+        "line": { "type": "integer" },
+        "status": {
+          "type": "string",
+          "enum": ["RUN", "NOTRUN"]
+        },
+        "time": { "type": "string" },
+        "classname": { "type": "string" },
+        "failures": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/Failure"
+          }
+        }
+      }
+    },
+    "Failure": {
+      "type": "object",
+      "properties": {
+        "failures": { "type": "string" },
+        "type": { "type": "string" }
+      }
+    }
+  },
+  "properties": {
+    "tests": { "type": "integer" },
+    "failures": { "type": "integer" },
+    "disabled": { "type": "integer" },
+    "errors": { "type": "integer" },
+    "timestamp": {
+      "type": "string",
+      "format": "date-time"
+    },
+    "time": { "type": "string" },
+    "name": { "type": "string" },
+    "testsuites": {
+      "type": "array",
+      "items": {
+        "$ref": "#/definitions/TestCase"
+      }
+    }
+  }
+}
+```
+
+The report uses the format that conforms to the following Proto3 using the
+[JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json):
+
+```proto
+syntax = "proto3";
+
+package googletest;
+
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/duration.proto";
+
+message UnitTest {
+  int32 tests = 1;
+  int32 failures = 2;
+  int32 disabled = 3;
+  int32 errors = 4;
+  google.protobuf.Timestamp timestamp = 5;
+  google.protobuf.Duration time = 6;
+  string name = 7;
+  repeated TestCase testsuites = 8;
+}
+
+message TestCase {
+  string name = 1;
+  int32 tests = 2;
+  int32 failures = 3;
+  int32 disabled = 4;
+  int32 errors = 5;
+  google.protobuf.Duration time = 6;
+  repeated TestInfo testsuite = 7;
+}
+
+message TestInfo {
+  string name = 1;
+  string file = 6;
+  int32 line = 7;
+  enum Status {
+    RUN = 0;
+    NOTRUN = 1;
+  }
+  Status status = 2;
+  google.protobuf.Duration time = 3;
+  string classname = 4;
+  message Failure {
+    string failures = 1;
+    string type = 2;
+  }
+  repeated Failure failures = 5;
+}
+```
+
+For instance, the following program
+
+```c++
+TEST(MathTest, Addition) { ... }
+TEST(MathTest, Subtraction) { ... }
+TEST(LogicTest, NonContradiction) { ... }
+```
+
+could generate this report:
+
+```json
+{
+  "tests": 3,
+  "failures": 1,
+  "errors": 0,
+  "time": "0.035s",
+  "timestamp": "2011-10-31T18:52:42Z",
+  "name": "AllTests",
+  "testsuites": [
+    {
+      "name": "MathTest",
+      "tests": 2,
+      "failures": 1,
+      "errors": 0,
+      "time": "0.015s",
+      "testsuite": [
+        {
+          "name": "Addition",
+          "file": "test.cpp",
+          "line": 1,
+          "status": "RUN",
+          "time": "0.007s",
+          "classname": "",
+          "failures": [
+            {
+              "message": "Value of: add(1, 1)\n  Actual: 3\nExpected: 2",
+              "type": ""
+            },
+            {
+              "message": "Value of: add(1, -1)\n  Actual: 1\nExpected: 0",
+              "type": ""
+            }
+          ]
+        },
+        {
+          "name": "Subtraction",
+          "file": "test.cpp",
+          "line": 2,
+          "status": "RUN",
+          "time": "0.005s",
+          "classname": ""
+        }
+      ]
+    },
+    {
+      "name": "LogicTest",
+      "tests": 1,
+      "failures": 0,
+      "errors": 0,
+      "time": "0.005s",
+      "testsuite": [
+        {
+          "name": "NonContradiction",
+          "file": "test.cpp",
+          "line": 3,
+          "status": "RUN",
+          "time": "0.005s",
+          "classname": ""
+        }
+      ]
+    }
+  ]
+}
+```
+
+{: .callout .important}
+IMPORTANT: The exact format of the JSON document is subject to change.
+
+### Controlling How Failures Are Reported
+
+#### Detecting Test Premature Exit
+
+Google Test implements the _premature-exit-file_ protocol for test runners to
+catch any kind of unexpected exits of test programs. Upon start, Google Test
+creates the file which will be automatically deleted after all work has been
+finished. Then, the test runner can check if this file exists. In case the file
+remains undeleted, the inspected test has exited prematurely.
+
+This feature is enabled only if the `TEST_PREMATURE_EXIT_FILE` environment
+variable has been set.
+
+#### Turning Assertion Failures into Break-Points
+
+When running test programs under a debugger, it's very convenient if the
+debugger can catch an assertion failure and automatically drop into interactive
+mode. GoogleTest's *break-on-failure* mode supports this behavior.
+
+To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value
+other than `0`. Alternatively, you can use the `--gtest_break_on_failure`
+command line flag.
+
+#### Disabling Catching Test-Thrown Exceptions
+
+GoogleTest can be used either with or without exceptions enabled. If a test
+throws a C++ exception or (on Windows) a structured exception (SEH), by default
+GoogleTest catches it, reports it as a test failure, and continues with the next
+test method. This maximizes the coverage of a test run. Also, on Windows an
+uncaught exception will cause a pop-up window, so catching the exceptions allows
+you to run the tests automatically.
+
+When debugging the test failures, however, you may instead want the exceptions
+to be handled by the debugger, such that you can examine the call stack when an
+exception is thrown. To achieve that, set the `GTEST_CATCH_EXCEPTIONS`
+environment variable to `0`, or use the `--gtest_catch_exceptions=0` flag when
+running the tests.
+
+### Sanitizer Integration
+
+The
+[Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html),
+[Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer),
+and
+[Thread Sanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
+all provide weak functions that you can override to trigger explicit failures
+when they detect sanitizer errors, such as creating a reference from `nullptr`.
+To override these functions, place definitions for them in a source file that
+you compile as part of your main binary:
+
+```
+extern "C" {
+void __ubsan_on_report() {
+  FAIL() << "Encountered an undefined behavior sanitizer error";
+}
+void __asan_on_error() {
+  FAIL() << "Encountered an address sanitizer error";
+}
+void __tsan_on_report() {
+  FAIL() << "Encountered a thread sanitizer error";
+}
+}  // extern "C"
+```
+
+After compiling your project with one of the sanitizers enabled, if a particular
+test triggers a sanitizer error, GoogleTest will report that it failed.
diff --git a/3rd-party/googletest/docs/assets/css/style.scss b/3rd-party/googletest/docs/assets/css/style.scss
new file mode 100644
index 0000000..bb30f41
--- /dev/null
+++ b/3rd-party/googletest/docs/assets/css/style.scss
@@ -0,0 +1,5 @@
+---
+---
+
+@import "jekyll-theme-primer";
+@import "main";
diff --git a/3rd-party/googletest/docs/community_created_documentation.md b/3rd-party/googletest/docs/community_created_documentation.md
new file mode 100644
index 0000000..4569075
--- /dev/null
+++ b/3rd-party/googletest/docs/community_created_documentation.md
@@ -0,0 +1,7 @@
+# Community-Created Documentation
+
+The following is a list, in no particular order, of links to documentation
+created by the Googletest community.
+
+*   [Googlemock Insights](https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/googletest/insights.md),
+    by [ElectricRCAircraftGuy](https://github.com/ElectricRCAircraftGuy)
diff --git a/3rd-party/googletest/docs/faq.md b/3rd-party/googletest/docs/faq.md
new file mode 100644
index 0000000..c7d10b5
--- /dev/null
+++ b/3rd-party/googletest/docs/faq.md
@@ -0,0 +1,671 @@
+# GoogleTest FAQ
+
+## Why should test suite names and test names not contain underscore?
+
+{: .callout .note}
+Note: GoogleTest reserves underscore (`_`) for special-purpose keywords, such as
+[the `DISABLED_` prefix](advanced.md#temporarily-disabling-tests), in addition
+to the following rationale.
+
+Underscore (`_`) is special, as C++ reserves the following to be used by the
+compiler and the standard library:
+
+1.  any identifier that starts with an `_` followed by an upper-case letter, and
+2.  any identifier that contains two consecutive underscores (i.e. `__`)
+    *anywhere* in its name.
+
+User code is *prohibited* from using such identifiers.
+
+Now let's look at what this means for `TEST` and `TEST_F`.
+
+Currently `TEST(TestSuiteName, TestName)` generates a class named
+`TestSuiteName_TestName_Test`. What happens if `TestSuiteName` or `TestName`
+contains `_`?
+
+1.  If `TestSuiteName` starts with an `_` followed by an upper-case letter (say,
+    `_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus
+    invalid.
+2.  If `TestSuiteName` ends with an `_` (say, `Foo_`), we get
+    `Foo__TestName_Test`, which is invalid.
+3.  If `TestName` starts with an `_` (say, `_Bar`), we get
+    `TestSuiteName__Bar_Test`, which is invalid.
+4.  If `TestName` ends with an `_` (say, `Bar_`), we get
+    `TestSuiteName_Bar__Test`, which is invalid.
+
+So clearly `TestSuiteName` and `TestName` cannot start or end with `_`
+(Actually, `TestSuiteName` can start with `_`—as long as the `_` isn't followed
+by an upper-case letter. But that's getting complicated. So for simplicity we
+just say that it cannot start with `_`.).
+
+It may seem fine for `TestSuiteName` and `TestName` to contain `_` in the
+middle. However, consider this:
+
+```c++
+TEST(Time, Flies_Like_An_Arrow) { ... }
+TEST(Time_Flies, Like_An_Arrow) { ... }
+```
+
+Now, the two `TEST`s will both generate the same class
+(`Time_Flies_Like_An_Arrow_Test`). That's not good.
+
+So for simplicity, we just ask the users to avoid `_` in `TestSuiteName` and
+`TestName`. The rule is more constraining than necessary, but it's simple and
+easy to remember. It also gives GoogleTest some wiggle room in case its
+implementation needs to change in the future.
+
+If you violate the rule, there may not be immediate consequences, but your test
+may (just may) break with a new compiler (or a new version of the compiler you
+are using) or with a new version of GoogleTest. Therefore it's best to follow
+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 `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()`
+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).
+
+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)` 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'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
+significant advantage of the matcher approach is that matchers can be easily
+combined to form new matchers, while the `EXPECT_NE`, etc, macros cannot be
+easily combined. Therefore we want to invest more in the matchers than in the
+`EXPECT_XX()` macros.
+
+## I need to test that different implementations of an interface satisfy some common requirements. Should I use typed tests or value-parameterized tests?
+
+For testing various implementations of the same interface, either typed tests or
+value-parameterized tests can get it done. It's really up to you the user to
+decide which is more convenient for you, depending on your particular case. Some
+rough guidelines:
+
+*   Typed tests can be easier to write if instances of the different
+    implementations can be created the same way, modulo the type. For example,
+    if all these implementations have a public default constructor (such that
+    you can write `new TypeParam`), or if their factory functions have the same
+    form (e.g. `CreateInstance<TypeParam>()`).
+*   Value-parameterized tests can be easier to write if you need different code
+    patterns to create different implementations' instances, e.g. `new Foo` vs
+    `new Bar(5)`. To accommodate for the differences, you can write factory
+    function wrappers and pass these function pointers to the tests as their
+    parameters.
+*   When a typed test fails, the default output includes the name of the type,
+    which can help you quickly identify which implementation is wrong.
+    Value-parameterized tests only show the number of the failed iteration by
+    default. You will need to define a function that returns the iteration name
+    and pass it as the third parameter to INSTANTIATE_TEST_SUITE_P to have more
+    useful output.
+*   When using typed tests, you need to make sure you are testing against the
+    interface type, not the concrete types (in other words, you want to make
+    sure `implicit_cast<MyInterface*>(my_concrete_impl)` works, not just that
+    `my_concrete_impl` works). It's less likely to make mistakes in this area
+    when using value-parameterized tests.
+
+I hope I didn't confuse you more. :-) If you don't mind, I'd suggest you to give
+both approaches a try. Practice is a much better way to grasp the subtle
+differences between the two tools. Once you have some concrete experience, you
+can much more easily decide which one to use the next time.
+
+## My death test modifies some state, but the change seems lost after the death test finishes. Why?
+
+Death tests (`EXPECT_DEATH`, etc.) are executed in a sub-process s.t. the
+expected crash won't kill the test program (i.e. the parent process). As a
+result, any in-memory side effects they incur are observable in their respective
+sub-processes, but not in the parent process. You can think of them as running
+in a parallel universe, more or less.
+
+In particular, if you use mocking and the death test statement invokes some mock
+methods, the parent process will think the calls have never occurred. Therefore,
+you may want to move your `EXPECT_CALL` statements inside the `EXPECT_DEATH`
+macro.
+
+## EXPECT_EQ(htonl(blah), blah_blah) generates weird compiler errors in opt mode. Is this a GoogleTest bug?
+
+Actually, the bug is in `htonl()`.
+
+According to `'man htonl'`, `htonl()` is a *function*, which means it's valid to
+use `htonl` as a function pointer. However, in opt mode `htonl()` is defined as
+a *macro*, which breaks this usage.
+
+Worse, the macro definition of `htonl()` uses a `gcc` extension and is *not*
+standard C++. That hacky implementation has some ad hoc limitations. In
+particular, it prevents you from writing `Foo<sizeof(htonl(x))>()`, where `Foo`
+is a template that has an integral argument.
+
+The implementation of `EXPECT_EQ(a, b)` uses `sizeof(... a ...)` inside a
+template argument, and thus doesn't compile in opt mode when `a` contains a call
+to `htonl()`. It is difficult to make `EXPECT_EQ` bypass the `htonl()` bug, as
+the solution must work with different compilers on various platforms.
+
+## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong?
+
+If your class has a static data member:
+
+```c++
+// foo.h
+class Foo {
+  ...
+  static const int kBar = 100;
+};
+```
+
+you also need to define it *outside* of the class body in `foo.cc`:
+
+```c++
+const int Foo::kBar;  // No initializer here.
+```
+
+Otherwise your code is **invalid C++**, and may break in unexpected ways. In
+particular, using it in GoogleTest comparison assertions (`EXPECT_EQ`, etc.)
+will generate an "undefined reference" linker error. The fact that "it used to
+work" doesn't mean it's valid. It just means that you were lucky. :-)
+
+If the declaration of the static data member is `constexpr` then it is
+implicitly an `inline` definition, and a separate definition in `foo.cc` is not
+needed:
+
+```c++
+// foo.h
+class Foo {
+  ...
+  static constexpr int kBar = 100;  // Defines kBar, no need to do it in foo.cc.
+};
+```
+
+## Can I derive a test fixture from another?
+
+Yes.
+
+Each test fixture has a corresponding and same named test suite. This means only
+one test suite can use a particular fixture. Sometimes, however, multiple test
+cases may want to use the same or slightly different fixtures. For example, you
+may want to make sure that all of a GUI library's test suites don't leak
+important system resources like fonts and brushes.
+
+In GoogleTest, you share a fixture among test suites by putting the shared logic
+in a base test fixture, then deriving from that base a separate fixture for each
+test suite that wants to use this common logic. You then use `TEST_F()` to write
+tests using each derived fixture.
+
+Typically, your code looks like this:
+
+```c++
+// Defines a base test fixture.
+class BaseTest : public ::testing::Test {
+ protected:
+  ...
+};
+
+// Derives a fixture FooTest from BaseTest.
+class FooTest : public BaseTest {
+ protected:
+  void SetUp() override {
+    BaseTest::SetUp();  // Sets up the base fixture first.
+    ... additional set-up work ...
+  }
+
+  void TearDown() override {
+    ... clean-up work for FooTest ...
+    BaseTest::TearDown();  // Remember to tear down the base fixture
+                           // after cleaning up FooTest!
+  }
+
+  ... functions and variables for FooTest ...
+};
+
+// Tests that use the fixture FooTest.
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+... additional fixtures derived from BaseTest ...
+```
+
+If necessary, you can continue to derive test fixtures from a derived fixture.
+GoogleTest has no limit on how deep the hierarchy can be.
+
+For a complete example using derived test fixtures, see
+[sample5_unittest.cc](https://github.com/google/googletest/blob/main/googletest/samples/sample5_unittest.cc).
+
+## My compiler complains "void value not ignored as it ought to be." What does this mean?
+
+You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
+`ASSERT_*()` can only be used in `void` functions, due to exceptions being
+disabled by our build system. Please see more details
+[here](advanced.md#assertion-placement).
+
+## My death test hangs (or seg-faults). How do I fix it?
+
+In GoogleTest, death tests are run in a child process and the way they work is
+delicate. To write death tests you really need to understand how they work—see
+the details at [Death Assertions](reference/assertions.md#death) in the
+Assertions Reference.
+
+In particular, death tests don't like having multiple threads in the parent
+process. So the first thing you can try is to eliminate creating threads outside
+of `EXPECT_DEATH()`. For example, you may want to use mocks or fake objects
+instead of real ones in your tests.
+
+Sometimes this is impossible as some library you must use may be creating
+threads before `main()` is even reached. In this case, you can try to minimize
+the chance of conflicts by either moving as many activities as possible inside
+`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
+leaving as few things as possible in it. Also, you can try to set the death test
+style to `"threadsafe"`, which is safer but slower, and see if it helps.
+
+If you go with thread-safe death tests, remember that they rerun the test
+program from the beginning in the child process. Therefore make sure your
+program can run side-by-side with itself and is deterministic.
+
+In the end, this boils down to good concurrent programming. You have to make
+sure that there are no race conditions or deadlocks in your program. No silver
+bullet - sorry!
+
+## Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()? {#CtorVsSetUp}
+
+The first thing to remember is that GoogleTest does **not** reuse the same test
+fixture object across multiple tests. For each `TEST_F`, GoogleTest will create
+a **fresh** test fixture object, immediately call `SetUp()`, run the test body,
+call `TearDown()`, and then delete the test fixture object.
+
+When you need to write per-test set-up and tear-down logic, you have the choice
+between using the test fixture constructor/destructor or `SetUp()`/`TearDown()`.
+The former is usually preferred, as it has the following benefits:
+
+*   By initializing a member variable in the constructor, we have the option to
+    make it `const`, which helps prevent accidental changes to its value and
+    makes the tests more obviously correct.
+*   In case we need to subclass the test fixture class, the subclass'
+    constructor is guaranteed to call the base class' constructor *first*, and
+    the subclass' destructor is guaranteed to call the base class' destructor
+    *afterward*. With `SetUp()/TearDown()`, a subclass may make the mistake of
+    forgetting to call the base class' `SetUp()/TearDown()` or call them at the
+    wrong time.
+
+You may still want to use `SetUp()/TearDown()` in the following cases:
+
+*   C++ does not allow virtual function calls in constructors and destructors.
+    You can call a method declared as virtual, but it will not use dynamic
+    dispatch. It will use the definition from the class the constructor of which
+    is currently executing. This is because calling a virtual method before the
+    derived class constructor has a chance to run is very dangerous - the
+    virtual method might operate on uninitialized data. Therefore, if you need
+    to call a method that will be overridden in a derived class, you have to use
+    `SetUp()/TearDown()`.
+*   In the body of a constructor (or destructor), it's not possible to use the
+    `ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal
+    test failure that should prevent the test from running, it's necessary to
+    use `abort` and abort the whole test
+    executable, or to use `SetUp()` instead of a constructor.
+*   If the tear-down operation could throw an exception, you must use
+    `TearDown()` as opposed to the destructor, as throwing in a destructor leads
+    to undefined behavior and usually will kill your program right away. Note
+    that many standard libraries (like STL) may throw when exceptions are
+    enabled in the compiler. Therefore you should prefer `TearDown()` if you
+    want to write portable tests that work with or without exceptions.
+*   The GoogleTest team is considering making the assertion macros throw on
+    platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux
+    client-side), which will eliminate the need for the user to propagate
+    failures from a subroutine to its caller. Therefore, you shouldn't use
+    GoogleTest assertions in a destructor if your code could run on such a
+    platform.
+
+## The compiler complains "no matching function to call" when I use `ASSERT_PRED*`. How do I fix it?
+
+See details for [`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the
+Assertions Reference.
+
+## My compiler complains about "ignoring return value" when I call RUN_ALL_TESTS(). Why?
+
+Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
+instead of
+
+```c++
+  return RUN_ALL_TESTS();
+```
+
+they write
+
+```c++
+  RUN_ALL_TESTS();
+```
+
+This is **wrong and dangerous**. The testing services needs to see the return
+value of `RUN_ALL_TESTS()` in order to determine if a test has passed. If your
+`main()` function ignores it, your test will be considered successful even if it
+has a GoogleTest assertion failure. Very bad.
+
+We have decided to fix this (thanks to Michael Chastain for the idea). Now, your
+code will no longer be able to ignore `RUN_ALL_TESTS()` when compiled with
+`gcc`. If you do so, you'll get a compiler error.
+
+If you see the compiler complaining about you ignoring the return value of
+`RUN_ALL_TESTS()`, the fix is simple: just make sure its value is used as the
+return value of `main()`.
+
+But how could we introduce a change that breaks existing tests? Well, in this
+case, the code was already broken in the first place, so we didn't break it. :-)
+
+## My compiler complains that a constructor (or destructor) cannot return a value. What's going on?
+
+Due to a peculiarity of C++, in order to support the syntax for streaming
+messages to an `ASSERT_*`, e.g.
+
+```c++
+  ASSERT_EQ(1, Foo()) << "blah blah" << foo;
+```
+
+we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
+`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
+content of your constructor/destructor to a private void member function, or
+switch to `EXPECT_*()` if that works. This
+[section](advanced.md#assertion-placement) in the user's guide explains it.
+
+## My SetUp() function is not called. Why?
+
+C++ is case-sensitive. Did you spell it as `Setup()`?
+
+Similarly, sometimes people spell `SetUpTestSuite()` as `SetupTestSuite()` and
+wonder why it's never called.
+
+## I have several test suites which share the same test fixture logic; do I have to define a new test fixture class for each of them? This seems pretty tedious.
+
+You don't have to. Instead of
+
+```c++
+class FooTest : public BaseTest {};
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+class BarTest : public BaseTest {};
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+you can simply `typedef` the test fixtures:
+
+```c++
+typedef BaseTest FooTest;
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef BaseTest BarTest;
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+## GoogleTest output is buried in a whole bunch of LOG messages. What do I do?
+
+The GoogleTest output is meant to be a concise and human-friendly report. If
+your test generates textual output itself, it will mix with the GoogleTest
+output, making it hard to read. However, there is an easy solution to this
+problem.
+
+Since `LOG` messages go to stderr, we decided to let GoogleTest output go to
+stdout. This way, you can easily separate the two using redirection. For
+example:
+
+```shell
+$ ./my_test > gtest_output.txt
+```
+
+## Why should I prefer test fixtures over global variables?
+
+There are several good reasons:
+
+1.  It's likely your test needs to change the states of its global variables.
+    This makes it difficult to keep side effects from escaping one test and
+    contaminating others, making debugging difficult. By using fixtures, each
+    test has a fresh set of variables that's different (but with the same
+    names). Thus, tests are kept independent of each other.
+2.  Global variables pollute the global namespace.
+3.  Test fixtures can be reused via subclassing, which cannot be done easily
+    with global variables. This is useful if many test suites have something in
+    common.
+
+## What can the statement argument in ASSERT_DEATH() be?
+
+`ASSERT_DEATH(statement, matcher)` (or any death assertion macro) can be used
+wherever *`statement`* is valid. So basically *`statement`* can be any C++
+statement that makes sense in the current context. In particular, it can
+reference global and/or local variables, and can be:
+
+*   a simple function call (often the case),
+*   a complex expression, or
+*   a compound statement.
+
+Some examples are shown here:
+
+```c++
+// A death test can be a simple function call.
+TEST(MyDeathTest, FunctionCall) {
+  ASSERT_DEATH(Xyz(5), "Xyz failed");
+}
+
+// Or a complex expression that references variables and functions.
+TEST(MyDeathTest, ComplexExpression) {
+  const bool c = Condition();
+  ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
+               "(Func1|Method) failed");
+}
+
+// Death assertions can be used anywhere in a function.  In
+// particular, they can be inside a loop.
+TEST(MyDeathTest, InsideLoop) {
+  // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
+                   ::testing::Message() << "where i is " << i);
+  }
+}
+
+// A death assertion can contain a compound statement.
+TEST(MyDeathTest, CompoundStatement) {
+  // Verifies that at lease one of Bar(0), Bar(1), ..., and
+  // Bar(4) dies.
+  ASSERT_DEATH({
+    for (int i = 0; i < 5; i++) {
+      Bar(i);
+    }
+  },
+  "Bar has \\d+ errors");
+}
+```
+
+## I have a fixture class `FooTest`, but `TEST_F(FooTest, Bar)` gives me error ``"no matching function for call to `FooTest::FooTest()'"``. Why?
+
+GoogleTest needs to be able to create objects of your test fixture class, so it
+must have a default constructor. Normally the compiler will define one for you.
+However, there are cases where you have to define your own:
+
+*   If you explicitly declare a non-default constructor for class `FooTest`
+    (`DISALLOW_EVIL_CONSTRUCTORS()` does this), then you need to define a
+    default constructor, even if it would be empty.
+*   If `FooTest` has a const non-static data member, then you have to define the
+    default constructor *and* initialize the const member in the initializer
+    list of the constructor. (Early versions of `gcc` doesn't force you to
+    initialize the const member. It's a bug that has been fixed in `gcc 4`.)
+
+## Why does ASSERT_DEATH complain about previous threads that were already joined?
+
+With the Linux pthread library, there is no turning back once you cross the line
+from a single thread to multiple threads. The first time you create a thread, a
+manager thread is created in addition, so you get 3, not 2, threads. Later when
+the thread you create joins the main thread, the thread count decrements by 1,
+but the manager thread will never be killed, so you still have 2 threads, which
+means you cannot safely run a death test.
+
+The new NPTL thread library doesn't suffer from this problem, as it doesn't
+create a manager thread. However, if you don't control which machine your test
+runs on, you shouldn't depend on this.
+
+## Why does GoogleTest require the entire test suite, instead of individual tests, to be named `*DeathTest` when it uses `ASSERT_DEATH`?
+
+GoogleTest does not interleave tests from different test suites. That is, it
+runs all tests in one test suite first, and then runs all tests in the next test
+suite, and so on. GoogleTest does this because it needs to set up a test suite
+before the first test in it is run, and tear it down afterwards. Splitting up
+the test case would require multiple set-up and tear-down processes, which is
+inefficient and makes the semantics unclean.
+
+If we were to determine the order of tests based on test name instead of test
+case name, then we would have a problem with the following situation:
+
+```c++
+TEST_F(FooTest, AbcDeathTest) { ... }
+TEST_F(FooTest, Uvw) { ... }
+
+TEST_F(BarTest, DefDeathTest) { ... }
+TEST_F(BarTest, Xyz) { ... }
+```
+
+Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
+interleave tests from different test suites, we need to run all tests in the
+`FooTest` case before running any test in the `BarTest` case. This contradicts
+with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
+
+## But I don't like calling my entire test suite `*DeathTest` when it contains both death tests and non-death tests. What do I do?
+
+You don't have to, but if you like, you may split up the test suite into
+`FooTest` and `FooDeathTest`, where the names make it clear that they are
+related:
+
+```c++
+class FooTest : public ::testing::Test { ... };
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+using FooDeathTest = FooTest;
+
+TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
+TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
+```
+
+## GoogleTest prints the LOG messages in a death test's child process only when the test fails. How can I see the LOG messages when the death test succeeds?
+
+Printing the LOG messages generated by the statement inside `EXPECT_DEATH()`
+makes it harder to search for real problems in the parent's log. Therefore,
+GoogleTest only prints them when the death test has failed.
+
+If you really need to see such LOG messages, a workaround is to temporarily
+break the death test (e.g. by changing the regex pattern it is expected to
+match). Admittedly, this is a hack. We'll consider a more permanent solution
+after the fork-and-exec-style death tests are implemented.
+
+## The compiler complains about `no match for 'operator<<'` when I use an assertion. What gives?
+
+If you use a user-defined type `FooType` in an assertion, you must make sure
+there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
+defined such that we can print a value of `FooType`.
+
+In addition, if `FooType` is declared in a name space, the `<<` operator also
+needs to be defined in the *same* name space. See
+[Tip of the Week #49](https://abseil.io/tips/49) for details.
+
+## How do I suppress the memory leak messages on Windows?
+
+Since the statically initialized GoogleTest singleton requires allocations on
+the heap, the Visual C++ memory leak detector will report memory leaks at the
+end of the program run. The easiest way to avoid this is to use the
+`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
+statically initialized heap objects. See MSDN for more details and additional
+heap check/debug routines.
+
+## How can my code detect if it is running in a test?
+
+If you write code that sniffs whether it's running in a test and does different
+things accordingly, you are leaking test-only logic into production code and
+there is no easy way to ensure that the test-only code paths aren't run by
+mistake in production. Such cleverness also leads to
+[Heisenbugs](https://en.wikipedia.org/wiki/Heisenbug). Therefore we strongly
+advise against the practice, and GoogleTest doesn't provide a way to do it.
+
+In general, the recommended way to cause the code to behave differently under
+test is [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). You can inject
+different functionality from the test and from the production code. Since your
+production code doesn't link in the for-test logic at all (the
+[`testonly`](https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly) attribute for BUILD targets helps to ensure
+that), there is no danger in accidentally running it.
+
+However, if you *really*, *really*, *really* have no choice, and if you follow
+the rule of ending your test program names with `_test`, you can use the
+*horrible* hack of sniffing your executable name (`argv[0]` in `main()`) to know
+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).
+
+To include disabled tests in test execution, just invoke the test program with
+the `--gtest_also_run_disabled_tests` flag.
+
+## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces?
+
+Yes.
+
+The rule is **all test methods in the same test suite must use the same fixture
+class**. This means that the following is **allowed** because both tests use the
+same fixture class (`::testing::Test`).
+
+```c++
+namespace foo {
+TEST(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+
+namespace bar {
+TEST(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace bar
+```
+
+However, the following code is **not allowed** and will produce a runtime error
+from GoogleTest because the test methods are using different test fixture
+classes with the same test suite name.
+
+```c++
+namespace foo {
+class CoolTest : public ::testing::Test {};  // Fixture foo::CoolTest
+TEST_F(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+
+namespace bar {
+class CoolTest : public ::testing::Test {};  // Fixture: bar::CoolTest
+TEST_F(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace bar
+```
diff --git a/3rd-party/googletest/docs/gmock_cheat_sheet.md b/3rd-party/googletest/docs/gmock_cheat_sheet.md
new file mode 100644
index 0000000..ddafaaa
--- /dev/null
+++ b/3rd-party/googletest/docs/gmock_cheat_sheet.md
@@ -0,0 +1,241 @@
+# gMock Cheat Sheet
+
+## Defining a Mock Class
+
+### Mocking a Normal Class {#MockClass}
+
+Given
+
+```cpp
+class Foo {
+ public:
+  virtual ~Foo();
+  virtual int GetSize() const = 0;
+  virtual string Describe(const char* name) = 0;
+  virtual string Describe(int type) = 0;
+  virtual bool Process(Bar elem, int count) = 0;
+};
+```
+
+(note that `~Foo()` **must** be virtual) we can define its mock as
+
+```cpp
+#include <gmock/gmock.h>
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(int, GetSize, (), (const, override));
+  MOCK_METHOD(string, Describe, (const char* name), (override));
+  MOCK_METHOD(string, Describe, (int type), (override));
+  MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
+};
+```
+
+To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock,
+which warns on all uninteresting calls, or a "strict" mock, which treats them as
+failures:
+
+```cpp
+using ::testing::NiceMock;
+using ::testing::NaggyMock;
+using ::testing::StrictMock;
+
+NiceMock<MockFoo> nice_foo;      // The type is a subclass of MockFoo.
+NaggyMock<MockFoo> naggy_foo;    // The type is a subclass of MockFoo.
+StrictMock<MockFoo> strict_foo;  // The type is a subclass of MockFoo.
+```
+
+{: .callout .note}
+**Note:** A mock object is currently naggy by default. We may make it nice by
+default in the future.
+
+### Mocking a Class Template {#MockTemplate}
+
+Class templates can be mocked just like any class.
+
+To mock
+
+```cpp
+template <typename Elem>
+class StackInterface {
+ public:
+  virtual ~StackInterface();
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+```
+
+(note that all member functions that are mocked, including `~StackInterface()`
+**must** be virtual).
+
+```cpp
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+ public:
+  MOCK_METHOD(int, GetSize, (), (const, override));
+  MOCK_METHOD(void, Push, (const Elem& x), (override));
+};
+```
+
+### Specifying Calling Conventions for Mock Functions
+
+If your mock function doesn't use the default calling convention, you can
+specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter.
+For example,
+
+```cpp
+  MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE)));
+  MOCK_METHOD(int, Bar, (double x, double y),
+              (const, Calltype(STDMETHODCALLTYPE)));
+```
+
+where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
+
+## Using Mocks in Tests {#UsingMocks}
+
+The typical work flow is:
+
+1.  Import the gMock names you need to use. All gMock symbols are in the
+    `testing` namespace unless they are macros or otherwise noted.
+2.  Create the mock objects.
+3.  Optionally, set the default actions of the mock objects.
+4.  Set your expectations on the mock objects (How will they be called? What
+    will they do?).
+5.  Exercise code that uses the mock objects; if necessary, check the result
+    using googletest assertions.
+6.  When a mock object is destructed, gMock automatically verifies that all
+    expectations on it have been satisfied.
+
+Here's an example:
+
+```cpp
+using ::testing::Return;                          // #1
+
+TEST(BarTest, DoesThis) {
+  MockFoo foo;                                    // #2
+
+  ON_CALL(foo, GetSize())                         // #3
+      .WillByDefault(Return(1));
+  // ... other default actions ...
+
+  EXPECT_CALL(foo, Describe(5))                   // #4
+      .Times(3)
+      .WillRepeatedly(Return("Category 5"));
+  // ... other expectations ...
+
+  EXPECT_EQ(MyProductionFunction(&foo), "good");  // #5
+}                                                 // #6
+```
+
+## Setting Default Actions {#OnCall}
+
+gMock has a **built-in default action** for any function that returns `void`,
+`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
+the default-constructed value, if one exists for the given type.
+
+To customize the default action for functions with return type `T`, use
+[`DefaultValue<T>`](reference/mocking.md#DefaultValue). For example:
+
+```cpp
+  // Sets the default action for return type std::unique_ptr<Buzz> to
+  // creating a new Buzz every time.
+  DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
+      [] { return std::make_unique<Buzz>(AccessLevel::kInternal); });
+
+  // When this fires, the default action of MakeBuzz() will run, which
+  // will return a new Buzz object.
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber());
+
+  auto buzz1 = mock_buzzer_.MakeBuzz("hello");
+  auto buzz2 = mock_buzzer_.MakeBuzz("hello");
+  EXPECT_NE(buzz1, nullptr);
+  EXPECT_NE(buzz2, nullptr);
+  EXPECT_NE(buzz1, buzz2);
+
+  // Resets the default action for return type std::unique_ptr<Buzz>,
+  // to avoid interfere with other tests.
+  DefaultValue<std::unique_ptr<Buzz>>::Clear();
+```
+
+To customize the default action for a particular method of a specific mock
+object, use [`ON_CALL`](reference/mocking.md#ON_CALL). `ON_CALL` has a similar
+syntax to `EXPECT_CALL`, but it is used for setting default behaviors when you
+do not require that the mock method is called. See
+[Knowing When to Expect](gmock_cook_book.md#UseOnCall) for a more detailed
+discussion.
+
+## Setting Expectations {#ExpectCall}
+
+See [`EXPECT_CALL`](reference/mocking.md#EXPECT_CALL) in the Mocking Reference.
+
+## Matchers {#MatcherList}
+
+See the [Matchers Reference](reference/matchers.md).
+
+## Actions {#ActionList}
+
+See the [Actions Reference](reference/actions.md).
+
+## Cardinalities {#CardinalityList}
+
+See the [`Times` clause](reference/mocking.md#EXPECT_CALL.Times) of
+`EXPECT_CALL` in the Mocking Reference.
+
+## Expectation Order
+
+By default, expectations can be matched in *any* order. If some or all
+expectations must be matched in a given order, you can use the
+[`After` clause](reference/mocking.md#EXPECT_CALL.After) or
+[`InSequence` clause](reference/mocking.md#EXPECT_CALL.InSequence) of
+`EXPECT_CALL`, or use an [`InSequence` object](reference/mocking.md#InSequence).
+
+## Verifying and Resetting a Mock
+
+gMock will verify the expectations on a mock object when it is destructed, or
+you can do it earlier:
+
+```cpp
+using ::testing::Mock;
+...
+// Verifies and removes the expectations on mock_obj;
+// returns true if and only if successful.
+Mock::VerifyAndClearExpectations(&mock_obj);
+...
+// Verifies and removes the expectations on mock_obj;
+// also removes the default actions set by ON_CALL();
+// returns true if and only if successful.
+Mock::VerifyAndClear(&mock_obj);
+```
+
+Do not set new expectations after verifying and clearing a mock after its use.
+Setting expectations after code that exercises the mock has undefined behavior.
+See [Using Mocks in Tests](gmock_for_dummies.md#using-mocks-in-tests) for more
+information.
+
+You can also tell gMock that a mock object can be leaked and doesn't need to be
+verified:
+
+```cpp
+Mock::AllowLeak(&mock_obj);
+```
+
+## Mock Classes
+
+gMock defines a convenient mock class template
+
+```cpp
+class MockFunction<R(A1, ..., An)> {
+ public:
+  MOCK_METHOD(R, Call, (A1, ..., An));
+};
+```
+
+See this [recipe](gmock_cook_book.md#UsingCheckPoints) for one application of
+it.
+
+## Flags
+
+| Flag                           | Description                               |
+| :----------------------------- | :---------------------------------------- |
+| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
+| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
diff --git a/3rd-party/googletest/docs/gmock_cook_book.md b/3rd-party/googletest/docs/gmock_cook_book.md
new file mode 100644
index 0000000..f1b10b4
--- /dev/null
+++ b/3rd-party/googletest/docs/gmock_cook_book.md
@@ -0,0 +1,4379 @@
+# gMock Cookbook
+
+You can find recipes for using gMock here. If you haven't yet, please read
+[the dummy guide](gmock_for_dummies.md) first to make sure you understand the
+basics.
+
+{: .callout .note}
+**Note:** gMock lives in the `testing` name space. For readability, it is
+recommended to write `using ::testing::Foo;` once in your file before using the
+name `Foo` defined by gMock. We omit such `using` statements in this section for
+brevity, but you should do it in your own code.
+
+## Creating Mock Classes
+
+Mock classes are defined as normal classes, using the `MOCK_METHOD` macro to
+generate mocked methods. The macro gets 3 or 4 parameters:
+
+```cpp
+class MyMock {
+ public:
+  MOCK_METHOD(ReturnType, MethodName, (Args...));
+  MOCK_METHOD(ReturnType, MethodName, (Args...), (Specs...));
+};
+```
+
+The first 3 parameters are simply the method declaration, split into 3 parts.
+The 4th parameter accepts a closed list of qualifiers, which affect the
+generated method:
+
+*   **`const`** - Makes the mocked method a `const` method. Required if
+    overriding a `const` method.
+*   **`override`** - Marks the method with `override`. Recommended if overriding
+    a `virtual` method.
+*   **`noexcept`** - Marks the method with `noexcept`. Required if overriding a
+    `noexcept` method.
+*   **`Calltype(...)`** - Sets the call type for the method (e.g. to
+    `STDMETHODCALLTYPE`), useful in Windows.
+*   **`ref(...)`** - Marks the method with the reference qualification
+    specified. Required if overriding a method that has reference
+    qualifications. Eg `ref(&)` or `ref(&&)`.
+
+### Dealing with unprotected commas
+
+Unprotected commas, i.e. commas which are not surrounded by parentheses, prevent
+`MOCK_METHOD` from parsing its arguments correctly:
+
+{: .bad}
+```cpp
+class MockFoo {
+ public:
+  MOCK_METHOD(std::pair<bool, int>, GetPair, ());  // Won't compile!
+  MOCK_METHOD(bool, CheckMap, (std::map<int, double>, bool));  // Won't compile!
+};
+```
+
+Solution 1 - wrap with parentheses:
+
+{: .good}
+```cpp
+class MockFoo {
+ public:
+  MOCK_METHOD((std::pair<bool, int>), GetPair, ());
+  MOCK_METHOD(bool, CheckMap, ((std::map<int, double>), bool));
+};
+```
+
+Note that wrapping a return or argument type with parentheses is, in general,
+invalid C++. `MOCK_METHOD` removes the parentheses.
+
+Solution 2 - define an alias:
+
+{: .good}
+```cpp
+class MockFoo {
+ public:
+  using BoolAndInt = std::pair<bool, int>;
+  MOCK_METHOD(BoolAndInt, GetPair, ());
+  using MapIntDouble = std::map<int, double>;
+  MOCK_METHOD(bool, CheckMap, (MapIntDouble, bool));
+};
+```
+
+### Mocking Private or Protected Methods
+
+You must always put a mock method definition (`MOCK_METHOD`) in a `public:`
+section of the mock class, regardless of the method being mocked being `public`,
+`protected`, or `private` in the base class. This allows `ON_CALL` and
+`EXPECT_CALL` to reference the mock function from outside of the mock class.
+(Yes, C++ allows a subclass to change the access level of a virtual function in
+the base class.) Example:
+
+```cpp
+class Foo {
+ public:
+  ...
+  virtual bool Transform(Gadget* g) = 0;
+
+ protected:
+  virtual void Resume();
+
+ private:
+  virtual int GetTimeOut();
+};
+
+class MockFoo : public Foo {
+ public:
+  ...
+  MOCK_METHOD(bool, Transform, (Gadget* g), (override));
+
+  // The following must be in the public section, even though the
+  // methods are protected or private in the base class.
+  MOCK_METHOD(void, Resume, (), (override));
+  MOCK_METHOD(int, GetTimeOut, (), (override));
+};
+```
+
+### Mocking Overloaded Methods
+
+You can mock overloaded functions as usual. No special attention is required:
+
+```cpp
+class Foo {
+  ...
+
+  // Must be virtual as we'll inherit from Foo.
+  virtual ~Foo();
+
+  // Overloaded on the types and/or numbers of arguments.
+  virtual int Add(Element x);
+  virtual int Add(int times, Element x);
+
+  // Overloaded on the const-ness of this object.
+  virtual Bar& GetBar();
+  virtual const Bar& GetBar() const;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD(int, Add, (Element x), (override));
+  MOCK_METHOD(int, Add, (int times, Element x), (override));
+
+  MOCK_METHOD(Bar&, GetBar, (), (override));
+  MOCK_METHOD(const Bar&, GetBar, (), (const, override));
+};
+```
+
+{: .callout .note}
+**Note:** if you don't mock all versions of the overloaded method, the compiler
+will give you a warning about some methods in the base class being hidden. To
+fix that, use `using` to bring them in scope:
+
+```cpp
+class MockFoo : public Foo {
+  ...
+  using Foo::Add;
+  MOCK_METHOD(int, Add, (Element x), (override));
+  // We don't want to mock int Add(int times, Element x);
+  ...
+};
+```
+
+### Mocking Class Templates
+
+You can mock class templates just like any class.
+
+```cpp
+template <typename Elem>
+class StackInterface {
+  ...
+  // Must be virtual as we'll inherit from StackInterface.
+  virtual ~StackInterface();
+
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+  ...
+  MOCK_METHOD(int, GetSize, (), (override));
+  MOCK_METHOD(void, Push, (const Elem& x), (override));
+};
+```
+
+### Mocking Non-virtual Methods {#MockingNonVirtualMethods}
+
+gMock can mock non-virtual functions to be used in Hi-perf dependency injection.
+
+In this case, instead of sharing a common base class with the real class, your
+mock class will be *unrelated* to the real class, but contain methods with the
+same signatures. The syntax for mocking non-virtual methods is the *same* as
+mocking virtual methods (just don't add `override`):
+
+```cpp
+// A simple packet stream class.  None of its members is virtual.
+class ConcretePacketStream {
+ public:
+  void AppendPacket(Packet* new_packet);
+  const Packet* GetPacket(size_t packet_number) const;
+  size_t NumberOfPackets() const;
+  ...
+};
+
+// A mock packet stream class.  It inherits from no other, but defines
+// GetPacket() and NumberOfPackets().
+class MockPacketStream {
+ public:
+  MOCK_METHOD(const Packet*, GetPacket, (size_t packet_number), (const));
+  MOCK_METHOD(size_t, NumberOfPackets, (), (const));
+  ...
+};
+```
+
+Note that the mock class doesn't define `AppendPacket()`, unlike the real class.
+That's fine as long as the test doesn't need to call it.
+
+Next, you need a way to say that you want to use `ConcretePacketStream` in
+production code, and use `MockPacketStream` in tests. Since the functions are
+not virtual and the two classes are unrelated, you must specify your choice at
+*compile time* (as opposed to run time).
+
+One way to do it is to templatize your code that needs to use a packet stream.
+More specifically, you will give your code a template type argument for the type
+of the packet stream. In production, you will instantiate your template with
+`ConcretePacketStream` as the type argument. In tests, you will instantiate the
+same template with `MockPacketStream`. For example, you may write:
+
+```cpp
+template <class PacketStream>
+void CreateConnection(PacketStream* stream) { ... }
+
+template <class PacketStream>
+class PacketReader {
+ public:
+  void ReadPackets(PacketStream* stream, size_t packet_num);
+};
+```
+
+Then you can use `CreateConnection<ConcretePacketStream>()` and
+`PacketReader<ConcretePacketStream>` in production code, and use
+`CreateConnection<MockPacketStream>()` and `PacketReader<MockPacketStream>` in
+tests.
+
+```cpp
+  MockPacketStream mock_stream;
+  EXPECT_CALL(mock_stream, ...)...;
+  .. set more expectations on mock_stream ...
+  PacketReader<MockPacketStream> reader(&mock_stream);
+  ... exercise reader ...
+```
+
+### Mocking Free Functions
+
+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:
+
+```cpp
+class FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) = 0;
+};
+
+class File : public FileInterface {
+ public:
+  ...
+  bool Open(const char* path, const char* mode) override {
+     return OpenFile(path, mode);
+  }
+};
+```
+
+Your code should talk to `FileInterface` to open a file. Now it's easy to mock
+out the function.
+
+This may seem like a lot of hassle, but in practice you often have multiple
+related functions that you can put in the same interface, so the per-function
+syntactic overhead will be much lower.
+
+If you are concerned about the performance overhead incurred by virtual
+functions, and profiling confirms your concern, you can combine this with the
+recipe for [mocking non-virtual methods](#MockingNonVirtualMethods).
+
+Alternatively, instead of introducing a new interface, you can rewrite your code
+to accept a std::function instead of the free function, and then use
+[MockFunction](#MockFunction) to mock the std::function.
+
+### Old-Style `MOCK_METHODn` Macros
+
+Before the generic `MOCK_METHOD` macro
+[was introduced in 2018](https://github.com/google/googletest/commit/c5f08bf91944ce1b19bcf414fa1760e69d20afc2),
+mocks where created using a family of macros collectively called `MOCK_METHODn`.
+These macros are still supported, though migration to the new `MOCK_METHOD` is
+recommended.
+
+The macros in the `MOCK_METHODn` family differ from `MOCK_METHOD`:
+
+*   The general structure is `MOCK_METHODn(MethodName, ReturnType(Args))`,
+    instead of `MOCK_METHOD(ReturnType, MethodName, (Args))`.
+*   The number `n` must equal the number of arguments.
+*   When mocking a const method, one must use `MOCK_CONST_METHODn`.
+*   When mocking a class template, the macro name must be suffixed with `_T`.
+*   In order to specify the call type, the macro name must be suffixed with
+    `_WITH_CALLTYPE`, and the call type is the first macro argument.
+
+Old macros and their new equivalents:
+
+<table>
+  <tr><th colspan=2>Simple</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_METHOD1(Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Const Method</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_CONST_METHOD1(Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int), (const))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Method in a Class Template</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_METHOD1_T(Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Const Method in a Class Template</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_CONST_METHOD1_T(Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int), (const))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Method with Call Type</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int), (Calltype(STDMETHODCALLTYPE)))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Const Method with Call Type</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int), (const, Calltype(STDMETHODCALLTYPE)))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Method with Call Type in a Class Template</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int), (Calltype(STDMETHODCALLTYPE)))</code></td>
+  </tr>
+
+  <tr><th colspan=2>Const Method with Call Type in a Class Template</th></tr>
+  <tr>
+    <td>Old</td>
+    <td><code>MOCK_CONST_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))</code></td>
+  </tr>
+  <tr>
+    <td>New</td>
+    <td><code>MOCK_METHOD(bool, Foo, (int), (const, Calltype(STDMETHODCALLTYPE)))</code></td>
+  </tr>
+</table>
+
+### The Nice, the Strict, and the Naggy {#NiceStrictNaggy}
+
+If a mock method has no `EXPECT_CALL` spec but is called, we say that it's an
+"uninteresting call", and the default action (which can be specified using
+`ON_CALL()`) of the method will be taken. Currently, an uninteresting call will
+also by default cause gMock to print a warning.
+
+However, sometimes you may want to ignore these uninteresting calls, and
+sometimes you may want to treat them as errors. gMock lets you make the decision
+on a per-mock-object basis.
+
+Suppose your test uses a mock class `MockFoo`:
+
+```cpp
+TEST(...) {
+  MockFoo mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+If a method of `mock_foo` other than `DoThis()` is called, you will get a
+warning. However, if you rewrite your test to use `NiceMock<MockFoo>` instead,
+you can suppress the warning:
+
+```cpp
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+`NiceMock<MockFoo>` is a subclass of `MockFoo`, so it can be used wherever
+`MockFoo` is accepted.
+
+It also works if `MockFoo`'s constructor takes some arguments, as
+`NiceMock<MockFoo>` "inherits" `MockFoo`'s constructors:
+
+```cpp
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo(5, "hi");  // Calls MockFoo(5, "hi").
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+The usage of `StrictMock` is similar, except that it makes all uninteresting
+calls failures:
+
+```cpp
+using ::testing::StrictMock;
+
+TEST(...) {
+  StrictMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+
+  // The test will fail if a method of mock_foo other than DoThis()
+  // is called.
+}
+```
+
+{: .callout .note}
+NOTE: `NiceMock` and `StrictMock` only affects *uninteresting* calls (calls of
+*methods* with no expectations); they do not affect *unexpected* calls (calls of
+methods with expectations, but they don't match). See
+[Understanding Uninteresting vs Unexpected Calls](#uninteresting-vs-unexpected).
+
+There are some caveats though (sadly they are side effects of C++'s
+limitations):
+
+1.  `NiceMock<MockFoo>` and `StrictMock<MockFoo>` only work for mock methods
+    defined using the `MOCK_METHOD` macro **directly** in the `MockFoo` class.
+    If a mock method is defined in a **base class** of `MockFoo`, the "nice" or
+    "strict" modifier may not affect it, depending on the compiler. In
+    particular, nesting `NiceMock` and `StrictMock` (e.g.
+    `NiceMock<StrictMock<MockFoo> >`) is **not** supported.
+2.  `NiceMock<MockFoo>` and `StrictMock<MockFoo>` may not work correctly if the
+    destructor of `MockFoo` is not virtual. We would like to fix this, but it
+    requires cleaning up existing tests.
+
+Finally, you should be **very cautious** about when to use naggy or strict
+mocks, as they tend to make tests more brittle and harder to maintain. When you
+refactor your code without changing its externally visible behavior, ideally you
+shouldn't need to update any tests. If your code interacts with a naggy mock,
+however, you may start to get spammed with warnings as the result of your
+change. Worse, if your code interacts with a strict mock, your tests may start
+to fail and you'll be forced to fix them. Our general recommendation is to use
+nice mocks (not yet the default) most of the time, use naggy mocks (the current
+default) when developing or debugging tests, and use strict mocks only as the
+last resort.
+
+### Simplifying the Interface without Breaking Existing Code {#SimplerInterfaces}
+
+Sometimes a method has a long list of arguments that is mostly uninteresting.
+For example:
+
+```cpp
+class LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) = 0;
+};
+```
+
+This method's argument list is lengthy and hard to work with (the `message`
+argument is not even 0-terminated). If we mock it as is, using the mock will be
+awkward. If, however, we try to simplify this interface, we'll need to fix all
+clients depending on it, which is often infeasible.
+
+The trick is to redispatch the method in the mock class:
+
+```cpp
+class ScopedMockLog : public LogSink {
+ public:
+  ...
+  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) override {
+    // We are only interested in the log severity, full file name, and
+    // log message.
+    Log(severity, full_filename, std::string(message, message_len));
+  }
+
+  // Implements the mock method:
+  //
+  //   void Log(LogSeverity severity,
+  //            const string& file_path,
+  //            const string& message);
+  MOCK_METHOD(void, Log,
+              (LogSeverity severity, const string& file_path,
+               const string& message));
+};
+```
+
+By defining a new mock method with a trimmed argument list, we make the mock
+class more user-friendly.
+
+This technique may also be applied to make overloaded methods more amenable to
+mocking. For example, when overloads have been used to implement default
+arguments:
+
+```cpp
+class MockTurtleFactory : public TurtleFactory {
+ public:
+  Turtle* MakeTurtle(int length, int weight) override { ... }
+  Turtle* MakeTurtle(int length, int weight, int speed) override { ... }
+
+  // the above methods delegate to this one:
+  MOCK_METHOD(Turtle*, DoMakeTurtle, ());
+};
+```
+
+This allows tests that don't care which overload was invoked to avoid specifying
+argument matchers:
+
+```cpp
+ON_CALL(factory, DoMakeTurtle)
+    .WillByDefault(Return(MakeMockTurtle()));
+```
+
+### Alternative to Mocking Concrete Classes
+
+Often you may find yourself using classes that don't implement interfaces. In
+order to test your code that uses such a class (let's call it `Concrete`), you
+may be tempted to make the methods of `Concrete` virtual and then mock it.
+
+Try not to do that.
+
+Making a non-virtual function virtual is a big decision. It creates an extension
+point where subclasses can tweak your class' behavior. This weakens your control
+on the class because now it's harder to maintain the class invariants. You
+should make a function virtual only when there is a valid reason for a subclass
+to override it.
+
+Mocking concrete classes directly is problematic as it creates a tight coupling
+between the class and the tests - any small change in the class may invalidate
+your tests and make test maintenance a pain.
+
+To avoid such problems, many programmers have been practicing "coding to
+interfaces": instead of talking to the `Concrete` class, your code would define
+an interface and talk to it. Then you implement that interface as an adaptor on
+top of `Concrete`. In tests, you can easily mock that interface to observe how
+your code is doing.
+
+This technique incurs some overhead:
+
+*   You pay the cost of virtual function calls (usually not a problem).
+*   There is more abstraction for the programmers to learn.
+
+However, it can also bring significant benefits in addition to better
+testability:
+
+*   `Concrete`'s API may not fit your problem domain very well, as you may not
+    be the only client it tries to serve. By designing your own interface, you
+    have a chance to tailor it to your need - you may add higher-level
+    functionalities, rename stuff, etc instead of just trimming the class. This
+    allows you to write your code (user of the interface) in a more natural way,
+    which means it will be more readable, more maintainable, and you'll be more
+    productive.
+*   If `Concrete`'s implementation ever has to change, you don't have to rewrite
+    everywhere it is used. Instead, you can absorb the change in your
+    implementation of the interface, and your other code and tests will be
+    insulated from this change.
+
+Some people worry that if everyone is practicing this technique, they will end
+up writing lots of redundant code. This concern is totally understandable.
+However, there are two reasons why it may not be the case:
+
+*   Different projects may need to use `Concrete` in different ways, so the best
+    interfaces for them will be different. Therefore, each of them will have its
+    own domain-specific interface on top of `Concrete`, and they will not be the
+    same code.
+*   If enough projects want to use the same interface, they can always share it,
+    just like they have been sharing `Concrete`. You can check in the interface
+    and the adaptor somewhere near `Concrete` (perhaps in a `contrib`
+    sub-directory) and let many projects use it.
+
+You need to weigh the pros and cons carefully for your particular problem, but
+I'd like to assure you that the Java community has been practicing this for a
+long time and it's a proven effective technique applicable in a wide variety of
+situations. :-)
+
+### Delegating Calls to a Fake {#DelegatingToFake}
+
+Some times you have a non-trivial fake implementation of an interface. For
+example:
+
+```cpp
+class Foo {
+ public:
+  virtual ~Foo() {}
+  virtual char DoThis(int n) = 0;
+  virtual void DoThat(const char* s, int* p) = 0;
+};
+
+class FakeFoo : public Foo {
+ public:
+  char DoThis(int n) override {
+    return (n > 0) ? '+' :
+           (n < 0) ? '-' : '0';
+  }
+
+  void DoThat(const char* s, int* p) override {
+    *p = strlen(s);
+  }
+};
+```
+
+Now you want to mock this interface such that you can set expectations on it.
+However, you also want to use `FakeFoo` for the default behavior, as duplicating
+it in the mock object is, well, a lot of work.
+
+When you define the mock class using gMock, you can have it delegate its default
+action to a fake class you already have, using this pattern:
+
+```cpp
+class MockFoo : public Foo {
+ public:
+  // Normal mock method definitions using gMock.
+  MOCK_METHOD(char, DoThis, (int n), (override));
+  MOCK_METHOD(void, DoThat, (const char* s, int* p), (override));
+
+  // Delegates the default actions of the methods to a FakeFoo object.
+  // This must be called *before* the custom ON_CALL() statements.
+  void DelegateToFake() {
+    ON_CALL(*this, DoThis).WillByDefault([this](int n) {
+      return fake_.DoThis(n);
+    });
+    ON_CALL(*this, DoThat).WillByDefault([this](const char* s, int* p) {
+      fake_.DoThat(s, p);
+    });
+  }
+
+ private:
+  FakeFoo fake_;  // Keeps an instance of the fake in the mock.
+};
+```
+
+With that, you can use `MockFoo` in your tests as usual. Just remember that if
+you don't explicitly set an action in an `ON_CALL()` or `EXPECT_CALL()`, the
+fake will be called upon to do it.:
+
+```cpp
+using ::testing::_;
+
+TEST(AbcTest, Xyz) {
+  MockFoo foo;
+
+  foo.DelegateToFake();  // Enables the fake for delegation.
+
+  // Put your ON_CALL(foo, ...)s here, if any.
+
+  // No action specified, meaning to use the default action.
+  EXPECT_CALL(foo, DoThis(5));
+  EXPECT_CALL(foo, DoThat(_, _));
+
+  int n = 0;
+  EXPECT_EQ(foo.DoThis(5), '+');  // FakeFoo::DoThis() is invoked.
+  foo.DoThat("Hi", &n);  // FakeFoo::DoThat() is invoked.
+  EXPECT_EQ(n, 2);
+}
+```
+
+**Some tips:**
+
+*   If you want, you can still override the default action by providing your own
+    `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`.
+*   In `DelegateToFake()`, you only need to delegate the methods whose fake
+    implementation you intend to use.
+
+*   The general technique discussed here works for overloaded methods, but
+    you'll need to tell the compiler which version you mean. To disambiguate a
+    mock function (the one you specify inside the parentheses of `ON_CALL()`),
+    use [this technique](#SelectOverload); to disambiguate a fake function (the
+    one you place inside `Invoke()`), use a `static_cast` to specify the
+    function's type. For instance, if class `Foo` has methods `char DoThis(int
+    n)` and `bool DoThis(double x) const`, and you want to invoke the latter,
+    you need to write `Invoke(&fake_, static_cast<bool (FakeFoo::*)(double)
+    const>(&FakeFoo::DoThis))` instead of `Invoke(&fake_, &FakeFoo::DoThis)`
+    (The strange-looking thing inside the angled brackets of `static_cast` is
+    the type of a function pointer to the second `DoThis()` method.).
+
+*   Having to mix a mock and a fake is often a sign of something gone wrong.
+    Perhaps you haven't got used to the interaction-based way of testing yet. Or
+    perhaps your interface is taking on too many roles and should be split up.
+    Therefore, **don't abuse this**. We would only recommend to do it as an
+    intermediate step when you are refactoring your code.
+
+Regarding the tip on mixing a mock and a fake, here's an example on why it may
+be a bad sign: Suppose you have a class `System` for low-level system
+operations. In particular, it does file and I/O operations. And suppose you want
+to test how your code uses `System` to do I/O, and you just want the file
+operations to work normally. If you mock out the entire `System` class, you'll
+have to provide a fake implementation for the file operation part, which
+suggests that `System` is taking on too many roles.
+
+Instead, you can define a `FileOps` interface and an `IOOps` interface and split
+`System`'s functionalities into the two. Then you can mock `IOOps` without
+mocking `FileOps`.
+
+### Delegating Calls to a Real Object
+
+When using testing doubles (mocks, fakes, stubs, and etc), sometimes their
+behaviors will differ from those of the real objects. This difference could be
+either intentional (as in simulating an error such that you can test the error
+handling code) or unintentional. If your mocks have different behaviors than the
+real objects by mistake, you could end up with code that passes the tests but
+fails in production.
+
+You can use the *delegating-to-real* technique to ensure that your mock has the
+same behavior as the real object while retaining the ability to validate calls.
+This technique is very similar to the [delegating-to-fake](#DelegatingToFake)
+technique, the difference being that we use a real object instead of a fake.
+Here's an example:
+
+```cpp
+using ::testing::AtLeast;
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() {
+    // By default, all calls are delegated to the real object.
+    ON_CALL(*this, DoThis).WillByDefault([this](int n) {
+      return real_.DoThis(n);
+    });
+    ON_CALL(*this, DoThat).WillByDefault([this](const char* s, int* p) {
+      real_.DoThat(s, p);
+    });
+    ...
+  }
+  MOCK_METHOD(char, DoThis, ...);
+  MOCK_METHOD(void, DoThat, ...);
+  ...
+ private:
+  Foo real_;
+};
+
+...
+  MockFoo mock;
+  EXPECT_CALL(mock, DoThis())
+      .Times(3);
+  EXPECT_CALL(mock, DoThat("Hi"))
+      .Times(AtLeast(1));
+  ... use mock in test ...
+```
+
+With this, gMock will verify that your code made the right calls (with the right
+arguments, in the right order, called the right number of times, etc), and a
+real object will answer the calls (so the behavior will be the same as in
+production). This gives you the best of both worlds.
+
+### Delegating Calls to a Parent Class
+
+Ideally, you should code to interfaces, whose methods are all pure virtual. In
+reality, sometimes you do need to mock a virtual method that is not pure (i.e,
+it already has an implementation). For example:
+
+```cpp
+class Foo {
+ public:
+  virtual ~Foo();
+
+  virtual void Pure(int n) = 0;
+  virtual int Concrete(const char* str) { ... }
+};
+
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD(void, Pure, (int n), (override));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD(int, Concrete, (const char* str), (override));
+};
+```
+
+Sometimes you may want to call `Foo::Concrete()` instead of
+`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub action, or
+perhaps your test doesn't need to mock `Concrete()` at all (but it would be
+oh-so painful to have to define a new mock class whenever you don't need to mock
+one of its methods).
+
+You can call `Foo::Concrete()` inside an action by:
+
+```cpp
+...
+  EXPECT_CALL(foo, Concrete).WillOnce([&foo](const char* str) {
+    return foo.Foo::Concrete(str);
+  });
+```
+
+or tell the mock object that you don't want to mock `Concrete()`:
+
+```cpp
+...
+  ON_CALL(foo, Concrete).WillByDefault([&foo](const char* str) {
+    return foo.Foo::Concrete(str);
+  });
+```
+
+(Why don't we just write `{ return foo.Concrete(str); }`? If you do that,
+`MockFoo::Concrete()` will be called (and cause an infinite recursion) since
+`Foo::Concrete()` is virtual. That's just how C++ works.)
+
+## Using Matchers
+
+### Matching Argument Values Exactly
+
+You can specify exactly which arguments a mock method is expecting:
+
+```cpp
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(5))
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", bar));
+```
+
+### Using Simple Matchers
+
+You can use matchers to match arguments that have a certain property:
+
+```cpp
+using ::testing::NotNull;
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(Ge(5)))  // The argument must be >= 5.
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", NotNull()));
+      // The second argument must not be NULL.
+```
+
+A frequently used matcher is `_`, which matches anything:
+
+```cpp
+  EXPECT_CALL(foo, DoThat(_, NotNull()));
+```
+
+### Combining Matchers {#CombiningMatchers}
+
+You can build complex matchers from existing ones using `AllOf()`,
+`AllOfArray()`, `AnyOf()`, `AnyOfArray()` and `Not()`:
+
+```cpp
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::HasSubstr;
+using ::testing::Ne;
+using ::testing::Not;
+...
+  // The argument must be > 5 and != 10.
+  EXPECT_CALL(foo, DoThis(AllOf(Gt(5),
+                                Ne(10))));
+
+  // The first argument must not contain sub-string "blah".
+  EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")),
+                          NULL));
+```
+
+Matchers are function objects, and parametrized matchers can be composed just
+like any other function. However because their types can be long and rarely
+provide meaningful information, it can be easier to express them with C++14
+generic lambdas to avoid specifying types. For example,
+
+```cpp
+using ::testing::Contains;
+using ::testing::Property;
+
+inline constexpr auto HasFoo = [](const auto& f) {
+  return Property("foo", &MyClass::foo, Contains(f));
+};
+...
+  EXPECT_THAT(x, HasFoo("blah"));
+```
+
+### Casting Matchers {#SafeMatcherCast}
+
+gMock matchers are statically typed, meaning that the compiler can catch your
+mistake if you use a matcher of the wrong type (for example, if you use `Eq(5)`
+to match a `string` argument). Good for you!
+
+Sometimes, however, you know what you're doing and want the compiler to give you
+some slack. One example is that you have a matcher for `long` and the argument
+you want to match is `int`. While the two types aren't exactly the same, there
+is nothing really wrong with using a `Matcher<long>` to match an `int` - after
+all, we can first convert the `int` argument to a `long` losslessly before
+giving it to the matcher.
+
+To support this need, gMock gives you the `SafeMatcherCast<T>(m)` function. It
+casts a matcher `m` to type `Matcher<T>`. To ensure safety, gMock checks that
+(let `U` be the type `m` accepts :
+
+1.  Type `T` can be *implicitly* cast to type `U`;
+2.  When both `T` and `U` are built-in arithmetic types (`bool`, integers, and
+    floating-point numbers), the conversion from `T` to `U` is not lossy (in
+    other words, any value representable by `T` can also be represented by `U`);
+    and
+3.  When `U` is a reference, `T` must also be a reference (as the underlying
+    matcher may be interested in the address of the `U` value).
+
+The code won't compile if any of these conditions isn't met.
+
+Here's one example:
+
+```cpp
+using ::testing::SafeMatcherCast;
+
+// A base class and a child class.
+class Base { ... };
+class Derived : public Base { ... };
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(void, DoThis, (Derived* derived), (override));
+};
+
+...
+  MockFoo foo;
+  // m is a Matcher<Base*> we got from somewhere.
+  EXPECT_CALL(foo, DoThis(SafeMatcherCast<Derived*>(m)));
+```
+
+If you find `SafeMatcherCast<T>(m)` too limiting, you can use a similar function
+`MatcherCast<T>(m)`. The difference is that `MatcherCast` works as long as you
+can `static_cast` type `T` to type `U`.
+
+`MatcherCast` essentially lets you bypass C++'s type system (`static_cast` isn't
+always safe as it could throw away information, for example), so be careful not
+to misuse/abuse it.
+
+### Selecting Between Overloaded Functions {#SelectOverload}
+
+If you expect an overloaded function to be called, the compiler may need some
+help on which overloaded version it is.
+
+To disambiguate functions overloaded on the const-ness of this object, use the
+`Const()` argument wrapper.
+
+```cpp
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD(Bar&, GetBar, (), (override));
+  MOCK_METHOD(const Bar&, GetBar, (), (const, override));
+};
+
+...
+  MockFoo foo;
+  Bar bar1, bar2;
+  EXPECT_CALL(foo, GetBar())         // The non-const GetBar().
+      .WillOnce(ReturnRef(bar1));
+  EXPECT_CALL(Const(foo), GetBar())  // The const GetBar().
+      .WillOnce(ReturnRef(bar2));
+```
+
+(`Const()` is defined by gMock and returns a `const` reference to its argument.)
+
+To disambiguate overloaded functions with the same number of arguments but
+different argument types, you may need to specify the exact type of a matcher,
+either by wrapping your matcher in `Matcher<type>()`, or using a matcher whose
+type is fixed (`TypedEq<type>`, `An<type>()`, etc):
+
+```cpp
+using ::testing::An;
+using ::testing::Matcher;
+using ::testing::TypedEq;
+
+class MockPrinter : public Printer {
+ public:
+  MOCK_METHOD(void, Print, (int n), (override));
+  MOCK_METHOD(void, Print, (char c), (override));
+};
+
+TEST(PrinterTest, Print) {
+  MockPrinter printer;
+
+  EXPECT_CALL(printer, Print(An<int>()));            // void Print(int);
+  EXPECT_CALL(printer, Print(Matcher<int>(Lt(5))));  // void Print(int);
+  EXPECT_CALL(printer, Print(TypedEq<char>('a')));   // void Print(char);
+
+  printer.Print(3);
+  printer.Print(6);
+  printer.Print('a');
+}
+```
+
+### Performing Different Actions Based on the Arguments
+
+When a mock method is called, the *last* matching expectation that's still
+active will be selected (think "newer overrides older"). So, you can make a
+method do different things depending on its argument values like this:
+
+```cpp
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Return;
+...
+  // The default case.
+  EXPECT_CALL(foo, DoThis(_))
+      .WillRepeatedly(Return('b'));
+  // The more specific case.
+  EXPECT_CALL(foo, DoThis(Lt(5)))
+      .WillRepeatedly(Return('a'));
+```
+
+Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will be
+returned; otherwise `'b'` will be returned.
+
+### Matching Multiple Arguments as a Whole
+
+Sometimes it's not enough to match the arguments individually. For example, we
+may want to say that the first argument must be less than the second argument.
+The `With()` clause allows us to match all arguments of a mock function as a
+whole. For example,
+
+```cpp
+using ::testing::_;
+using ::testing::Ne;
+using ::testing::Lt;
+...
+  EXPECT_CALL(foo, InRange(Ne(0), _))
+      .With(Lt());
+```
+
+says that the first argument of `InRange()` must not be 0, and must be less than
+the second argument.
+
+The expression inside `With()` must be a matcher of type `Matcher<std::tuple<A1,
+..., An>>`, where `A1`, ..., `An` are the types of the function arguments.
+
+You can also write `AllArgs(m)` instead of `m` inside `.With()`. The two forms
+are equivalent, but `.With(AllArgs(Lt()))` is more readable than `.With(Lt())`.
+
+You can use `Args<k1, ..., kn>(m)` to match the `n` selected arguments (as a
+tuple) against `m`. For example,
+
+```cpp
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Args;
+using ::testing::Lt;
+...
+  EXPECT_CALL(foo, Blah)
+      .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt())));
+```
+
+says that `Blah` will be called with arguments `x`, `y`, and `z` where `x < y <
+z`. Note that in this example, it wasn't necessary to specify the positional
+matchers.
+
+As a convenience and example, gMock provides some matchers for 2-tuples,
+including the `Lt()` matcher above. See
+[Multi-argument Matchers](reference/matchers.md#MultiArgMatchers) for the
+complete list.
+
+Note that if you want to pass the arguments to a predicate of your own (e.g.
+`.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be written to
+take a `std::tuple` as its argument; gMock will pass the `n` selected arguments
+as *one* single tuple to the predicate.
+
+### Using Matchers as Predicates
+
+Have you noticed that a matcher is just a fancy predicate that also knows how to
+describe itself? Many existing algorithms take predicates as arguments (e.g.
+those defined in STL's `<algorithm>` header), and it would be a shame if gMock
+matchers were not allowed to participate.
+
+Luckily, you can use a matcher where a unary predicate functor is expected by
+wrapping it inside the `Matches()` function. For example,
+
+```cpp
+#include <algorithm>
+#include <vector>
+
+using ::testing::Matches;
+using ::testing::Ge;
+
+vector<int> v;
+...
+// How many elements in v are >= 10?
+const int count = count_if(v.begin(), v.end(), Matches(Ge(10)));
+```
+
+Since you can build complex matchers from simpler ones easily using gMock, this
+gives you a way to conveniently construct composite predicates (doing the same
+using STL's `<functional>` header is just painful). For example, here's a
+predicate that's satisfied by any number that is >= 0, <= 100, and != 50:
+
+```cpp
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::Le;
+using ::testing::Matches;
+using ::testing::Ne;
+...
+Matches(AllOf(Ge(0), Le(100), Ne(50)))
+```
+
+### Using Matchers in googletest Assertions
+
+See [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) in the Assertions
+Reference.
+
+### Using Predicates as Matchers
+
+gMock provides a set of built-in matchers for matching arguments with expected
+values—see the [Matchers Reference](reference/matchers.md) for more information.
+In case you find the built-in set lacking, you can use an arbitrary unary
+predicate function or functor as a matcher - as long as the predicate accepts a
+value of the type you want. You do this by wrapping the predicate inside the
+`Truly()` function, for example:
+
+```cpp
+using ::testing::Truly;
+
+int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; }
+...
+  // Bar() must be called with an even number.
+  EXPECT_CALL(foo, Bar(Truly(IsEven)));
+```
+
+Note that the predicate function / functor doesn't have to return `bool`. It
+works as long as the return value can be used as the condition in the statement
+`if (condition) ...`.
+
+### Matching Arguments that Are Not Copyable
+
+When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, gMock saves away a copy of
+`bar`. When `Foo()` is called later, gMock compares the argument to `Foo()` with
+the saved copy of `bar`. This way, you don't need to worry about `bar` being
+modified or destroyed after the `EXPECT_CALL()` is executed. The same is true
+when you use matchers like `Eq(bar)`, `Le(bar)`, and so on.
+
+But what if `bar` cannot be copied (i.e. has no copy constructor)? You could
+define your own matcher function or callback and use it with `Truly()`, as the
+previous couple of recipes have shown. Or, you may be able to get away from it
+if you can guarantee that `bar` won't be changed after the `EXPECT_CALL()` is
+executed. Just tell gMock that it should save a reference to `bar`, instead of a
+copy of it. Here's how:
+
+```cpp
+using ::testing::Eq;
+using ::testing::Lt;
+...
+  // Expects that Foo()'s argument == bar.
+  EXPECT_CALL(mock_obj, Foo(Eq(std::ref(bar))));
+
+  // Expects that Foo()'s argument < bar.
+  EXPECT_CALL(mock_obj, Foo(Lt(std::ref(bar))));
+```
+
+Remember: if you do this, don't change `bar` after the `EXPECT_CALL()`, or the
+result is undefined.
+
+### Validating a Member of an Object
+
+Often a mock function takes a reference to object as an argument. When matching
+the argument, you may not want to compare the entire object against a fixed
+object, as that may be over-specification. Instead, you may need to validate a
+certain member variable or the result of a certain getter method of the object.
+You can do this with `Field()` and `Property()`. More specifically,
+
+```cpp
+Field(&Foo::bar, m)
+```
+
+is a matcher that matches a `Foo` object whose `bar` member variable satisfies
+matcher `m`.
+
+```cpp
+Property(&Foo::baz, m)
+```
+
+is a matcher that matches a `Foo` object whose `baz()` method returns a value
+that satisfies matcher `m`.
+
+For example:
+
+| Expression                   | Description                              |
+| :--------------------------- | :--------------------------------------- |
+| `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`.       |
+| `Property(&Foo::name,  StartsWith("John "))` | Matches `x` where `x.name()` starts with  `"John "`. |
+
+Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no argument
+and be declared as `const`. 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.
+
+`Field()` and `Property()` can also match plain pointers to objects. For
+instance,
+
+```cpp
+using ::testing::Field;
+using ::testing::Ge;
+...
+Field(&Foo::number, Ge(3))
+```
+
+matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`, the match
+will always fail regardless of the inner matcher.
+
+What if you want to validate more than one members at the same time? Remember
+that there are [`AllOf()` and `AllOfArray()`](#CombiningMatchers).
+
+Finally `Field()` and `Property()` provide overloads that take the field or
+property names as the first argument to include it in the error message. This
+can be useful when creating combined matchers.
+
+```cpp
+using ::testing::AllOf;
+using ::testing::Field;
+using ::testing::Matcher;
+using ::testing::SafeMatcherCast;
+
+Matcher<Foo> IsFoo(const Foo& foo) {
+  return AllOf(Field("some_field", &Foo::some_field, foo.some_field),
+               Field("other_field", &Foo::other_field, foo.other_field),
+               Field("last_field", &Foo::last_field, foo.last_field));
+}
+```
+
+### Validating the Value Pointed to by a Pointer Argument
+
+C++ functions often take pointers as arguments. You can use matchers like
+`IsNull()`, `NotNull()`, and other comparison matchers to match a pointer, but
+what if you want to make sure the value *pointed to* by the pointer, instead of
+the pointer itself, has a certain property? Well, you can use the `Pointee(m)`
+matcher.
+
+`Pointee(m)` matches a pointer if and only if `m` matches the value the pointer
+points to. For example:
+
+```cpp
+using ::testing::Ge;
+using ::testing::Pointee;
+...
+  EXPECT_CALL(foo, Bar(Pointee(Ge(3))));
+```
+
+expects `foo.Bar()` to be called with a pointer that points to a value greater
+than or equal to 3.
+
+One nice thing about `Pointee()` is that it treats a `NULL` pointer as a match
+failure, so you can write `Pointee(m)` instead of
+
+```cpp
+using ::testing::AllOf;
+using ::testing::NotNull;
+using ::testing::Pointee;
+...
+  AllOf(NotNull(), Pointee(m))
+```
+
+without worrying that a `NULL` pointer will crash your test.
+
+Also, did we tell you that `Pointee()` works with both raw pointers **and**
+smart pointers (`std::unique_ptr`, `std::shared_ptr`, etc)?
+
+What if you have a pointer to pointer? You guessed it - you can use nested
+`Pointee()` to probe deeper inside the value. For example,
+`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer that points
+to a number less than 3 (what a mouthful...).
+
+### Defining a Custom Matcher Class {#CustomMatcherClass}
+
+Most matchers can be simply defined using [the MATCHER* macros](#NewMatchers),
+which are terse and flexible, and produce good error messages. However, these
+macros are not very explicit about the interfaces they create and are not always
+suitable, especially for matchers that will be widely reused.
+
+For more advanced cases, you may need to define your own matcher class. A custom
+matcher allows you to test a specific invariant property of that object. Let's
+take a look at how to do so.
+
+Imagine you have a mock function that takes an object of type `Foo`, which has
+an `int bar()` method and an `int baz()` method. You want to constrain that the
+argument's `bar()` value plus its `baz()` value is a given number. (This is an
+invariant.) Here's how we can write and use a matcher class to do so:
+
+```cpp
+class BarPlusBazEqMatcher {
+ public:
+  using is_gtest_matcher = void;
+
+  explicit BarPlusBazEqMatcher(int expected_sum)
+      : expected_sum_(expected_sum) {}
+
+  bool MatchAndExplain(const Foo& foo,
+                       std::ostream* /* listener */) const {
+    return (foo.bar() + foo.baz()) == expected_sum_;
+  }
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "bar() + baz() equals " << expected_sum_;
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "bar() + baz() does not equal " << expected_sum_;
+  }
+ private:
+  const int expected_sum_;
+};
+
+::testing::Matcher<const Foo&> BarPlusBazEq(int expected_sum) {
+  return BarPlusBazEqMatcher(expected_sum);
+}
+
+...
+  Foo foo;
+  EXPECT_THAT(foo, BarPlusBazEq(5))...;
+```
+
+### Matching Containers
+
+Sometimes an STL container (e.g. list, vector, map, ...) is passed to a mock
+function and you may want to validate it. Since most STL containers support the
+`==` operator, you can write `Eq(expected_container)` or simply
+`expected_container` to match a container exactly.
+
+Sometimes, though, you may want to be more flexible (for example, the first
+element must be an exact match, but the second element can be any positive
+number, and so on). Also, containers used in tests often have a small number of
+elements, and having to define the expected container out-of-line is a bit of a
+hassle.
+
+You can use the `ElementsAre()` or `UnorderedElementsAre()` matcher in such
+cases:
+
+```cpp
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
+...
+  MOCK_METHOD(void, Foo, (const vector<int>& numbers), (override));
+...
+  EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5)));
+```
+
+The above matcher says that the container must have 4 elements, which must be 1,
+greater than 0, anything, and 5 respectively.
+
+If you instead write:
+
+```cpp
+using ::testing::_;
+using ::testing::Gt;
+using ::testing::UnorderedElementsAre;
+...
+  MOCK_METHOD(void, Foo, (const vector<int>& numbers), (override));
+...
+  EXPECT_CALL(mock, Foo(UnorderedElementsAre(1, Gt(0), _, 5)));
+```
+
+It means that the container must have 4 elements, which (under some permutation)
+must be 1, greater than 0, anything, and 5 respectively.
+
+As an alternative you can place the arguments in a C-style array and use
+`ElementsAreArray()` or `UnorderedElementsAreArray()` instead:
+
+```cpp
+using ::testing::ElementsAreArray;
+...
+  // ElementsAreArray accepts an array of element values.
+  const int expected_vector1[] = {1, 5, 2, 4, ...};
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1)));
+
+  // Or, an array of element matchers.
+  Matcher<int> expected_vector2[] = {1, Gt(2), _, 3, ...};
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2)));
+```
+
+In case the array needs to be dynamically created (and therefore the array size
+cannot be inferred by the compiler), you can give `ElementsAreArray()` an
+additional argument to specify the array size:
+
+```cpp
+using ::testing::ElementsAreArray;
+...
+  int* const expected_vector3 = new int[count];
+  ... fill expected_vector3 with values ...
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count)));
+```
+
+Use `Pair` when comparing maps or other associative containers.
+
+{% raw %}
+
+```cpp
+using ::testing::UnorderedElementsAre;
+using ::testing::Pair;
+...
+  absl::flat_hash_map<string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
+  EXPECT_THAT(m, UnorderedElementsAre(
+      Pair("a", 1), Pair("b", 2), Pair("c", 3)));
+```
+
+{% endraw %}
+
+**Tips:**
+
+*   `ElementsAre*()` can be used to match *any* container that implements the
+    STL iterator pattern (i.e. it has a `const_iterator` type and supports
+    `begin()/end()`), not just the ones defined in STL. It will even work with
+    container types yet to be written - as long as they follows the above
+    pattern.
+*   You can use nested `ElementsAre*()` to match nested (multi-dimensional)
+    containers.
+*   If the container is passed by pointer instead of by reference, just write
+    `Pointee(ElementsAre*(...))`.
+*   The order of elements *matters* for `ElementsAre*()`. If you are using it
+    with containers whose element order are undefined (such as a
+    `std::unordered_map`) you should use `UnorderedElementsAre`.
+
+### Sharing Matchers
+
+Under the hood, a gMock matcher object consists of a pointer to a ref-counted
+implementation object. Copying matchers is allowed and very efficient, as only
+the pointer is copied. When the last matcher that references the implementation
+object dies, the implementation object will be deleted.
+
+Therefore, if you have some complex matcher that you want to use again and
+again, there is no need to build it every time. Just assign it to a matcher
+variable and use that variable repeatedly! For example,
+
+```cpp
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::Le;
+using ::testing::Matcher;
+...
+  Matcher<int> in_range = AllOf(Gt(5), Le(10));
+  ... use in_range as a matcher in multiple EXPECT_CALLs ...
+```
+
+### Matchers must have no side-effects {#PureMatchers}
+
+{: .callout .warning}
+WARNING: gMock does not guarantee when or how many times a matcher will be
+invoked. Therefore, all matchers must be *purely functional*: they cannot have
+any side effects, and the match result must not depend on anything other than
+the matcher's parameters and the value being matched.
+
+This requirement must be satisfied no matter how a matcher is defined (e.g., if
+it is one of the standard matchers, or a custom matcher). In particular, a
+matcher can never call a mock function, as that will affect the state of the
+mock object and gMock.
+
+## Setting Expectations
+
+### Knowing When to Expect {#UseOnCall}
+
+**`ON_CALL`** is likely the *single most under-utilized construct* in gMock.
+
+There are basically two constructs for defining the behavior of a mock object:
+`ON_CALL` and `EXPECT_CALL`. The difference? `ON_CALL` defines what happens when
+a mock method is called, but <em>doesn't imply any expectation on the method
+being called</em>. `EXPECT_CALL` not only defines the behavior, but also sets an
+expectation that <em>the method will be called with the given arguments, for the
+given number of times</em> (and *in the given order* when you specify the order
+too).
+
+Since `EXPECT_CALL` does more, isn't it better than `ON_CALL`? Not really. Every
+`EXPECT_CALL` adds a constraint on the behavior of the code under test. Having
+more constraints than necessary is *baaad* - even worse than not having enough
+constraints.
+
+This may be counter-intuitive. How could tests that verify more be worse than
+tests that verify less? Isn't verification the whole point of tests?
+
+The answer lies in *what* a test should verify. **A good test verifies the
+contract of the code.** If a test over-specifies, it doesn't leave enough
+freedom to the implementation. As a result, changing the implementation without
+breaking the contract (e.g. refactoring and optimization), which should be
+perfectly fine to do, can break such tests. Then you have to spend time fixing
+them, only to see them broken again the next time the implementation is changed.
+
+Keep in mind that one doesn't have to verify more than one property in one test.
+In fact, **it's a good style to verify only one thing in one test.** If you do
+that, a bug will likely break only one or two tests instead of dozens (which
+case would you rather debug?). If you are also in the habit of giving tests
+descriptive names that tell what they verify, you can often easily guess what's
+wrong just from the test log itself.
+
+So use `ON_CALL` by default, and only use `EXPECT_CALL` when you actually intend
+to verify that the call is made. For example, you may have a bunch of `ON_CALL`s
+in your test fixture to set the common mock behavior shared by all tests in the
+same group, and write (scarcely) different `EXPECT_CALL`s in different `TEST_F`s
+to verify different aspects of the code's behavior. Compared with the style
+where each `TEST` has many `EXPECT_CALL`s, this leads to tests that are more
+resilient to implementational changes (and thus less likely to require
+maintenance) and makes the intent of the tests more obvious (so they are easier
+to maintain when you do need to maintain them).
+
+If you are bothered by the "Uninteresting mock function call" message printed
+when a mock method without an `EXPECT_CALL` is called, you may use a `NiceMock`
+instead to suppress all such messages for the mock object, or suppress the
+message for specific methods by adding `EXPECT_CALL(...).Times(AnyNumber())`. DO
+NOT suppress it by blindly adding an `EXPECT_CALL(...)`, or you'll have a test
+that's a pain to maintain.
+
+### Ignoring Uninteresting Calls
+
+If you are not interested in how a mock method is called, just don't say
+anything about it. In this case, if the method is ever called, gMock will
+perform its default action to allow the test program to continue. If you are not
+happy with the default action taken by gMock, you can override it using
+`DefaultValue<T>::Set()` (described [here](#DefaultValue)) or `ON_CALL()`.
+
+Please note that once you expressed interest in a particular mock method (via
+`EXPECT_CALL()`), all invocations to it must match some expectation. If this
+function is called but the arguments don't match any `EXPECT_CALL()` statement,
+it will be an error.
+
+### Disallowing Unexpected Calls
+
+If a mock method shouldn't be called at all, explicitly say so:
+
+```cpp
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .Times(0);
+```
+
+If some calls to the method are allowed, but the rest are not, just list all the
+expected calls:
+
+```cpp
+using ::testing::AnyNumber;
+using ::testing::Gt;
+...
+  EXPECT_CALL(foo, Bar(5));
+  EXPECT_CALL(foo, Bar(Gt(10)))
+      .Times(AnyNumber());
+```
+
+A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()` statements
+will be an error.
+
+### Understanding Uninteresting vs Unexpected Calls {#uninteresting-vs-unexpected}
+
+*Uninteresting* calls and *unexpected* calls are different concepts in gMock.
+*Very* different.
+
+A call `x.Y(...)` is **uninteresting** if there's *not even a single*
+`EXPECT_CALL(x, Y(...))` set. In other words, the test isn't interested in the
+`x.Y()` method at all, as evident in that the test doesn't care to say anything
+about it.
+
+A call `x.Y(...)` is **unexpected** if there are *some* `EXPECT_CALL(x,
+Y(...))`s set, but none of them matches the call. Put another way, the test is
+interested in the `x.Y()` method (therefore it explicitly sets some
+`EXPECT_CALL` to verify how it's called); however, the verification fails as the
+test doesn't expect this particular call to happen.
+
+**An unexpected call is always an error,** as the code under test doesn't behave
+the way the test expects it to behave.
+
+**By default, an uninteresting call is not an error,** as it violates no
+constraint specified by the test. (gMock's philosophy is that saying nothing
+means there is no constraint.) However, it leads to a warning, as it *might*
+indicate a problem (e.g. the test author might have forgotten to specify a
+constraint).
+
+In gMock, `NiceMock` and `StrictMock` can be used to make a mock class "nice" or
+"strict". How does this affect uninteresting calls and unexpected calls?
+
+A **nice mock** suppresses uninteresting call *warnings*. It is less chatty than
+the default mock, but otherwise is the same. If a test fails with a default
+mock, it will also fail using a nice mock instead. And vice versa. Don't expect
+making a mock nice to change the test's result.
+
+A **strict mock** turns uninteresting call warnings into errors. So making a
+mock strict may change the test's result.
+
+Let's look at an example:
+
+```cpp
+TEST(...) {
+  NiceMock<MockDomainRegistry> mock_registry;
+  EXPECT_CALL(mock_registry, GetDomainOwner("google.com"))
+          .WillRepeatedly(Return("Larry Page"));
+
+  // Use mock_registry in code under test.
+  ... &mock_registry ...
+}
+```
+
+The sole `EXPECT_CALL` here says that all calls to `GetDomainOwner()` must have
+`"google.com"` as the argument. If `GetDomainOwner("yahoo.com")` is called, it
+will be an unexpected call, and thus an error. *Having a nice mock doesn't
+change the severity of an unexpected call.*
+
+So how do we tell gMock that `GetDomainOwner()` can be called with some other
+arguments as well? The standard technique is to add a "catch all" `EXPECT_CALL`:
+
+```cpp
+  EXPECT_CALL(mock_registry, GetDomainOwner(_))
+        .Times(AnyNumber());  // catches all other calls to this method.
+  EXPECT_CALL(mock_registry, GetDomainOwner("google.com"))
+        .WillRepeatedly(Return("Larry Page"));
+```
+
+Remember that `_` is the wildcard matcher that matches anything. With this, if
+`GetDomainOwner("google.com")` is called, it will do what the second
+`EXPECT_CALL` says; if it is called with a different argument, it will do what
+the first `EXPECT_CALL` says.
+
+Note that the order of the two `EXPECT_CALL`s is important, as a newer
+`EXPECT_CALL` takes precedence over an older one.
+
+For more on uninteresting calls, nice mocks, and strict mocks, read
+["The Nice, the Strict, and the Naggy"](#NiceStrictNaggy).
+
+### Ignoring Uninteresting Arguments {#ParameterlessExpectations}
+
+If your test doesn't care about the parameters (it only cares about the number
+or order of calls), you can often simply omit the parameter list:
+
+```cpp
+  // Expect foo.Bar( ... ) twice with any arguments.
+  EXPECT_CALL(foo, Bar).Times(2);
+
+  // Delegate to the given method whenever the factory is invoked.
+  ON_CALL(foo_factory, MakeFoo)
+      .WillByDefault(&BuildFooForTest);
+```
+
+This functionality is only available when a method is not overloaded; to prevent
+unexpected behavior it is a compilation error to try to set an expectation on a
+method where the specific overload is ambiguous. You can work around this by
+supplying a [simpler mock interface](#SimplerInterfaces) than the mocked class
+provides.
+
+This pattern is also useful when the arguments are interesting, but match logic
+is substantially complex. You can leave the argument list unspecified and use
+SaveArg actions to [save the values for later verification](#SaveArgVerify). If
+you do that, you can easily differentiate calling the method the wrong number of
+times from calling it with the wrong arguments.
+
+### Expecting Ordered Calls {#OrderedCalls}
+
+Although an `EXPECT_CALL()` statement defined later takes precedence when gMock
+tries to match a function call with an expectation, by default calls don't have
+to happen in the order `EXPECT_CALL()` statements are written. For example, if
+the arguments match the matchers in the second `EXPECT_CALL()`, but not those in
+the first and third, then the second expectation will be used.
+
+If you would rather have all calls occur in the order of the expectations, put
+the `EXPECT_CALL()` statements in a block where you define a variable of type
+`InSequence`:
+
+```cpp
+using ::testing::_;
+using ::testing::InSequence;
+
+  {
+    InSequence s;
+
+    EXPECT_CALL(foo, DoThis(5));
+    EXPECT_CALL(bar, DoThat(_))
+        .Times(2);
+    EXPECT_CALL(foo, DoThis(6));
+  }
+```
+
+In this example, we expect a call to `foo.DoThis(5)`, followed by two calls to
+`bar.DoThat()` where the argument can be anything, which are in turn followed by
+a call to `foo.DoThis(6)`. If a call occurred out-of-order, gMock will report an
+error.
+
+### Expecting Partially Ordered Calls {#PartialOrder}
+
+Sometimes requiring everything to occur in a predetermined order can lead to
+brittle tests. For example, we may care about `A` occurring before both `B` and
+`C`, but aren't interested in the relative order of `B` and `C`. In this case,
+the test should reflect our real intent, instead of being overly constraining.
+
+gMock allows you to impose an arbitrary DAG (directed acyclic graph) on the
+calls. One way to express the DAG is to use the
+[`After` clause](reference/mocking.md#EXPECT_CALL.After) of `EXPECT_CALL`.
+
+Another way is via the `InSequence()` clause (not the same as the `InSequence`
+class), which we borrowed from jMock 2. It's less flexible than `After()`, but
+more convenient when you have long chains of sequential calls, as it doesn't
+require you to come up with different names for the expectations in the chains.
+Here's how it works:
+
+If we view `EXPECT_CALL()` statements as nodes in a graph, and add an edge from
+node A to node B wherever A must occur before B, we can get a DAG. We use the
+term "sequence" to mean a directed path in this DAG. Now, if we decompose the
+DAG into sequences, we just need to know which sequences each `EXPECT_CALL()`
+belongs to in order to be able to reconstruct the original DAG.
+
+So, to specify the partial order on the expectations we need to do two things:
+first to define some `Sequence` objects, and then for each `EXPECT_CALL()` say
+which `Sequence` objects it is part of.
+
+Expectations in the same sequence must occur in the order they are written. For
+example,
+
+```cpp
+using ::testing::Sequence;
+...
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo, A())
+      .InSequence(s1, s2);
+  EXPECT_CALL(bar, B())
+      .InSequence(s1);
+  EXPECT_CALL(bar, C())
+      .InSequence(s2);
+  EXPECT_CALL(foo, D())
+      .InSequence(s2);
+```
+
+specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A -> C -> D`):
+
+```text
+       +---> B
+       |
+  A ---|
+       |
+       +---> C ---> D
+```
+
+This means that A must occur before B and C, and C must occur before D. There's
+no restriction about the order other than these.
+
+### Controlling When an Expectation Retires
+
+When a mock method is called, gMock only considers expectations that are still
+active. An expectation is active when created, and becomes inactive (aka
+*retires*) when a call that has to occur later has occurred. For example, in
+
+```cpp
+using ::testing::_;
+using ::testing::Sequence;
+...
+  Sequence s1, s2;
+
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))      // #1
+      .Times(AnyNumber())
+      .InSequence(s1, s2);
+  EXPECT_CALL(log, Log(WARNING, _, "Data set is empty."))   // #2
+      .InSequence(s1);
+  EXPECT_CALL(log, Log(WARNING, _, "User not found."))      // #3
+      .InSequence(s2);
+```
+
+as soon as either #2 or #3 is matched, #1 will retire. If a warning `"File too
+large."` is logged after this, it will be an error.
+
+Note that an expectation doesn't retire automatically when it's saturated. For
+example,
+
+```cpp
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                     // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."));     // #2
+```
+
+says that there will be exactly one warning with the message `"File too
+large."`. If the second warning contains this message too, #2 will match again
+and result in an upper-bound-violated error.
+
+If this is not what you want, you can ask an expectation to retire as soon as it
+becomes saturated:
+
+```cpp
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                     // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))      // #2
+      .RetiresOnSaturation();
+```
+
+Here #2 can be used only once, so if you have two warnings with the message
+`"File too large."`, the first will match #2 and the second will match #1 -
+there will be no error.
+
+## Using Actions
+
+### Returning References from Mock Methods
+
+If a mock function's return type is a reference, you need to use `ReturnRef()`
+instead of `Return()` to return a result:
+
+```cpp
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(Bar&, GetBar, (), (override));
+};
+...
+  MockFoo foo;
+  Bar bar;
+  EXPECT_CALL(foo, GetBar())
+      .WillOnce(ReturnRef(bar));
+...
+```
+
+### Returning Live Values from Mock Methods
+
+The `Return(x)` action saves a copy of `x` when the action is created, and
+always returns the same value whenever it's executed. Sometimes you may want to
+instead return the *live* value of `x` (i.e. its value at the time when the
+action is *executed*.). Use either `ReturnRef()` or `ReturnPointee()` for this
+purpose.
+
+If the mock function's return type is a reference, you can do it using
+`ReturnRef(x)`, as shown in the previous recipe ("Returning References from Mock
+Methods"). However, gMock doesn't let you use `ReturnRef()` in a mock function
+whose return type is not a reference, as doing that usually indicates a user
+error. So, what shall you do?
+
+Though you may be tempted, DO NOT use `std::ref()`:
+
+```cpp
+using ::testing::Return;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(int, GetValue, (), (override));
+};
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(Return(std::ref(x)));  // Wrong!
+  x = 42;
+  EXPECT_EQ(foo.GetValue(), 42);
+```
+
+Unfortunately, it doesn't work here. The above code will fail with error:
+
+```text
+Value of: foo.GetValue()
+  Actual: 0
+Expected: 42
+```
+
+The reason is that `Return(*value*)` converts `value` to the actual return type
+of the mock function at the time when the action is *created*, not when it is
+*executed*. (This behavior was chosen for the action to be safe when `value` is
+a proxy object that references some temporary objects.) As a result,
+`std::ref(x)` is converted to an `int` value (instead of a `const int&`) when
+the expectation is set, and `Return(std::ref(x))` will always return 0.
+
+`ReturnPointee(pointer)` was provided to solve this problem specifically. It
+returns the value pointed to by `pointer` at the time the action is *executed*:
+
+```cpp
+using ::testing::ReturnPointee;
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(ReturnPointee(&x));  // Note the & here.
+  x = 42;
+  EXPECT_EQ(foo.GetValue(), 42);  // This will succeed now.
+```
+
+### Combining Actions
+
+Want to do more than one thing when a function is called? That's fine. `DoAll()`
+allows you to do a sequence of actions every time. Only the return value of the
+last action in the sequence will be used.
+
+```cpp
+using ::testing::_;
+using ::testing::DoAll;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(bool, Bar, (int n), (override));
+};
+...
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(DoAll(action_1,
+                      action_2,
+                      ...
+                      action_n));
+```
+
+The return value of the last action **must** match the return type of the mocked
+method. In the example above, `action_n` could be `Return(true)`, or a lambda
+that returns a `bool`, but not `SaveArg`, which returns `void`. Otherwise the
+signature of `DoAll` would not match the signature expected by `WillOnce`, which
+is the signature of the mocked method, and it wouldn't compile.
+
+### Verifying Complex Arguments {#SaveArgVerify}
+
+If you want to verify that a method is called with a particular argument but the
+match criteria is complex, it can be difficult to distinguish between
+cardinality failures (calling the method the wrong number of times) and argument
+match failures. Similarly, if you are matching multiple parameters, it may not
+be easy to distinguishing which argument failed to match. For example:
+
+```cpp
+  // Not ideal: this could fail because of a problem with arg1 or arg2, or maybe
+  // just the method wasn't called.
+  EXPECT_CALL(foo, SendValues(_, ElementsAre(1, 4, 4, 7), EqualsProto( ... )));
+```
+
+You can instead save the arguments and test them individually:
+
+```cpp
+  EXPECT_CALL(foo, SendValues)
+      .WillOnce(DoAll(SaveArg<1>(&actual_array), SaveArg<2>(&actual_proto)));
+  ... run the test
+  EXPECT_THAT(actual_array, ElementsAre(1, 4, 4, 7));
+  EXPECT_THAT(actual_proto, EqualsProto( ... ));
+```
+
+### Mocking Side Effects {#MockingSideEffects}
+
+Sometimes a method exhibits its effect not via returning a value but via side
+effects. For example, it may change some global state or modify an output
+argument. To mock side effects, in general you can define your own action by
+implementing `::testing::ActionInterface`.
+
+If all you need to do is to change an output argument, the built-in
+`SetArgPointee()` action is convenient:
+
+```cpp
+using ::testing::_;
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  MOCK_METHOD(void, Mutate, (bool mutate, int* value), (override));
+  ...
+}
+...
+  MockMutator mutator;
+  EXPECT_CALL(mutator, Mutate(true, _))
+      .WillOnce(SetArgPointee<1>(5));
+```
+
+In this example, when `mutator.Mutate()` is called, we will assign 5 to the
+`int` variable pointed to by argument #1 (0-based).
+
+`SetArgPointee()` conveniently makes an internal copy of the value you pass to
+it, removing the need to keep the value in scope and alive. The implication
+however is that the value must have a copy constructor and assignment operator.
+
+If the mock method also needs to return a value as well, you can chain
+`SetArgPointee()` with `Return()` using `DoAll()`, remembering to put the
+`Return()` statement last:
+
+```cpp
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  ...
+  MOCK_METHOD(bool, MutateInt, (int* value), (override));
+}
+...
+  MockMutator mutator;
+  EXPECT_CALL(mutator, MutateInt(_))
+      .WillOnce(DoAll(SetArgPointee<0>(5),
+                      Return(true)));
+```
+
+Note, however, that if you use the `ReturnOKWith()` method, it will override the
+values provided by `SetArgPointee()` in the response parameters of your function
+call.
+
+If the output argument is an array, use the `SetArrayArgument<N>(first, last)`
+action instead. It copies the elements in source range `[first, last)` to the
+array pointed to by the `N`-th (0-based) argument:
+
+```cpp
+using ::testing::NotNull;
+using ::testing::SetArrayArgument;
+
+class MockArrayMutator : public ArrayMutator {
+ public:
+  MOCK_METHOD(void, Mutate, (int* values, int num_values), (override));
+  ...
+}
+...
+  MockArrayMutator mutator;
+  int values[5] = {1, 2, 3, 4, 5};
+  EXPECT_CALL(mutator, Mutate(NotNull(), 5))
+      .WillOnce(SetArrayArgument<0>(values, values + 5));
+```
+
+This also works when the argument is an output iterator:
+
+```cpp
+using ::testing::_;
+using ::testing::SetArrayArgument;
+
+class MockRolodex : public Rolodex {
+ public:
+  MOCK_METHOD(void, GetNames, (std::back_insert_iterator<vector<string>>),
+              (override));
+  ...
+}
+...
+  MockRolodex rolodex;
+  vector<string> names = {"George", "John", "Thomas"};
+  EXPECT_CALL(rolodex, GetNames(_))
+      .WillOnce(SetArrayArgument<0>(names.begin(), names.end()));
+```
+
+### Changing a Mock Object's Behavior Based on the State
+
+If you expect a call to change the behavior of a mock object, you can use
+`::testing::InSequence` to specify different behaviors before and after the
+call:
+
+```cpp
+using ::testing::InSequence;
+using ::testing::Return;
+
+...
+  {
+     InSequence seq;
+     EXPECT_CALL(my_mock, IsDirty())
+         .WillRepeatedly(Return(true));
+     EXPECT_CALL(my_mock, Flush());
+     EXPECT_CALL(my_mock, IsDirty())
+         .WillRepeatedly(Return(false));
+  }
+  my_mock.FlushIfDirty();
+```
+
+This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called
+and return `false` afterwards.
+
+If the behavior change is more complex, you can store the effects in a variable
+and make a mock method get its return value from that variable:
+
+```cpp
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::Return;
+
+ACTION_P(ReturnPointee, p) { return *p; }
+...
+  int previous_value = 0;
+  EXPECT_CALL(my_mock, GetPrevValue)
+      .WillRepeatedly(ReturnPointee(&previous_value));
+  EXPECT_CALL(my_mock, UpdateValue)
+      .WillRepeatedly(SaveArg<0>(&previous_value));
+  my_mock.DoSomethingToUpdateValue();
+```
+
+Here `my_mock.GetPrevValue()` will always return the argument of the last
+`UpdateValue()` call.
+
+### Setting the Default Value for a Return Type {#DefaultValue}
+
+If a mock method's return type is a built-in C++ type or pointer, by default it
+will return 0 when invoked. Also, in C++ 11 and above, a mock method whose
+return type has a default constructor will return a default-constructed value by
+default. You only need to specify an action if this default value doesn't work
+for you.
+
+Sometimes, you may want to change this default value, or you may want to specify
+a default value for types gMock doesn't know about. You can do this using the
+`::testing::DefaultValue` class template:
+
+```cpp
+using ::testing::DefaultValue;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(Bar, CalculateBar, (), (override));
+};
+
+
+...
+  Bar default_bar;
+  // Sets the default return value for type Bar.
+  DefaultValue<Bar>::Set(default_bar);
+
+  MockFoo foo;
+
+  // We don't need to specify an action here, as the default
+  // return value works for us.
+  EXPECT_CALL(foo, CalculateBar());
+
+  foo.CalculateBar();  // This should return default_bar.
+
+  // Unsets the default return value.
+  DefaultValue<Bar>::Clear();
+```
+
+Please note that changing the default value for a type can make your tests hard
+to understand. We recommend you to use this feature judiciously. For example,
+you may want to make sure the `Set()` and `Clear()` calls are right next to the
+code that uses your mock.
+
+### Setting the Default Actions for a Mock Method
+
+You've learned how to change the default value of a given type. However, this
+may be too coarse for your purpose: perhaps you have two mock methods with the
+same return type and you want them to have different behaviors. The `ON_CALL()`
+macro allows you to customize your mock's behavior at the method level:
+
+```cpp
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Gt;
+using ::testing::Return;
+...
+  ON_CALL(foo, Sign(_))
+      .WillByDefault(Return(-1));
+  ON_CALL(foo, Sign(0))
+      .WillByDefault(Return(0));
+  ON_CALL(foo, Sign(Gt(0)))
+      .WillByDefault(Return(1));
+
+  EXPECT_CALL(foo, Sign(_))
+      .Times(AnyNumber());
+
+  foo.Sign(5);   // This should return 1.
+  foo.Sign(-9);  // This should return -1.
+  foo.Sign(0);   // This should return 0.
+```
+
+As you may have guessed, when there are more than one `ON_CALL()` statements,
+the newer ones in the order take precedence over the older ones. In other words,
+the **last** one that matches the function arguments will be used. This matching
+order allows you to set up the common behavior in a mock object's constructor or
+the test fixture's set-up phase and specialize the mock's behavior later.
+
+Note that both `ON_CALL` and `EXPECT_CALL` have the same "later statements take
+precedence" rule, but they don't interact. That is, `EXPECT_CALL`s have their
+own precedence order distinct from the `ON_CALL` precedence order.
+
+### Using Functions/Methods/Functors/Lambdas as Actions {#FunctionsAsActions}
+
+If the built-in actions don't suit you, you can use an existing callable
+(function, `std::function`, method, functor, lambda) as an action.
+
+```cpp
+using ::testing::_; using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(int, Sum, (int x, int y), (override));
+  MOCK_METHOD(bool, ComplexJob, (int x), (override));
+};
+
+int CalculateSum(int x, int y) { return x + y; }
+int Sum3(int x, int y, int z) { return x + y + z; }
+
+class Helper {
+ public:
+  bool ComplexJob(int x);
+};
+
+...
+  MockFoo foo;
+  Helper helper;
+  EXPECT_CALL(foo, Sum(_, _))
+      .WillOnce(&CalculateSum)
+      .WillRepeatedly(Invoke(NewPermanentCallback(Sum3, 1)));
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(Invoke(&helper, &Helper::ComplexJob))
+      .WillOnce([] { return true; })
+      .WillRepeatedly([](int x) { return x > 0; });
+
+  foo.Sum(5, 6);         // Invokes CalculateSum(5, 6).
+  foo.Sum(2, 3);         // Invokes Sum3(1, 2, 3).
+  foo.ComplexJob(10);    // Invokes helper.ComplexJob(10).
+  foo.ComplexJob(-1);    // Invokes the inline lambda.
+```
+
+The only requirement is that the type of the function, etc must be *compatible*
+with the signature of the mock function, meaning that the latter's arguments (if
+it takes any) can be implicitly converted to the corresponding arguments of the
+former, and the former's return type can be implicitly converted to that of the
+latter. So, you can invoke something whose type is *not* exactly the same as the
+mock function, as long as it's safe to do so - nice, huh?
+
+Note that:
+
+*   The action takes ownership of the callback and will delete it when the
+    action itself is destructed.
+*   If the type of a callback is derived from a base callback type `C`, you need
+    to implicitly cast it to `C` to resolve the overloading, e.g.
+
+    ```cpp
+    using ::testing::Invoke;
+    ...
+      ResultCallback<bool>* is_ok = ...;
+      ... Invoke(is_ok) ...;  // This works.
+
+      BlockingClosure* done = new BlockingClosure;
+      ... Invoke(implicit_cast<Closure*>(done)) ...;  // The cast is necessary.
+    ```
+
+### Using Functions with Extra Info as Actions
+
+The function or functor you call using `Invoke()` must have the same number of
+arguments as the mock function you use it for. Sometimes you may have a function
+that takes more arguments, and you are willing to pass in the extra arguments
+yourself to fill the gap. You can do this in gMock using callbacks with
+pre-bound arguments. Here's an example:
+
+```cpp
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(char, DoThis, (int n), (override));
+};
+
+char SignOfSum(int x, int y) {
+  const int sum = x + y;
+  return (sum > 0) ? '+' : (sum < 0) ? '-' : '0';
+}
+
+TEST_F(FooTest, Test) {
+  MockFoo foo;
+
+  EXPECT_CALL(foo, DoThis(2))
+      .WillOnce(Invoke(NewPermanentCallback(SignOfSum, 5)));
+  EXPECT_EQ(foo.DoThis(2), '+');  // Invokes SignOfSum(5, 2).
+}
+```
+
+### Invoking a Function/Method/Functor/Lambda/Callback Without Arguments
+
+`Invoke()` passes the mock function's arguments to the function, etc being
+invoked such that the callee has the full context of the call to work with. If
+the invoked function is not interested in some or all of the arguments, it can
+simply ignore them.
+
+Yet, a common pattern is that a test author wants to invoke a function without
+the arguments of the mock function. She could do that using a wrapper function
+that throws away the arguments before invoking an underlining nullary function.
+Needless to say, this can be tedious and obscures the intent of the test.
+
+There are two solutions to this problem. First, you can pass any callable of
+zero args as an action. Alternatively, use `InvokeWithoutArgs()`, which is like
+`Invoke()` except that it doesn't pass the mock function's arguments to the
+callee. Here's an example of each:
+
+```cpp
+using ::testing::_;
+using ::testing::InvokeWithoutArgs;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(bool, ComplexJob, (int n), (override));
+};
+
+bool Job1() { ... }
+bool Job2(int n, char c) { ... }
+
+...
+  MockFoo foo;
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce([] { Job1(); });
+      .WillOnce(InvokeWithoutArgs(NewPermanentCallback(Job2, 5, 'a')));
+
+  foo.ComplexJob(10);  // Invokes Job1().
+  foo.ComplexJob(20);  // Invokes Job2(5, 'a').
+```
+
+Note that:
+
+*   The action takes ownership of the callback and will delete it when the
+    action itself is destructed.
+*   If the type of a callback is derived from a base callback type `C`, you need
+    to implicitly cast it to `C` to resolve the overloading, e.g.
+
+    ```cpp
+    using ::testing::InvokeWithoutArgs;
+    ...
+      ResultCallback<bool>* is_ok = ...;
+      ... InvokeWithoutArgs(is_ok) ...;  // This works.
+
+      BlockingClosure* done = ...;
+      ... InvokeWithoutArgs(implicit_cast<Closure*>(done)) ...;
+      // The cast is necessary.
+    ```
+
+### Invoking an Argument of the Mock Function
+
+Sometimes a mock function will receive a function pointer, a functor (in other
+words, a "callable") as an argument, e.g.
+
+```cpp
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(bool, DoThis, (int n, (ResultCallback1<bool, int>* callback)),
+              (override));
+};
+```
+
+and you may want to invoke this callable argument:
+
+```cpp
+using ::testing::_;
+...
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(...);
+      // Will execute callback->Run(5), where callback is the
+      // second argument DoThis() receives.
+```
+
+{: .callout .note}
+NOTE: The section below is legacy documentation from before C++ had lambdas:
+
+Arghh, you need to refer to a mock function argument but C++ has no lambda
+(yet), so you have to define your own action. :-( Or do you really?
+
+Well, gMock has an action to solve *exactly* this problem:
+
+```cpp
+InvokeArgument<N>(arg_1, arg_2, ..., arg_m)
+```
+
+will invoke the `N`-th (0-based) argument the mock function receives, with
+`arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is a function
+pointer, a functor, or a callback. gMock handles them all.
+
+With that, you could write:
+
+```cpp
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(InvokeArgument<1>(5));
+      // Will execute callback->Run(5), where callback is the
+      // second argument DoThis() receives.
+```
+
+What if the callable takes an argument by reference? No problem - just wrap it
+inside `std::ref()`:
+
+```cpp
+  ...
+  MOCK_METHOD(bool, Bar,
+              ((ResultCallback2<bool, int, const Helper&>* callback)),
+              (override));
+  ...
+  using ::testing::_;
+  using ::testing::InvokeArgument;
+  ...
+  MockFoo foo;
+  Helper helper;
+  ...
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(InvokeArgument<0>(5, std::ref(helper)));
+      // std::ref(helper) guarantees that a reference to helper, not a copy of
+      // it, will be passed to the callback.
+```
+
+What if the callable takes an argument by reference and we do **not** wrap the
+argument in `std::ref()`? Then `InvokeArgument()` will *make a copy* of the
+argument, and pass a *reference to the copy*, instead of a reference to the
+original value, to the callable. This is especially handy when the argument is a
+temporary value:
+
+```cpp
+  ...
+  MOCK_METHOD(bool, DoThat, (bool (*f)(const double& x, const string& s)),
+              (override));
+  ...
+  using ::testing::_;
+  using ::testing::InvokeArgument;
+  ...
+  MockFoo foo;
+  ...
+  EXPECT_CALL(foo, DoThat(_))
+      .WillOnce(InvokeArgument<0>(5.0, string("Hi")));
+      // Will execute (*f)(5.0, string("Hi")), where f is the function pointer
+      // DoThat() receives.  Note that the values 5.0 and string("Hi") are
+      // temporary and dead once the EXPECT_CALL() statement finishes.  Yet
+      // it's fine to perform this action later, since a copy of the values
+      // are kept inside the InvokeArgument action.
+```
+
+### Ignoring an Action's Result
+
+Sometimes you have an action that returns *something*, but you need an action
+that returns `void` (perhaps you want to use it in a mock function that returns
+`void`, or perhaps it needs to be used in `DoAll()` and it's not the last in the
+list). `IgnoreResult()` lets you do that. For example:
+
+```cpp
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::IgnoreResult;
+using ::testing::Return;
+
+int Process(const MyData& data);
+string DoSomething();
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(void, Abc, (const MyData& data), (override));
+  MOCK_METHOD(bool, Xyz, (), (override));
+};
+
+  ...
+  MockFoo foo;
+  EXPECT_CALL(foo, Abc(_))
+      // .WillOnce(Invoke(Process));
+      // The above line won't compile as Process() returns int but Abc() needs
+      // to return void.
+      .WillOnce(IgnoreResult(Process));
+  EXPECT_CALL(foo, Xyz())
+      .WillOnce(DoAll(IgnoreResult(DoSomething),
+                      // Ignores the string DoSomething() returns.
+                      Return(true)));
+```
+
+Note that you **cannot** use `IgnoreResult()` on an action that already returns
+`void`. Doing so will lead to ugly compiler errors.
+
+### Selecting an Action's Arguments {#SelectingArgs}
+
+Say you have a mock function `Foo()` that takes seven arguments, and you have a
+custom action that you want to invoke when `Foo()` is called. Trouble is, the
+custom action only wants three arguments:
+
+```cpp
+using ::testing::_;
+using ::testing::Invoke;
+...
+  MOCK_METHOD(bool, Foo,
+              (bool visible, const string& name, int x, int y,
+               (const map<pair<int, int>>), double& weight, double min_weight,
+               double max_wight));
+...
+bool IsVisibleInQuadrant1(bool visible, int x, int y) {
+  return visible && x >= 0 && y >= 0;
+}
+...
+  EXPECT_CALL(mock, Foo)
+      .WillOnce(Invoke(IsVisibleInQuadrant1));  // Uh, won't compile. :-(
+```
+
+To please the compiler God, you need to define an "adaptor" that has the same
+signature as `Foo()` and calls the custom action with the right arguments:
+
+```cpp
+using ::testing::_;
+using ::testing::Invoke;
+...
+bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y,
+                            const map<pair<int, int>, double>& weight,
+                            double min_weight, double max_wight) {
+  return IsVisibleInQuadrant1(visible, x, y);
+}
+...
+  EXPECT_CALL(mock, Foo)
+      .WillOnce(Invoke(MyIsVisibleInQuadrant1));  // Now it works.
+```
+
+But isn't this awkward?
+
+gMock provides a generic *action adaptor*, so you can spend your time minding
+more important business than writing your own adaptors. Here's the syntax:
+
+```cpp
+WithArgs<N1, N2, ..., Nk>(action)
+```
+
+creates an action that passes the arguments of the mock function at the given
+indices (0-based) to the inner `action` and performs it. Using `WithArgs`, our
+original example can be written as:
+
+```cpp
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+...
+  EXPECT_CALL(mock, Foo)
+      .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1)));  // No need to define your own adaptor.
+```
+
+For better readability, gMock also gives you:
+
+*   `WithoutArgs(action)` when the inner `action` takes *no* argument, and
+*   `WithArg<N>(action)` (no `s` after `Arg`) when the inner `action` takes
+    *one* argument.
+
+As you may have realized, `InvokeWithoutArgs(...)` is just syntactic sugar for
+`WithoutArgs(Invoke(...))`.
+
+Here are more tips:
+
+*   The inner action used in `WithArgs` and friends does not have to be
+    `Invoke()` -- it can be anything.
+*   You can repeat an argument in the argument list if necessary, e.g.
+    `WithArgs<2, 3, 3, 5>(...)`.
+*   You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`.
+*   The types of the selected arguments do *not* have to match the signature of
+    the inner action exactly. It works as long as they can be implicitly
+    converted to the corresponding arguments of the inner action. For example,
+    if the 4-th argument of the mock function is an `int` and `my_action` takes
+    a `double`, `WithArg<4>(my_action)` will work.
+
+### Ignoring Arguments in Action Functions
+
+The [selecting-an-action's-arguments](#SelectingArgs) recipe showed us one way
+to make a mock function and an action with incompatible argument lists fit
+together. The downside is that wrapping the action in `WithArgs<...>()` can get
+tedious for people writing the tests.
+
+If you are defining a function (or method, functor, lambda, callback) to be used
+with `Invoke*()`, and you are not interested in some of its arguments, an
+alternative to `WithArgs` is to declare the uninteresting arguments as `Unused`.
+This makes the definition less cluttered and less fragile in case the types of
+the uninteresting arguments change. It could also increase the chance the action
+function can be reused. For example, given
+
+```cpp
+ public:
+  MOCK_METHOD(double, Foo, double(const string& label, double x, double y),
+              (override));
+  MOCK_METHOD(double, Bar, (int index, double x, double y), (override));
+```
+
+instead of
+
+```cpp
+using ::testing::_;
+using ::testing::Invoke;
+
+double DistanceToOriginWithLabel(const string& label, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+double DistanceToOriginWithIndex(int index, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+  EXPECT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOriginWithLabel));
+  EXPECT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOriginWithIndex));
+```
+
+you could write
+
+```cpp
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Unused;
+
+double DistanceToOrigin(Unused, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+  EXPECT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+  EXPECT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+```
+
+### Sharing Actions
+
+Just like matchers, a gMock action object consists of a pointer to a ref-counted
+implementation object. Therefore copying actions is also allowed and very
+efficient. When the last action that references the implementation object dies,
+the implementation object will be deleted.
+
+If you have some complex action that you want to use again and again, you may
+not have to build it from scratch every time. If the action doesn't have an
+internal state (i.e. if it always does the same thing no matter how many times
+it has been called), you can assign it to an action variable and use that
+variable repeatedly. For example:
+
+```cpp
+using ::testing::Action;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+...
+  Action<bool(int*)> set_flag = DoAll(SetArgPointee<0>(5),
+                                      Return(true));
+  ... use set_flag in .WillOnce() and .WillRepeatedly() ...
+```
+
+However, if the action has its own state, you may be surprised if you share the
+action object. Suppose you have an action factory `IncrementCounter(init)` which
+creates an action that increments and returns a counter whose initial value is
+`init`, using two actions created from the same expression and using a shared
+action will exhibit different behaviors. Example:
+
+```cpp
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(IncrementCounter(0));
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(IncrementCounter(0));
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 1 - DoThat() uses a different
+                 // counter than DoThis()'s.
+```
+
+versus
+
+```cpp
+using ::testing::Action;
+...
+  Action<int()> increment = IncrementCounter(0);
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(increment);
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(increment);
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 3 - the counter is shared.
+```
+
+### Testing Asynchronous Behavior
+
+One oft-encountered problem with gMock is that it can be hard to test
+asynchronous behavior. Suppose you had a `EventQueue` class that you wanted to
+test, and you created a separate `EventDispatcher` interface so that you could
+easily mock it out. However, the implementation of the class fired all the
+events on a background thread, which made test timings difficult. You could just
+insert `sleep()` statements and hope for the best, but that makes your test
+behavior nondeterministic. A better way is to use gMock actions and
+`Notification` objects to force your asynchronous test to behave synchronously.
+
+```cpp
+class MockEventDispatcher : public EventDispatcher {
+  MOCK_METHOD(bool, DispatchEvent, (int32), (override));
+};
+
+TEST(EventQueueTest, EnqueueEventTest) {
+  MockEventDispatcher mock_event_dispatcher;
+  EventQueue event_queue(&mock_event_dispatcher);
+
+  const int32 kEventId = 321;
+  absl::Notification done;
+  EXPECT_CALL(mock_event_dispatcher, DispatchEvent(kEventId))
+      .WillOnce([&done] { done.Notify(); });
+
+  event_queue.EnqueueEvent(kEventId);
+  done.WaitForNotification();
+}
+```
+
+In the example above, we set our normal gMock expectations, but then add an
+additional action to notify the `Notification` object. Now we can just call
+`Notification::WaitForNotification()` in the main thread to wait for the
+asynchronous call to finish. After that, our test suite is complete and we can
+safely exit.
+
+{: .callout .note}
+Note: this example has a downside: namely, if the expectation is not satisfied,
+our test will run forever. It will eventually time-out and fail, but it will
+take longer and be slightly harder to debug. To alleviate this problem, you can
+use `WaitForNotificationWithTimeout(ms)` instead of `WaitForNotification()`.
+
+## Misc Recipes on Using gMock
+
+### Mocking Methods That Use Move-Only Types
+
+C++11 introduced *move-only types*. A move-only-typed value can be moved from
+one object to another, but cannot be copied. `std::unique_ptr<T>` is probably
+the most commonly used move-only type.
+
+Mocking a method that takes and/or returns move-only types presents some
+challenges, but nothing insurmountable. This recipe shows you how you can do it.
+Note that the support for move-only method arguments was only introduced to
+gMock in April 2017; in older code, you may find more complex
+[workarounds](#LegacyMoveOnly) for lack of this feature.
+
+Let’s say we are working on a fictional project that lets one post and share
+snippets called “buzzes”. Your code uses these types:
+
+```cpp
+enum class AccessLevel { kInternal, kPublic };
+
+class Buzz {
+ public:
+  explicit Buzz(AccessLevel access) { ... }
+  ...
+};
+
+class Buzzer {
+ public:
+  virtual ~Buzzer() {}
+  virtual std::unique_ptr<Buzz> MakeBuzz(StringPiece text) = 0;
+  virtual bool ShareBuzz(std::unique_ptr<Buzz> buzz, int64_t timestamp) = 0;
+  ...
+};
+```
+
+A `Buzz` object represents a snippet being posted. A class that implements the
+`Buzzer` interface is capable of creating and sharing `Buzz`es. Methods in
+`Buzzer` may return a `unique_ptr<Buzz>` or take a `unique_ptr<Buzz>`. Now we
+need to mock `Buzzer` in our tests.
+
+To mock a method that accepts or returns move-only types, you just use the
+familiar `MOCK_METHOD` syntax as usual:
+
+```cpp
+class MockBuzzer : public Buzzer {
+ public:
+  MOCK_METHOD(std::unique_ptr<Buzz>, MakeBuzz, (StringPiece text), (override));
+  MOCK_METHOD(bool, ShareBuzz, (std::unique_ptr<Buzz> buzz, int64_t timestamp),
+              (override));
+};
+```
+
+Now that we have the mock class defined, we can use it in tests. In the
+following code examples, we assume that we have defined a `MockBuzzer` object
+named `mock_buzzer_`:
+
+```cpp
+  MockBuzzer mock_buzzer_;
+```
+
+First let’s see how we can set expectations on the `MakeBuzz()` method, which
+returns a `unique_ptr<Buzz>`.
+
+As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or
+`.WillRepeatedly()` clause), when that expectation fires, the default action for
+that method will be taken. Since `unique_ptr<>` has a default constructor that
+returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an
+action:
+
+```cpp
+using ::testing::IsNull;
+...
+  // Use the default action.
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("hello"));
+
+  // Triggers the previous EXPECT_CALL.
+  EXPECT_THAT(mock_buzzer_.MakeBuzz("hello"), IsNull());
+```
+
+If you are not happy with the default action, you can tweak it as usual; see
+[Setting Default Actions](#OnCall).
+
+If you just need to return a move-only value, you can use it in combination with
+`WillOnce`. For example:
+
+```cpp
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("hello"))
+      .WillOnce(Return(std::make_unique<Buzz>(AccessLevel::kInternal)));
+  EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("hello"));
+```
+
+Quiz time! What do you think will happen if a `Return` action is performed more
+than once (e.g. you write `... .WillRepeatedly(Return(std::move(...)));`)? Come
+think of it, after the first time the action runs, the source value will be
+consumed (since it’s a move-only value), so the next time around, there’s no
+value to move from -- you’ll get a run-time error that `Return(std::move(...))`
+can only be run once.
+
+If you need your mock method to do more than just moving a pre-defined value,
+remember that you can always use a lambda or a callable object, which can do
+pretty much anything you want:
+
+```cpp
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("x"))
+      .WillRepeatedly([](StringPiece text) {
+        return std::make_unique<Buzz>(AccessLevel::kInternal);
+      });
+
+  EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
+  EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
+```
+
+Every time this `EXPECT_CALL` fires, a new `unique_ptr<Buzz>` will be created
+and returned. You cannot do this with `Return(std::make_unique<...>(...))`.
+
+That covers returning move-only values; but how do we work with methods
+accepting move-only arguments? The answer is that they work normally, although
+some actions will not compile when any of method's arguments are move-only. You
+can always use `Return`, or a [lambda or functor](#FunctionsAsActions):
+
+```cpp
+  using ::testing::Unused;
+
+  EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)).WillOnce(Return(true));
+  EXPECT_TRUE(mock_buzzer_.ShareBuzz(std::make_unique<Buzz>(AccessLevel::kInternal)),
+              0);
+
+  EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)).WillOnce(
+      [](std::unique_ptr<Buzz> buzz, Unused) { return buzz != nullptr; });
+  EXPECT_FALSE(mock_buzzer_.ShareBuzz(nullptr, 0));
+```
+
+Many built-in actions (`WithArgs`, `WithoutArgs`,`DeleteArg`, `SaveArg`, ...)
+could in principle support move-only arguments, but the support for this is not
+implemented yet. If this is blocking you, please file a bug.
+
+A few actions (e.g. `DoAll`) copy their arguments internally, so they can never
+work with non-copyable objects; you'll have to use functors instead.
+
+#### Legacy workarounds for move-only types {#LegacyMoveOnly}
+
+Support for move-only function arguments was only introduced to gMock in April
+of 2017. In older code, you may encounter the following workaround for the lack
+of this feature (it is no longer necessary - we're including it just for
+reference):
+
+```cpp
+class MockBuzzer : public Buzzer {
+ public:
+  MOCK_METHOD(bool, DoShareBuzz, (Buzz* buzz, Time timestamp));
+  bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) override {
+    return DoShareBuzz(buzz.get(), timestamp);
+  }
+};
+```
+
+The trick is to delegate the `ShareBuzz()` method to a mock method (let’s call
+it `DoShareBuzz()`) that does not take move-only parameters. Then, instead of
+setting expectations on `ShareBuzz()`, you set them on the `DoShareBuzz()` mock
+method:
+
+```cpp
+  MockBuzzer mock_buzzer_;
+  EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _));
+
+  // When one calls ShareBuzz() on the MockBuzzer like this, the call is
+  // forwarded to DoShareBuzz(), which is mocked.  Therefore this statement
+  // will trigger the above EXPECT_CALL.
+  mock_buzzer_.ShareBuzz(std::make_unique<Buzz>(AccessLevel::kInternal), 0);
+```
+
+### Making the Compilation Faster
+
+Believe it or not, the *vast majority* of the time spent on compiling a mock
+class is in generating its constructor and destructor, as they perform
+non-trivial tasks (e.g. verification of the expectations). What's more, mock
+methods with different signatures have different types and thus their
+constructors/destructors need to be generated by the compiler separately. As a
+result, if you mock many different types of methods, compiling your mock class
+can get really slow.
+
+If you are experiencing slow compilation, you can move the definition of your
+mock class' constructor and destructor out of the class body and into a `.cc`
+file. This way, even if you `#include` your mock class in N files, the compiler
+only needs to generate its constructor and destructor once, resulting in a much
+faster compilation.
+
+Let's illustrate the idea using an example. Here's the definition of a mock
+class before applying this recipe:
+
+```cpp
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // Since we don't declare the constructor or the destructor,
+  // the compiler will generate them in every translation unit
+  // where this mock class is used.
+
+  MOCK_METHOD(int, DoThis, (), (override));
+  MOCK_METHOD(bool, DoThat, (const char* str), (override));
+  ... more mock methods ...
+};
+```
+
+After the change, it would look like:
+
+```cpp
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // The constructor and destructor are declared, but not defined, here.
+  MockFoo();
+  virtual ~MockFoo();
+
+  MOCK_METHOD(int, DoThis, (), (override));
+  MOCK_METHOD(bool, DoThat, (const char* str), (override));
+  ... more mock methods ...
+};
+```
+
+and
+
+```cpp
+// File mock_foo.cc.
+#include "path/to/mock_foo.h"
+
+// The definitions may appear trivial, but the functions actually do a
+// lot of things through the constructors/destructors of the member
+// variables used to implement the mock methods.
+MockFoo::MockFoo() {}
+MockFoo::~MockFoo() {}
+```
+
+### Forcing a Verification
+
+When it's being destroyed, your friendly mock object will automatically verify
+that all expectations on it have been satisfied, and will generate googletest
+failures if not. This is convenient as it leaves you with one less thing to
+worry about. That is, unless you are not sure if your mock object will be
+destroyed.
+
+How could it be that your mock object won't eventually be destroyed? Well, it
+might be created on the heap and owned by the code you are testing. Suppose
+there's a bug in that code and it doesn't delete the mock object properly - you
+could end up with a passing test when there's actually a bug.
+
+Using a heap checker is a good idea and can alleviate the concern, but its
+implementation is not 100% reliable. So, sometimes you do want to *force* gMock
+to verify a mock object before it is (hopefully) destructed. You can do this
+with `Mock::VerifyAndClearExpectations(&mock_object)`:
+
+```cpp
+TEST(MyServerTest, ProcessesRequest) {
+  using ::testing::Mock;
+
+  MockFoo* const foo = new MockFoo;
+  EXPECT_CALL(*foo, ...)...;
+  // ... other expectations ...
+
+  // server now owns foo.
+  MyServer server(foo);
+  server.ProcessRequest(...);
+
+  // In case that server's destructor will forget to delete foo,
+  // this will verify the expectations anyway.
+  Mock::VerifyAndClearExpectations(foo);
+}  // server is destroyed when it goes out of scope here.
+```
+
+{: .callout .tip}
+**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a `bool` to
+indicate whether the verification was successful (`true` for yes), so you can
+wrap that function call inside a `ASSERT_TRUE()` if there is no point going
+further when the verification has failed.
+
+Do not set new expectations after verifying and clearing a mock after its use.
+Setting expectations after code that exercises the mock has undefined behavior.
+See [Using Mocks in Tests](gmock_for_dummies.md#using-mocks-in-tests) for more
+information.
+
+### Using Checkpoints {#UsingCheckPoints}
+
+Sometimes you might want to test a mock object's behavior in phases whose sizes
+are each manageable, or you might want to set more detailed expectations about
+which API calls invoke which mock functions.
+
+A technique you can use is to put the expectations in a sequence and insert
+calls to a dummy "checkpoint" function at specific places. Then you can verify
+that the mock function calls do happen at the right time. For example, if you
+are exercising the code:
+
+```cpp
+  Foo(1);
+  Foo(2);
+  Foo(3);
+```
+
+and want to verify that `Foo(1)` and `Foo(3)` both invoke `mock.Bar("a")`, but
+`Foo(2)` doesn't invoke anything, you can write:
+
+```cpp
+using ::testing::MockFunction;
+
+TEST(FooTest, InvokesBarCorrectly) {
+  MyMock mock;
+  // Class MockFunction<F> has exactly one mock method.  It is named
+  // Call() and has type F.
+  MockFunction<void(string check_point_name)> check;
+  {
+    InSequence s;
+
+    EXPECT_CALL(mock, Bar("a"));
+    EXPECT_CALL(check, Call("1"));
+    EXPECT_CALL(check, Call("2"));
+    EXPECT_CALL(mock, Bar("a"));
+  }
+  Foo(1);
+  check.Call("1");
+  Foo(2);
+  check.Call("2");
+  Foo(3);
+}
+```
+
+The expectation spec says that the first `Bar("a")` call must happen before
+checkpoint "1", the second `Bar("a")` call must happen after checkpoint "2", and
+nothing should happen between the two checkpoints. The explicit checkpoints make
+it clear which `Bar("a")` is called by which call to `Foo()`.
+
+### Mocking Destructors
+
+Sometimes you want to make sure a mock object is destructed at the right time,
+e.g. after `bar->A()` is called but before `bar->B()` is called. We already know
+that you can specify constraints on the [order](#OrderedCalls) of mock function
+calls, so all we need to do is to mock the destructor of the mock function.
+
+This sounds simple, except for one problem: a destructor is a special function
+with special syntax and special semantics, and the `MOCK_METHOD` macro doesn't
+work for it:
+
+```cpp
+MOCK_METHOD(void, ~MockFoo, ());  // Won't compile!
+```
+
+The good news is that you can use a simple pattern to achieve the same effect.
+First, add a mock function `Die()` to your mock class and call it in the
+destructor, like this:
+
+```cpp
+class MockFoo : public Foo {
+  ...
+  // Add the following two lines to the mock class.
+  MOCK_METHOD(void, Die, ());
+  ~MockFoo() override { Die(); }
+};
+```
+
+(If the name `Die()` clashes with an existing symbol, choose another name.) Now,
+we have translated the problem of testing when a `MockFoo` object dies to
+testing when its `Die()` method is called:
+
+```cpp
+  MockFoo* foo = new MockFoo;
+  MockBar* bar = new MockBar;
+  ...
+  {
+    InSequence s;
+
+    // Expects *foo to die after bar->A() and before bar->B().
+    EXPECT_CALL(*bar, A());
+    EXPECT_CALL(*foo, Die());
+    EXPECT_CALL(*bar, B());
+  }
+```
+
+And that's that.
+
+### Using gMock and Threads {#UsingThreads}
+
+In a **unit** test, it's best if you could isolate and test a piece of code in a
+single-threaded context. That avoids race conditions and dead locks, and makes
+debugging your test much easier.
+
+Yet most programs are multi-threaded, and sometimes to test something we need to
+pound on it from more than one thread. gMock works for this purpose too.
+
+Remember the steps for using a mock:
+
+1.  Create a mock object `foo`.
+2.  Set its default actions and expectations using `ON_CALL()` and
+    `EXPECT_CALL()`.
+3.  The code under test calls methods of `foo`.
+4.  Optionally, verify and reset the mock.
+5.  Destroy the mock yourself, or let the code under test destroy it. The
+    destructor will automatically verify it.
+
+If you follow the following simple rules, your mocks and threads can live
+happily together:
+
+*   Execute your *test code* (as opposed to the code being tested) in *one*
+    thread. This makes your test easy to follow.
+*   Obviously, you can do step #1 without locking.
+*   When doing step #2 and #5, make sure no other thread is accessing `foo`.
+    Obvious too, huh?
+*   #3 and #4 can be done either in one thread or in multiple threads - anyway
+    you want. gMock takes care of the locking, so you don't have to do any -
+    unless required by your test logic.
+
+If you violate the rules (for example, if you set expectations on a mock while
+another thread is calling its methods), you get undefined behavior. That's not
+fun, so don't do it.
+
+gMock guarantees that the action for a mock function is done in the same thread
+that called the mock function. For example, in
+
+```cpp
+  EXPECT_CALL(mock, Foo(1))
+      .WillOnce(action1);
+  EXPECT_CALL(mock, Foo(2))
+      .WillOnce(action2);
+```
+
+if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2, gMock will
+execute `action1` in thread 1 and `action2` in thread 2.
+
+gMock does *not* impose a sequence on actions performed in different threads
+(doing so may create deadlocks as the actions may need to cooperate). This means
+that the execution of `action1` and `action2` in the above example *may*
+interleave. If this is a problem, you should add proper synchronization logic to
+`action1` and `action2` to make the test thread-safe.
+
+Also, remember that `DefaultValue<T>` is a global resource that potentially
+affects *all* living mock objects in your program. Naturally, you won't want to
+mess with it from multiple threads or when there still are mocks in action.
+
+### Controlling How Much Information gMock Prints
+
+When gMock sees something that has the potential of being an error (e.g. a mock
+function with no expectation is called, a.k.a. an uninteresting call, which is
+allowed but perhaps you forgot to explicitly ban the call), it prints some
+warning messages, including the arguments of the function, the return value, and
+the stack trace. Hopefully this will remind you to take a look and see if there
+is indeed a problem.
+
+Sometimes you are confident that your tests are correct and may not appreciate
+such friendly messages. Some other times, you are debugging your tests or
+learning about the behavior of the code you are testing, and wish you could
+observe every mock call that happens (including argument values, the return
+value, and the stack trace). Clearly, one size doesn't fit all.
+
+You can control how much gMock tells you using the `--gmock_verbose=LEVEL`
+command-line flag, where `LEVEL` is a string with three possible values:
+
+*   `info`: gMock will print all informational messages, warnings, and errors
+    (most verbose). At this setting, gMock will also log any calls to the
+    `ON_CALL/EXPECT_CALL` macros. It will include a stack trace in
+    "uninteresting call" warnings.
+*   `warning`: gMock will print both warnings and errors (less verbose); it will
+    omit the stack traces in "uninteresting call" warnings. This is the default.
+*   `error`: gMock will print errors only (least verbose).
+
+Alternatively, you can adjust the value of that flag from within your tests like
+so:
+
+```cpp
+  ::testing::FLAGS_gmock_verbose = "error";
+```
+
+If you find gMock printing too many stack frames with its informational or
+warning messages, remember that you can control their amount with the
+`--gtest_stack_trace_depth=max_depth` flag.
+
+Now, judiciously use the right flag to enable gMock serve you better!
+
+### Gaining Super Vision into Mock Calls
+
+You have a test using gMock. It fails: gMock tells you some expectations aren't
+satisfied. However, you aren't sure why: Is there a typo somewhere in the
+matchers? Did you mess up the order of the `EXPECT_CALL`s? Or is the code under
+test doing something wrong? How can you find out the cause?
+
+Won't it be nice if you have X-ray vision and can actually see the trace of all
+`EXPECT_CALL`s and mock method calls as they are made? For each call, would you
+like to see its actual argument values and which `EXPECT_CALL` gMock thinks it
+matches? If you still need some help to figure out who made these calls, how
+about being able to see the complete stack trace at each mock call?
+
+You can unlock this power by running your test with the `--gmock_verbose=info`
+flag. For example, given the test program:
+
+```cpp
+#include <gmock/gmock.h>
+
+using ::testing::_;
+using ::testing::HasSubstr;
+using ::testing::Return;
+
+class MockFoo {
+ public:
+  MOCK_METHOD(void, F, (const string& x, const string& y));
+};
+
+TEST(Foo, Bar) {
+  MockFoo mock;
+  EXPECT_CALL(mock, F(_, _)).WillRepeatedly(Return());
+  EXPECT_CALL(mock, F("a", "b"));
+  EXPECT_CALL(mock, F("c", HasSubstr("d")));
+
+  mock.F("a", "good");
+  mock.F("a", "b");
+}
+```
+
+if you run it with `--gmock_verbose=info`, you will see this output:
+
+```shell
+[ RUN       ] Foo.Bar
+
+foo_test.cc:14: EXPECT_CALL(mock, F(_, _)) invoked
+Stack trace: ...
+
+foo_test.cc:15: EXPECT_CALL(mock, F("a", "b")) invoked
+Stack trace: ...
+
+foo_test.cc:16: EXPECT_CALL(mock, F("c", HasSubstr("d"))) invoked
+Stack trace: ...
+
+foo_test.cc:14: Mock function call matches EXPECT_CALL(mock, F(_, _))...
+    Function call: F(@0x7fff7c8dad40"a",@0x7fff7c8dad10"good")
+Stack trace: ...
+
+foo_test.cc:15: Mock function call matches EXPECT_CALL(mock, F("a", "b"))...
+    Function call: F(@0x7fff7c8dada0"a",@0x7fff7c8dad70"b")
+Stack trace: ...
+
+foo_test.cc:16: Failure
+Actual function call count doesn't match EXPECT_CALL(mock, F("c", HasSubstr("d")))...
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] Foo.Bar
+```
+
+Suppose the bug is that the `"c"` in the third `EXPECT_CALL` is a typo and
+should actually be `"a"`. With the above message, you should see that the actual
+`F("a", "good")` call is matched by the first `EXPECT_CALL`, not the third as
+you thought. From that it should be obvious that the third `EXPECT_CALL` is
+written wrong. Case solved.
+
+If you are interested in the mock call trace but not the stack traces, you can
+combine `--gmock_verbose=info` with `--gtest_stack_trace_depth=0` on the test
+command line.
+
+### Running Tests in Emacs
+
+If you build and run your tests in Emacs using the `M-x google-compile` command
+(as many googletest users do), the source file locations of gMock and googletest
+errors will be highlighted. Just press `<Enter>` on one of them and you'll be
+taken to the offending line. Or, you can just type `C-x`` to jump to the next
+error.
+
+To make it even easier, you can add the following lines to your `~/.emacs` file:
+
+```text
+(global-set-key "\M-m"  'google-compile)  ; m is for make
+(global-set-key [M-down] 'next-error)
+(global-set-key [M-up]  '(lambda () (interactive) (next-error -1)))
+```
+
+Then you can type `M-m` to start a build (if you want to run the test as well,
+just make sure `foo_test.run` or `runtests` is in the build command you supply
+after typing `M-m`), or `M-up`/`M-down` to move back and forth between errors.
+
+## Extending gMock
+
+### Writing New Matchers Quickly {#NewMatchers}
+
+{: .callout .warning}
+WARNING: gMock does not guarantee when or how many times a matcher will be
+invoked. Therefore, all matchers must be functionally pure. See
+[this section](#PureMatchers) for more details.
+
+The `MATCHER*` family of macros can be used to define custom matchers easily.
+The syntax:
+
+```cpp
+MATCHER(name, description_string_expression) { statements; }
+```
+
+will define a matcher with the given name that executes the statements, which
+must return a `bool` to indicate if the match succeeds. Inside the statements,
+you can refer to the value being matched by `arg`, and refer to its type by
+`arg_type`.
+
+The *description string* is a `string`-typed expression that documents what the
+matcher does, and is used to generate the failure message when the match fails.
+It can (and should) reference the special `bool` variable `negation`, and should
+evaluate to the description of the matcher when `negation` is `false`, or that
+of the matcher's negation when `negation` is `true`.
+
+For convenience, we allow the description string to be empty (`""`), in which
+case gMock will use the sequence of words in the matcher name as the
+description.
+
+#### Basic Example
+
+```cpp
+MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; }
+```
+
+allows you to write
+
+```cpp
+  // Expects mock_foo.Bar(n) to be called where n is divisible by 7.
+  EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7()));
+```
+
+or,
+
+```cpp
+  using ::testing::Not;
+  ...
+  // Verifies that a value is divisible by 7 and the other is not.
+  EXPECT_THAT(some_expression, IsDivisibleBy7());
+  EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7()));
+```
+
+If the above assertions fail, they will print something like:
+
+```shell
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27
+  ...
+  Value of: some_other_expression
+  Expected: not (is divisible by 7)
+    Actual: 21
+```
+
+where the descriptions `"is divisible by 7"` and `"not (is divisible by 7)"` are
+automatically calculated from the matcher name `IsDivisibleBy7`.
+
+#### Adding Custom Failure Messages
+
+As you may have noticed, the auto-generated descriptions (especially those for
+the negation) may not be so great. You can always override them with a `string`
+expression of your own:
+
+```cpp
+MATCHER(IsDivisibleBy7,
+        absl::StrCat(negation ? "isn't" : "is", " divisible by 7")) {
+  return (arg % 7) == 0;
+}
+```
+
+Optionally, you can stream additional information to a hidden argument named
+`result_listener` to explain the match result. For example, a better definition
+of `IsDivisibleBy7` is:
+
+```cpp
+MATCHER(IsDivisibleBy7, "") {
+  if ((arg % 7) == 0)
+    return true;
+
+  *result_listener << "the remainder is " << (arg % 7);
+  return false;
+}
+```
+
+With this definition, the above assertion will give a better message:
+
+```shell
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27 (the remainder is 6)
+```
+
+#### Using EXPECT_ Statements in Matchers
+
+You can also use `EXPECT_...` (and `ASSERT_...`) statements inside custom
+matcher definitions. In many cases, this allows you to write your matcher more
+concisely while still providing an informative error message. For example:
+
+```cpp
+MATCHER(IsDivisibleBy7, "") {
+  const auto remainder = arg % 7;
+  EXPECT_EQ(remainder, 0);
+  return true;
+}
+```
+
+If you write a test that includes the line `EXPECT_THAT(27, IsDivisibleBy7());`,
+you will get an error something like the following:
+
+```shell
+Expected equality of these values:
+  remainder
+    Which is: 6
+  0
+```
+
+#### `MatchAndExplain`
+
+You should let `MatchAndExplain()` print *any additional information* that can
+help a user understand the match result. Note that it should explain why the
+match succeeds in case of a success (unless it's obvious) - this is useful when
+the matcher is used inside `Not()`. There is no need to print the argument value
+itself, as gMock already prints it for you.
+
+#### Argument Types
+
+The type of the value being matched (`arg_type`) is determined by the
+context in which you use the matcher and is supplied to you by the compiler, so
+you don't need to worry about declaring it (nor can you). This allows the
+matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match
+any type where the value of `(arg % 7) == 0` can be implicitly converted to a
+`bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an
+`int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will
+be `unsigned long`; and so on.
+
+### Writing New Parameterized Matchers Quickly
+
+Sometimes you'll want to define a matcher that has parameters. For that you can
+use the macro:
+
+```cpp
+MATCHER_P(name, param_name, description_string) { statements; }
+```
+
+where the description string can be either `""` or a `string` expression that
+references `negation` and `param_name`.
+
+For example:
+
+```cpp
+MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+```
+
+will allow you to write:
+
+```cpp
+  EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+```
+
+which may lead to this message (assuming `n` is 10):
+
+```shell
+  Value of: Blah("a")
+  Expected: has absolute value 10
+    Actual: -9
+```
+
+Note that both the matcher description and its parameter are printed, making the
+message human-friendly.
+
+In the matcher definition body, you can write `foo_type` to reference the type
+of a parameter named `foo`. For example, in the body of
+`MATCHER_P(HasAbsoluteValue, value)` above, you can write `value_type` to refer
+to the type of `value`.
+
+gMock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to `MATCHER_P10` to
+support multi-parameter matchers:
+
+```cpp
+MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; }
+```
+
+Please note that the custom description string is for a particular *instance* of
+the matcher, where the parameters have been bound to actual values. Therefore
+usually you'll want the parameter values to be part of the description. gMock
+lets you do that by referencing the matcher parameters in the description string
+expression.
+
+For example,
+
+```cpp
+using ::testing::PrintToString;
+MATCHER_P2(InClosedRange, low, hi,
+           absl::StrFormat("%s in range [%s, %s]", negation ? "isn't" : "is",
+                           PrintToString(low), PrintToString(hi))) {
+  return low <= arg && arg <= hi;
+}
+...
+EXPECT_THAT(3, InClosedRange(4, 6));
+```
+
+would generate a failure that contains the message:
+
+```shell
+  Expected: is in range [4, 6]
+```
+
+If you specify `""` as the description, the failure message will contain the
+sequence of words in the matcher name followed by the parameter values printed
+as a tuple. For example,
+
+```cpp
+  MATCHER_P2(InClosedRange, low, hi, "") { ... }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+
+would generate a failure that contains the text:
+
+```shell
+  Expected: in closed range (4, 6)
+```
+
+For the purpose of typing, you can view
+
+```cpp
+MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+```
+
+as shorthand for
+
+```cpp
+template <typename p1_type, ..., typename pk_type>
+FooMatcherPk<p1_type, ..., pk_type>
+Foo(p1_type p1, ..., pk_type pk) { ... }
+```
+
+When you write `Foo(v1, ..., vk)`, the compiler infers the types of the
+parameters `v1`, ..., and `vk` for you. If you are not happy with the result of
+the type inference, you can specify the types by explicitly instantiating the
+template, as in `Foo<long, bool>(5, false)`. As said earlier, you don't get to
+(or need to) specify `arg_type` as that's determined by the context in which the
+matcher is used.
+
+You can assign the result of expression `Foo(p1, ..., pk)` to a variable of type
+`FooMatcherPk<p1_type, ..., pk_type>`. This can be useful when composing
+matchers. Matchers that don't have a parameter or have only one parameter have
+special types: you can assign `Foo()` to a `FooMatcher`-typed variable, and
+assign `Foo(p)` to a `FooMatcherP<p_type>`-typed variable.
+
+While you can instantiate a matcher template with reference types, passing the
+parameters by pointer usually makes your code more readable. If, however, you
+still want to pass a parameter by reference, be aware that in the failure
+message generated by the matcher you will see the value of the referenced object
+but not its address.
+
+You can overload matchers with different numbers of parameters:
+
+```cpp
+MATCHER_P(Blah, a, description_string_1) { ... }
+MATCHER_P2(Blah, a, b, description_string_2) { ... }
+```
+
+While it's tempting to always use the `MATCHER*` macros when defining a new
+matcher, you should also consider implementing the matcher interface directly
+instead (see the recipes that follow), especially if you need to use the matcher
+a lot. While these approaches require more work, they give you more control on
+the types of the value being matched and the matcher parameters, which in
+general leads to better compiler error messages that pay off in the long run.
+They also allow overloading matchers based on parameter types (as opposed to
+just based on the number of parameters).
+
+### Writing New Monomorphic Matchers
+
+A matcher of argument type `T` implements the matcher interface for `T` and does
+two things: it tests whether a value of type `T` matches the matcher, and can
+describe what kind of values it matches. The latter ability is used for
+generating readable error messages when expectations are violated.
+
+A matcher of `T` must declare a typedef like:
+
+```cpp
+using is_gtest_matcher = void;
+```
+
+and supports the following operations:
+
+```cpp
+// Match a value and optionally explain into an ostream.
+bool matched = matcher.MatchAndExplain(value, maybe_os);
+// where `value` is of type `T` and
+// `maybe_os` is of type `std::ostream*`, where it can be null if the caller
+// is not interested in there textual explanation.
+
+matcher.DescribeTo(os);
+matcher.DescribeNegationTo(os);
+// where `os` is of type `std::ostream*`.
+```
+
+If you need a custom matcher but `Truly()` is not a good option (for example,
+you may not be happy with the way `Truly(predicate)` describes itself, or you
+may want your matcher to be polymorphic as `Eq(value)` is), you can define a
+matcher to do whatever you want in two steps: first implement the matcher
+interface, and then define a factory function to create a matcher instance. The
+second step is not strictly needed but it makes the syntax of using the matcher
+nicer.
+
+For example, you can define a matcher to test whether an `int` is divisible by 7
+and then use it like this:
+
+```cpp
+using ::testing::Matcher;
+
+class DivisibleBy7Matcher {
+ public:
+  using is_gtest_matcher = void;
+
+  bool MatchAndExplain(int n, std::ostream*) const {
+    return (n % 7) == 0;
+  }
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "is divisible by 7";
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "is not divisible by 7";
+  }
+};
+
+Matcher<int> DivisibleBy7() {
+  return DivisibleBy7Matcher();
+}
+
+...
+  EXPECT_CALL(foo, Bar(DivisibleBy7()));
+```
+
+You may improve the matcher message by streaming additional information to the
+`os` argument in `MatchAndExplain()`:
+
+```cpp
+class DivisibleBy7Matcher {
+ public:
+  bool MatchAndExplain(int n, std::ostream* os) const {
+    const int remainder = n % 7;
+    if (remainder != 0 && os != nullptr) {
+      *os << "the remainder is " << remainder;
+    }
+    return remainder == 0;
+  }
+  ...
+};
+```
+
+Then, `EXPECT_THAT(x, DivisibleBy7());` may generate a message like this:
+
+```shell
+Value of: x
+Expected: is divisible by 7
+  Actual: 23 (the remainder is 2)
+```
+
+{: .callout .tip}
+Tip: for convenience, `MatchAndExplain()` can take a `MatchResultListener*`
+instead of `std::ostream*`.
+
+### Writing New Polymorphic Matchers
+
+Expanding what we learned above to *polymorphic* matchers is now just as simple
+as adding templates in the right place.
+
+```cpp
+
+class NotNullMatcher {
+ public:
+  using is_gtest_matcher = void;
+
+  // To implement a polymorphic matcher, we just need to make MatchAndExplain a
+  // template on its first argument.
+
+  // In this example, we want to use NotNull() with any pointer, so
+  // MatchAndExplain() accepts a pointer of any type as its first argument.
+  // In general, you can define MatchAndExplain() as an ordinary method or
+  // a method template, or even overload it.
+  template <typename T>
+  bool MatchAndExplain(T* p, std::ostream*) const {
+    return p != nullptr;
+  }
+
+  // Describes the property of a value matching this matcher.
+  void DescribeTo(std::ostream* os) const { *os << "is not NULL"; }
+
+  // Describes the property of a value NOT matching this matcher.
+  void DescribeNegationTo(std::ostream* os) const { *os << "is NULL"; }
+};
+
+NotNullMatcher NotNull() {
+  return NotNullMatcher();
+}
+
+...
+
+  EXPECT_CALL(foo, Bar(NotNull()));  // The argument must be a non-NULL pointer.
+```
+
+### Legacy Matcher Implementation
+
+Defining matchers used to be somewhat more complicated, in which it required
+several supporting classes and virtual functions. To implement a matcher for
+type `T` using the legacy API you have to derive from `MatcherInterface<T>` and
+call `MakeMatcher` to construct the object.
+
+The interface looks like this:
+
+```cpp
+class MatchResultListener {
+ public:
+  ...
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x);
+
+  // Returns the underlying ostream.
+  std::ostream* stream();
+};
+
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface();
+
+  // Returns true if and only if the matcher matches x; also explains the match
+  // result to 'listener'.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.
+  virtual void DescribeTo(std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.
+  virtual void DescribeNegationTo(std::ostream* os) const;
+};
+```
+
+Fortunately, most of the time you can define a polymorphic matcher easily with
+the help of `MakePolymorphicMatcher()`. Here's how you can define `NotNull()` as
+an example:
+
+```cpp
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+using ::testing::PolymorphicMatcher;
+
+class NotNullMatcher {
+ public:
+  // To implement a polymorphic matcher, first define a COPYABLE class
+  // that has three members MatchAndExplain(), DescribeTo(), and
+  // DescribeNegationTo(), like the following.
+
+  // In this example, we want to use NotNull() with any pointer, so
+  // MatchAndExplain() accepts a pointer of any type as its first argument.
+  // In general, you can define MatchAndExplain() as an ordinary method or
+  // a method template, or even overload it.
+  template <typename T>
+  bool MatchAndExplain(T* p,
+                       MatchResultListener* /* listener */) const {
+    return p != NULL;
+  }
+
+  // Describes the property of a value matching this matcher.
+  void DescribeTo(std::ostream* os) const { *os << "is not NULL"; }
+
+  // Describes the property of a value NOT matching this matcher.
+  void DescribeNegationTo(std::ostream* os) const { *os << "is NULL"; }
+};
+
+// To construct a polymorphic matcher, pass an instance of the class
+// to MakePolymorphicMatcher().  Note the return type.
+PolymorphicMatcher<NotNullMatcher> NotNull() {
+  return MakePolymorphicMatcher(NotNullMatcher());
+}
+
+...
+
+  EXPECT_CALL(foo, Bar(NotNull()));  // The argument must be a non-NULL pointer.
+```
+
+{: .callout .note}
+**Note:** Your polymorphic matcher class does **not** need to inherit from
+`MatcherInterface` or any other class, and its methods do **not** need to be
+virtual.
+
+Like in a monomorphic matcher, you may explain the match result by streaming
+additional information to the `listener` argument in `MatchAndExplain()`.
+
+### Writing New Cardinalities
+
+A cardinality is used in `Times()` to tell gMock how many times you expect a
+call to occur. It doesn't have to be exact. For example, you can say
+`AtLeast(5)` or `Between(2, 4)`.
+
+If the [built-in set](gmock_cheat_sheet.md#CardinalityList) of cardinalities
+doesn't suit you, you are free to define your own by implementing the following
+interface (in namespace `testing`):
+
+```cpp
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface();
+
+  // Returns true if and only if call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true if and only if call_count calls will saturate this
+  // cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(std::ostream* os) const = 0;
+};
+```
+
+For example, to specify that a call must occur even number of times, you can
+write
+
+```cpp
+using ::testing::Cardinality;
+using ::testing::CardinalityInterface;
+using ::testing::MakeCardinality;
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  bool IsSatisfiedByCallCount(int call_count) const override {
+    return (call_count % 2) == 0;
+  }
+
+  bool IsSaturatedByCallCount(int call_count) const override {
+    return false;
+  }
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() {
+  return MakeCardinality(new EvenNumberCardinality);
+}
+
+...
+  EXPECT_CALL(foo, Bar(3))
+      .Times(EvenNumber());
+```
+
+### Writing New Actions {#QuickNewActions}
+
+If the built-in actions don't work for you, you can easily define your own one.
+All you need is a call operator with a signature compatible with the mocked
+function. So you can use a lambda:
+
+```cpp
+MockFunction<int(int)> mock;
+EXPECT_CALL(mock, Call).WillOnce([](const int input) { return input * 7; });
+EXPECT_EQ(mock.AsStdFunction()(2), 14);
+```
+
+Or a struct with a call operator (even a templated one):
+
+```cpp
+struct MultiplyBy {
+  template <typename T>
+  T operator()(T arg) { return arg * multiplier; }
+
+  int multiplier;
+};
+
+// Then use:
+// EXPECT_CALL(...).WillOnce(MultiplyBy{7});
+```
+
+It's also fine for the callable to take no arguments, ignoring the arguments
+supplied to the mock function:
+
+```cpp
+MockFunction<int(int)> mock;
+EXPECT_CALL(mock, Call).WillOnce([] { return 17; });
+EXPECT_EQ(mock.AsStdFunction()(0), 17);
+```
+
+When used with `WillOnce`, the callable can assume it will be called at most
+once and is allowed to be a move-only type:
+
+```cpp
+// An action that contains move-only types and has an &&-qualified operator,
+// demanding in the type system that it be called at most once. This can be
+// used with WillOnce, but the compiler will reject it if handed to
+// WillRepeatedly.
+struct MoveOnlyAction {
+  std::unique_ptr<int> move_only_state;
+  std::unique_ptr<int> operator()() && { return std::move(move_only_state); }
+};
+
+MockFunction<std::unique_ptr<int>()> mock;
+EXPECT_CALL(mock, Call).WillOnce(MoveOnlyAction{std::make_unique<int>(17)});
+EXPECT_THAT(mock.AsStdFunction()(), Pointee(Eq(17)));
+```
+
+More generally, to use with a mock function whose signature is `R(Args...)` the
+object can be anything convertible to `OnceAction<R(Args...)>` or
+`Action<R(Args...)`>. The difference between the two is that `OnceAction` has
+weaker requirements (`Action` requires a copy-constructible input that can be
+called repeatedly whereas `OnceAction` requires only move-constructible and
+supports `&&`-qualified call operators), but can be used only with `WillOnce`.
+`OnceAction` is typically relevant only when supporting move-only types or
+actions that want a type-system guarantee that they will be called at most once.
+
+Typically the `OnceAction` and `Action` templates need not be referenced
+directly in your actions: a struct or class with a call operator is sufficient,
+as in the examples above. But fancier polymorphic actions that need to know the
+specific return type of the mock function can define templated conversion
+operators to make that possible. See `gmock-actions.h` for examples.
+
+#### Legacy macro-based Actions
+
+Before C++11, the functor-based actions were not supported; the old way of
+writing actions was through a set of `ACTION*` macros. We suggest to avoid them
+in new code; they hide a lot of logic behind the macro, potentially leading to
+harder-to-understand compiler errors. Nevertheless, we cover them here for
+completeness.
+
+By writing
+
+```cpp
+ACTION(name) { statements; }
+```
+
+in a namespace scope (i.e. not inside a class or function), you will define an
+action with the given name that executes the statements. The value returned by
+`statements` will be used as the return value of the action. Inside the
+statements, you can refer to the K-th (0-based) argument of the mock function as
+`argK`. For example:
+
+```cpp
+ACTION(IncrementArg1) { return ++(*arg1); }
+```
+
+allows you to write
+
+```cpp
+... WillOnce(IncrementArg1());
+```
+
+Note that you don't need to specify the types of the mock function arguments.
+Rest assured that your code is type-safe though: you'll get a compiler error if
+`*arg1` doesn't support the `++` operator, or if the type of `++(*arg1)` isn't
+compatible with the mock function's return type.
+
+Another example:
+
+```cpp
+ACTION(Foo) {
+  (*arg2)(5);
+  Blah();
+  *arg1 = 0;
+  return arg0;
+}
+```
+
+defines an action `Foo()` that invokes argument #2 (a function pointer) with 5,
+calls function `Blah()`, sets the value pointed to by argument #1 to 0, and
+returns argument #0.
+
+For more convenience and flexibility, you can also use the following pre-defined
+symbols in the body of `ACTION`:
+
+`argK_type`     | The type of the K-th (0-based) argument of the mock function
+:-------------- | :-----------------------------------------------------------
+`args`          | All arguments of the mock function as a tuple
+`args_type`     | The type of all arguments of the mock function as a tuple
+`return_type`   | The return type of the mock function
+`function_type` | The type of the mock function
+
+For example, when using an `ACTION` as a stub action for mock function:
+
+```cpp
+int DoSomething(bool flag, int* ptr);
+```
+
+we have:
+
+Pre-defined Symbol | Is Bound To
+------------------ | ---------------------------------
+`arg0`             | the value of `flag`
+`arg0_type`        | the type `bool`
+`arg1`             | the value of `ptr`
+`arg1_type`        | the type `int*`
+`args`             | the tuple `(flag, ptr)`
+`args_type`        | the type `std::tuple<bool, int*>`
+`return_type`      | the type `int`
+`function_type`    | the type `int(bool, int*)`
+
+#### Legacy macro-based parameterized Actions
+
+Sometimes you'll want to parameterize an action you define. For that we have
+another macro
+
+```cpp
+ACTION_P(name, param) { statements; }
+```
+
+For example,
+
+```cpp
+ACTION_P(Add, n) { return arg0 + n; }
+```
+
+will allow you to write
+
+```cpp
+// Returns argument #0 + 5.
+... WillOnce(Add(5));
+```
+
+For convenience, we use the term *arguments* for the values used to invoke the
+mock function, and the term *parameters* for the values used to instantiate an
+action.
+
+Note that you don't need to provide the type of the parameter either. Suppose
+the parameter is named `param`, you can also use the gMock-defined symbol
+`param_type` to refer to the type of the parameter as inferred by the compiler.
+For example, in the body of `ACTION_P(Add, n)` above, you can write `n_type` for
+the type of `n`.
+
+gMock also provides `ACTION_P2`, `ACTION_P3`, and etc to support multi-parameter
+actions. For example,
+
+```cpp
+ACTION_P2(ReturnDistanceTo, x, y) {
+  double dx = arg0 - x;
+  double dy = arg1 - y;
+  return sqrt(dx*dx + dy*dy);
+}
+```
+
+lets you write
+
+```cpp
+... WillOnce(ReturnDistanceTo(5.0, 26.5));
+```
+
+You can view `ACTION` as a degenerated parameterized action where the number of
+parameters is 0.
+
+You can also easily define actions overloaded on the number of parameters:
+
+```cpp
+ACTION_P(Plus, a) { ... }
+ACTION_P2(Plus, a, b) { ... }
+```
+
+### Restricting the Type of an Argument or Parameter in an ACTION
+
+For maximum brevity and reusability, the `ACTION*` macros don't ask you to
+provide the types of the mock function arguments and the action parameters.
+Instead, we let the compiler infer the types for us.
+
+Sometimes, however, we may want to be more explicit about the types. There are
+several tricks to do that. For example:
+
+```cpp
+ACTION(Foo) {
+  // Makes sure arg0 can be converted to int.
+  int n = arg0;
+  ... use n instead of arg0 here ...
+}
+
+ACTION_P(Bar, param) {
+  // Makes sure the type of arg1 is const char*.
+  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
+
+  // Makes sure param can be converted to bool.
+  bool flag = param;
+}
+```
+
+where `StaticAssertTypeEq` is a compile-time assertion in googletest that
+verifies two types are the same.
+
+### Writing New Action Templates Quickly
+
+Sometimes you want to give an action explicit template parameters that cannot be
+inferred from its value parameters. `ACTION_TEMPLATE()` supports that and can be
+viewed as an extension to `ACTION()` and `ACTION_P*()`.
+
+The syntax:
+
+```cpp
+ACTION_TEMPLATE(ActionName,
+                HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+                AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+```
+
+defines an action template that takes *m* explicit template parameters and *n*
+value parameters, where *m* is in [1, 10] and *n* is in [0, 10]. `name_i` is the
+name of the *i*-th template parameter, and `kind_i` specifies whether it's a
+`typename`, an integral constant, or a template. `p_i` is the name of the *i*-th
+value parameter.
+
+Example:
+
+```cpp
+// DuplicateArg<k, T>(output) converts the k-th argument of the mock
+// function to type T and copies it to *output.
+ACTION_TEMPLATE(DuplicateArg,
+                // Note the comma between int and k:
+                HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+                AND_1_VALUE_PARAMS(output)) {
+  *output = T(std::get<k>(args));
+}
+```
+
+To create an instance of an action template, write:
+
+```cpp
+ActionName<t1, ..., t_m>(v1, ..., v_n)
+```
+
+where the `t`s are the template arguments and the `v`s are the value arguments.
+The value argument types are inferred by the compiler. For example:
+
+```cpp
+using ::testing::_;
+...
+  int n;
+  EXPECT_CALL(mock, Foo).WillOnce(DuplicateArg<1, unsigned char>(&n));
+```
+
+If you want to explicitly specify the value argument types, you can provide
+additional template arguments:
+
+```cpp
+ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+```
+
+where `u_i` is the desired type of `v_i`.
+
+`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the number of
+value parameters, but not on the number of template parameters. Without the
+restriction, the meaning of the following is unclear:
+
+```cpp
+  OverloadedAction<int, bool>(x);
+```
+
+Are we using a single-template-parameter action where `bool` refers to the type
+of `x`, or a two-template-parameter action where the compiler is asked to infer
+the type of `x`?
+
+### Using the ACTION Object's Type
+
+If you are writing a function that returns an `ACTION` object, you'll need to
+know its type. The type depends on the macro used to define the action and the
+parameter types. The rule is relatively simple:
+
+
+| Given Definition              | Expression          | Has Type              |
+| ----------------------------- | ------------------- | --------------------- |
+| `ACTION(Foo)`                 | `Foo()`             | `FooAction`           |
+| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` | `Foo<t1, ..., t_m>()` | `FooAction<t1, ..., t_m>` |
+| `ACTION_P(Bar, param)`        | `Bar(int_value)`    | `BarActionP<int>`     |
+| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar<t1, ..., t_m>(int_value)` | `BarActionP<t1, ..., t_m, int>` |
+| `ACTION_P2(Baz, p1, p2)`      | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
+| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))` | `Baz<t1, ..., t_m>(bool_value, int_value)` | `BazActionP2<t1, ..., t_m, bool, int>` |
+| ...                           | ...                 | ...                   |
+
+
+Note that we have to pick different suffixes (`Action`, `ActionP`, `ActionP2`,
+and etc) for actions with different numbers of value parameters, or the action
+definitions cannot be overloaded on the number of them.
+
+### Writing New Monomorphic Actions {#NewMonoActions}
+
+While the `ACTION*` macros are very convenient, sometimes they are
+inappropriate. For example, despite the tricks shown in the previous recipes,
+they don't let you directly specify the types of the mock function arguments and
+the action parameters, which in general leads to unoptimized compiler error
+messages that can baffle unfamiliar users. They also don't allow overloading
+actions based on parameter types without jumping through some hoops.
+
+An alternative to the `ACTION*` macros is to implement
+`::testing::ActionInterface<F>`, where `F` is the type of the mock function in
+which the action will be used. For example:
+
+```cpp
+template <typename F>
+class ActionInterface {
+ public:
+  virtual ~ActionInterface();
+
+  // Performs the action.  Result is the return type of function type
+  // F, and ArgumentTuple is the tuple of arguments of F.
+  //
+
+  // For example, if F is int(bool, const string&), then Result would
+  // be int, and ArgumentTuple would be std::tuple<bool, const string&>.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+};
+```
+
+```cpp
+using ::testing::_;
+using ::testing::Action;
+using ::testing::ActionInterface;
+using ::testing::MakeAction;
+
+typedef int IncrementMethod(int*);
+
+class IncrementArgumentAction : public ActionInterface<IncrementMethod> {
+ public:
+  int Perform(const std::tuple<int*>& args) override {
+    int* p = std::get<0>(args);  // Grabs the first argument.
+    return *p++;
+  }
+};
+
+Action<IncrementMethod> IncrementArgument() {
+  return MakeAction(new IncrementArgumentAction);
+}
+
+...
+  EXPECT_CALL(foo, Baz(_))
+      .WillOnce(IncrementArgument());
+
+  int n = 5;
+  foo.Baz(&n);  // Should return 5 and change n to 6.
+```
+
+### Writing New Polymorphic Actions {#NewPolyActions}
+
+The previous recipe showed you how to define your own action. This is all good,
+except that you need to know the type of the function in which the action will
+be used. Sometimes that can be a problem. For example, if you want to use the
+action in functions with *different* types (e.g. like `Return()` and
+`SetArgPointee()`).
+
+If an action can be used in several types of mock functions, we say it's
+*polymorphic*. The `MakePolymorphicAction()` function template makes it easy to
+define such an action:
+
+```cpp
+namespace testing {
+template <typename Impl>
+PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl);
+}  // namespace testing
+```
+
+As an example, let's define an action that returns the second argument in the
+mock function's argument list. The first step is to define an implementation
+class:
+
+```cpp
+class ReturnSecondArgumentAction {
+ public:
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    // To get the i-th (0-based) argument, use std::get(args).
+    return std::get<1>(args);
+  }
+};
+```
+
+This implementation class does *not* need to inherit from any particular class.
+What matters is that it must have a `Perform()` method template. This method
+template takes the mock function's arguments as a tuple in a **single**
+argument, and returns the result of the action. It can be either `const` or not,
+but must be invocable with exactly one template argument, which is the result
+type. In other words, you must be able to call `Perform<R>(args)` where `R` is
+the mock function's return type and `args` is its arguments in a tuple.
+
+Next, we use `MakePolymorphicAction()` to turn an instance of the implementation
+class into the polymorphic action we need. It will be convenient to have a
+wrapper for this:
+
+```cpp
+using ::testing::MakePolymorphicAction;
+using ::testing::PolymorphicAction;
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+```
+
+Now, you can use this polymorphic action the same way you use the built-in ones:
+
+```cpp
+using ::testing::_;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD(int, DoThis, (bool flag, int n), (override));
+  MOCK_METHOD(string, DoThat, (int x, const char* str1, const char* str2),
+              (override));
+};
+
+  ...
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis).WillOnce(ReturnSecondArgument());
+  EXPECT_CALL(foo, DoThat).WillOnce(ReturnSecondArgument());
+  ...
+  foo.DoThis(true, 5);  // Will return 5.
+  foo.DoThat(1, "Hi", "Bye");  // Will return "Hi".
+```
+
+### Teaching gMock How to Print Your Values
+
+When an uninteresting or unexpected call occurs, gMock prints the argument
+values and the stack trace to help you debug. Assertion macros like
+`EXPECT_THAT` and `EXPECT_EQ` also print the values in question when the
+assertion fails. gMock and googletest do this using googletest's user-extensible
+value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator. For other types, it
+prints the raw bytes in the value and hopes that you the user can figure it out.
+[The GoogleTest advanced guide](advanced.md#teaching-googletest-how-to-print-your-values)
+explains how to extend the printer to do a better job at printing your
+particular type than to dump the bytes.
+
+## Useful Mocks Created Using gMock
+
+<!--#include file="includes/g3_testing_LOGs.md"-->
+<!--#include file="includes/g3_mock_callbacks.md"-->
+
+### Mock std::function {#MockFunction}
+
+`std::function` is a general function type introduced in C++11. It is a
+preferred way of passing callbacks to new interfaces. Functions are copyable,
+and are not usually passed around by pointer, which makes them tricky to mock.
+But fear not - `MockFunction` can help you with that.
+
+`MockFunction<R(T1, ..., Tn)>` has a mock method `Call()` with the signature:
+
+```cpp
+  R Call(T1, ..., Tn);
+```
+
+It also has a `AsStdFunction()` method, which creates a `std::function` proxy
+forwarding to Call:
+
+```cpp
+  std::function<R(T1, ..., Tn)> AsStdFunction();
+```
+
+To use `MockFunction`, first create `MockFunction` object and set up
+expectations on its `Call` method. Then pass proxy obtained from
+`AsStdFunction()` to the code you are testing. For example:
+
+```cpp
+TEST(FooTest, RunsCallbackWithBarArgument) {
+  // 1. Create a mock object.
+  MockFunction<int(string)> mock_function;
+
+  // 2. Set expectations on Call() method.
+  EXPECT_CALL(mock_function, Call("bar")).WillOnce(Return(1));
+
+  // 3. Exercise code that uses std::function.
+  Foo(mock_function.AsStdFunction());
+  // Foo's signature can be either of:
+  // void Foo(const std::function<int(string)>& fun);
+  // void Foo(std::function<int(string)> fun);
+
+  // 4. All expectations will be verified when mock_function
+  //     goes out of scope and is destroyed.
+}
+```
+
+Remember that function objects created with `AsStdFunction()` are just
+forwarders. If you create multiple of them, they will share the same set of
+expectations.
+
+Although `std::function` supports unlimited number of arguments, `MockFunction`
+implementation is limited to ten. If you ever hit that limit... well, your
+callback has bigger problems than being mockable. :-)
diff --git a/3rd-party/googletest/docs/gmock_faq.md b/3rd-party/googletest/docs/gmock_faq.md
new file mode 100644
index 0000000..8f220bf
--- /dev/null
+++ b/3rd-party/googletest/docs/gmock_faq.md
@@ -0,0 +1,390 @@
+# Legacy gMock FAQ
+
+### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem?
+
+In order for a method to be mocked, it must be *virtual*, unless you use the
+[high-perf dependency injection technique](gmock_cook_book.md#MockingNonVirtualMethods).
+
+### Can I mock a variadic function?
+
+You cannot mock a variadic function (i.e. a function taking ellipsis (`...`)
+arguments) directly in gMock.
+
+The problem is that in general, there is *no way* for a mock object to know how
+many arguments are passed to the variadic method, and what the arguments' types
+are. Only the *author of the base class* knows the protocol, and we cannot look
+into his or her head.
+
+Therefore, to mock such a function, the *user* must teach the mock object how to
+figure out the number of arguments and their types. One way to do it is to
+provide overloaded versions of the function.
+
+Ellipsis arguments are inherited from C and not really a C++ feature. They are
+unsafe to use and don't work with arguments that have constructors or
+destructors. Therefore we recommend to avoid them in C++ as much as possible.
+
+### MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter. Why?
+
+If you compile this using Microsoft Visual C++ 2005 SP1:
+
+```cpp
+class Foo {
+  ...
+  virtual void Bar(const int i) = 0;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD(void, Bar, (const int i), (override));
+};
+```
+
+You may get the following warning:
+
+```shell
+warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier
+```
+
+This is a MSVC bug. The same code compiles fine with gcc, for example. If you
+use Visual C++ 2008 SP1, you would get the warning:
+
+```shell
+warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
+```
+
+In C++, if you *declare* a function with a `const` parameter, the `const`
+modifier is ignored. Therefore, the `Foo` base class above is equivalent to:
+
+```cpp
+class Foo {
+  ...
+  virtual void Bar(int i) = 0;  // int or const int?  Makes no difference.
+};
+```
+
+In fact, you can *declare* `Bar()` with an `int` parameter, and define it with a
+`const int` parameter. The compiler will still match them up.
+
+Since making a parameter `const` is meaningless in the method declaration, we
+recommend to remove it in both `Foo` and `MockFoo`. That should workaround the
+VC bug.
+
+Note that we are talking about the *top-level* `const` modifier here. If the
+function parameter is passed by pointer or reference, declaring the pointee or
+referee as `const` is still meaningful. For example, the following two
+declarations are *not* equivalent:
+
+```cpp
+void Bar(int* p);         // Neither p nor *p is const.
+void Bar(const int* p);  // p is not const, but *p is.
+```
+
+### I can't figure out why gMock thinks my expectations are not satisfied. What should I do?
+
+You might want to run your test with `--gmock_verbose=info`. This flag lets
+gMock print a trace of every mock function call it receives. By studying the
+trace, you'll gain insights on why the expectations you set are not met.
+
+If you see the message "The mock function has no default action set, and its
+return type has no default value set.", then try
+[adding a default action](gmock_cheat_sheet.md#OnCall). Due to a known issue,
+unexpected calls on mocks without default actions don't print out a detailed
+comparison between the actual arguments and the expected arguments.
+
+### My program crashed and `ScopedMockLog` spit out tons of messages. Is it a gMock bug?
+
+gMock and `ScopedMockLog` are likely doing the right thing here.
+
+When a test crashes, the failure signal handler will try to log a lot of
+information (the stack trace, and the address map, for example). The messages
+are compounded if you have many threads with depth stacks. When `ScopedMockLog`
+intercepts these messages and finds that they don't match any expectations, it
+prints an error for each of them.
+
+You can learn to ignore the errors, or you can rewrite your expectations to make
+your test more robust, for example, by adding something like:
+
+```cpp
+using ::testing::AnyNumber;
+using ::testing::Not;
+...
+  // Ignores any log not done by us.
+  EXPECT_CALL(log, Log(_, Not(EndsWith("/my_file.cc")), _))
+      .Times(AnyNumber());
+```
+
+### How can I assert that a function is NEVER called?
+
+```cpp
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .Times(0);
+```
+
+### I have a failed test where gMock tells me TWICE that a particular expectation is not satisfied. Isn't this redundant?
+
+When gMock detects a failure, it prints relevant information (the mock function
+arguments, the state of relevant expectations, and etc) to help the user debug.
+If another failure is detected, gMock will do the same, including printing the
+state of relevant expectations.
+
+Sometimes an expectation's state didn't change between two failures, and you'll
+see the same description of the state twice. They are however *not* redundant,
+as they refer to *different points in time*. The fact they are the same *is*
+interesting information.
+
+### I get a heapcheck failure when using a mock object, but using a real object is fine. What can be wrong?
+
+Does the class (hopefully a pure interface) you are mocking have a virtual
+destructor?
+
+Whenever you derive from a base class, make sure its destructor is virtual.
+Otherwise Bad Things will happen. Consider the following code:
+
+```cpp
+class Base {
+ public:
+  // Not virtual, but should be.
+  ~Base() { ... }
+  ...
+};
+
+class Derived : public Base {
+ public:
+  ...
+ private:
+  std::string value_;
+};
+
+...
+  Base* p = new Derived;
+  ...
+  delete p;  // Surprise! ~Base() will be called, but ~Derived() will not
+                 // - value_ is leaked.
+```
+
+By changing `~Base()` to virtual, `~Derived()` will be correctly called when
+`delete p` is executed, and the heap checker will be happy.
+
+### The "newer expectations override older ones" rule makes writing expectations awkward. Why does gMock do that?
+
+When people complain about this, often they are referring to code like:
+
+```cpp
+using ::testing::Return;
+...
+  // foo.Bar() should be called twice, return 1 the first time, and return
+  // 2 the second time.  However, I have to write the expectations in the
+  // reverse order.  This sucks big time!!!
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(2))
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(1))
+      .RetiresOnSaturation();
+```
+
+The problem, is that they didn't pick the **best** way to express the test's
+intent.
+
+By default, expectations don't have to be matched in *any* particular order. If
+you want them to match in a certain order, you need to be explicit. This is
+gMock's (and jMock's) fundamental philosophy: it's easy to accidentally
+over-specify your tests, and we want to make it harder to do so.
+
+There are two better ways to write the test spec. You could either put the
+expectations in sequence:
+
+```cpp
+using ::testing::Return;
+...
+  // foo.Bar() should be called twice, return 1 the first time, and return
+  // 2 the second time.  Using a sequence, we can write the expectations
+  // in their natural order.
+  {
+    InSequence s;
+    EXPECT_CALL(foo, Bar())
+        .WillOnce(Return(1))
+        .RetiresOnSaturation();
+    EXPECT_CALL(foo, Bar())
+        .WillOnce(Return(2))
+        .RetiresOnSaturation();
+  }
+```
+
+or you can put the sequence of actions in the same expectation:
+
+```cpp
+using ::testing::Return;
+...
+  // foo.Bar() should be called twice, return 1 the first time, and return
+  // 2 the second time.
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(1))
+      .WillOnce(Return(2))
+      .RetiresOnSaturation();
+```
+
+Back to the original questions: why does gMock search the expectations (and
+`ON_CALL`s) from back to front? Because this allows a user to set up a mock's
+behavior for the common case early (e.g. in the mock's constructor or the test
+fixture's set-up phase) and customize it with more specific rules later. If
+gMock searches from front to back, this very useful pattern won't be possible.
+
+### gMock prints a warning when a function without EXPECT_CALL is called, even if I have set its behavior using ON_CALL. Would it be reasonable not to show the warning in this case?
+
+When choosing between being neat and being safe, we lean toward the latter. So
+the answer is that we think it's better to show the warning.
+
+Often people write `ON_CALL`s in the mock object's constructor or `SetUp()`, as
+the default behavior rarely changes from test to test. Then in the test body
+they set the expectations, which are often different for each test. Having an
+`ON_CALL` in the set-up part of a test doesn't mean that the calls are expected.
+If there's no `EXPECT_CALL` and the method is called, it's possibly an error. If
+we quietly let the call go through without notifying the user, bugs may creep in
+unnoticed.
+
+If, however, you are sure that the calls are OK, you can write
+
+```cpp
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .WillRepeatedly(...);
+```
+
+instead of
+
+```cpp
+using ::testing::_;
+...
+  ON_CALL(foo, Bar(_))
+      .WillByDefault(...);
+```
+
+This tells gMock that you do expect the calls and no warning should be printed.
+
+Also, you can control the verbosity by specifying `--gmock_verbose=error`. Other
+values are `info` and `warning`. If you find the output too noisy when
+debugging, just choose a less verbose level.
+
+### How can I delete the mock function's argument in an action?
+
+If your mock function takes a pointer argument and you want to delete that
+argument, you can use testing::DeleteArg<N>() to delete the N'th (zero-indexed)
+argument:
+
+```cpp
+using ::testing::_;
+  ...
+  MOCK_METHOD(void, Bar, (X* x, const Y& y));
+  ...
+  EXPECT_CALL(mock_foo_, Bar(_, _))
+      .WillOnce(testing::DeleteArg<0>()));
+```
+
+### How can I perform an arbitrary action on a mock function's argument?
+
+If you find yourself needing to perform some action that's not supported by
+gMock directly, remember that you can define your own actions using
+[`MakeAction()`](#NewMonoActions) or
+[`MakePolymorphicAction()`](#NewPolyActions), or you can write a stub function
+and invoke it using [`Invoke()`](#FunctionsAsActions).
+
+```cpp
+using ::testing::_;
+using ::testing::Invoke;
+  ...
+  MOCK_METHOD(void, Bar, (X* p));
+  ...
+  EXPECT_CALL(mock_foo_, Bar(_))
+      .WillOnce(Invoke(MyAction(...)));
+```
+
+### My code calls a static/global function. Can I mock it?
+
+You can, but you need to make some changes.
+
+In general, if you find yourself needing to mock a static function, it's a sign
+that your modules are too tightly coupled (and less flexible, less reusable,
+less testable, etc). You are probably better off defining a small interface and
+call the function through that interface, which then can be easily mocked. It's
+a bit of work initially, but usually pays for itself quickly.
+
+This Google Testing Blog
+[post](https://testing.googleblog.com/2008/06/defeat-static-cling.html) says it
+excellently. Check it out.
+
+### My mock object needs to do complex stuff. It's a lot of pain to specify the actions. gMock sucks!
+
+I know it's not a question, but you get an answer for free any way. :-)
+
+With gMock, you can create mocks in C++ easily. And people might be tempted to
+use them everywhere. Sometimes they work great, and sometimes you may find them,
+well, a pain to use. So, what's wrong in the latter case?
+
+When you write a test without using mocks, you exercise the code and assert that
+it returns the correct value or that the system is in an expected state. This is
+sometimes called "state-based testing".
+
+Mocks are great for what some call "interaction-based" testing: instead of
+checking the system state at the very end, mock objects verify that they are
+invoked the right way and report an error as soon as it arises, giving you a
+handle on the precise context in which the error was triggered. This is often
+more effective and economical to do than state-based testing.
+
+If you are doing state-based testing and using a test double just to simulate
+the real object, you are probably better off using a fake. Using a mock in this
+case causes pain, as it's not a strong point for mocks to perform complex
+actions. If you experience this and think that mocks suck, you are just not
+using the right tool for your problem. Or, you might be trying to solve the
+wrong problem. :-)
+
+### I got a warning "Uninteresting function call encountered - default action taken.." Should I panic?
+
+By all means, NO! It's just an FYI. :-)
+
+What it means is that you have a mock function, you haven't set any expectations
+on it (by gMock's rule this means that you are not interested in calls to this
+function and therefore it can be called any number of times), and it is called.
+That's OK - you didn't say it's not OK to call the function!
+
+What if you actually meant to disallow this function to be called, but forgot to
+write `EXPECT_CALL(foo, Bar()).Times(0)`? While one can argue that it's the
+user's fault, gMock tries to be nice and prints you a note.
+
+So, when you see the message and believe that there shouldn't be any
+uninteresting calls, you should investigate what's going on. To make your life
+easier, gMock dumps the stack trace when an uninteresting call is encountered.
+From that you can figure out which mock function it is, and how it is called.
+
+### I want to define a custom action. Should I use Invoke() or implement the ActionInterface interface?
+
+Either way is fine - you want to choose the one that's more convenient for your
+circumstance.
+
+Usually, if your action is for a particular function type, defining it using
+`Invoke()` should be easier; if your action can be used in functions of
+different types (e.g. if you are defining `Return(*value*)`),
+`MakePolymorphicAction()` is easiest. Sometimes you want precise control on what
+types of functions the action can be used in, and implementing `ActionInterface`
+is the way to go here. See the implementation of `Return()` in `gmock-actions.h`
+for an example.
+
+### I use SetArgPointee() in WillOnce(), but gcc complains about "conflicting return type specified". What does it mean?
+
+You got this error as gMock has no idea what value it should return when the
+mock method is called. `SetArgPointee()` says what the side effect is, but
+doesn't say what the return value should be. You need `DoAll()` to chain a
+`SetArgPointee()` with a `Return()` that provides a value appropriate to the API
+being mocked.
+
+See this [recipe](gmock_cook_book.md#mocking-side-effects) for more details and
+an example.
+
+### I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it. What can I do?
+
+We've noticed that when the `/clr` compiler flag is used, Visual C++ uses 5~6
+times as much memory when compiling a mock class. We suggest to avoid `/clr`
+when compiling native C++ mocks.
diff --git a/3rd-party/googletest/docs/gmock_for_dummies.md b/3rd-party/googletest/docs/gmock_for_dummies.md
new file mode 100644
index 0000000..ed2297c
--- /dev/null
+++ b/3rd-party/googletest/docs/gmock_for_dummies.md
@@ -0,0 +1,702 @@
+# gMock for Dummies
+
+## What Is gMock?
+
+When you write a prototype or test, often it's not feasible or wise to rely on
+real objects entirely. A **mock object** implements the same interface as a real
+object (so it can be used as one), but lets you specify at run time how it will
+be used and what it should do (which methods will be called? in which order? how
+many times? with what arguments? what will they return? etc).
+
+It is easy to confuse the term *fake objects* with mock objects. Fakes and mocks
+actually mean very different things in the Test-Driven Development (TDD)
+community:
+
+*   **Fake** objects have working implementations, but usually take some
+    shortcut (perhaps to make the operations less expensive), which makes them
+    not suitable for production. An in-memory file system would be an example of
+    a fake.
+*   **Mocks** are objects pre-programmed with *expectations*, which form a
+    specification of the calls they are expected to receive.
+
+If all this seems too abstract for you, don't worry - the most important thing
+to remember is that a mock allows you to check the *interaction* between itself
+and code that uses it. The difference between fakes and mocks shall become much
+clearer once you start to use mocks.
+
+**gMock** is a library (sometimes we also call it a "framework" to make it sound
+cool) for creating mock classes and using them. It does to C++ what
+jMock/EasyMock does to Java (well, more or less).
+
+When using gMock,
+
+1.  first, you use some simple macros to describe the interface you want to
+    mock, and they will expand to the implementation of your mock class;
+2.  next, you create some mock objects and specify its expectations and behavior
+    using an intuitive syntax;
+3.  then you exercise code that uses the mock objects. gMock will catch any
+    violation to the expectations as soon as it arises.
+
+## Why gMock?
+
+While mock objects help you remove unnecessary dependencies in tests and make
+them fast and reliable, using mocks manually in C++ is *hard*:
+
+*   Someone has to implement the mocks. The job is usually tedious and
+    error-prone. No wonder people go great distance to avoid it.
+*   The quality of those manually written mocks is a bit, uh, unpredictable. You
+    may see some really polished ones, but you may also see some that were
+    hacked up in a hurry and have all sorts of ad hoc restrictions.
+*   The knowledge you gained from using one mock doesn't transfer to the next
+    one.
+
+In contrast, Java and Python programmers have some fine mock frameworks (jMock,
+EasyMock, etc), which automate the creation of mocks. As a result, mocking is a
+proven effective technique and widely adopted practice in those communities.
+Having the right tool absolutely makes the difference.
+
+gMock was built to help C++ programmers. It was inspired by jMock and EasyMock,
+but designed with C++'s specifics in mind. It is your friend if any of the
+following problems is bothering you:
+
+*   You are stuck with a sub-optimal design and wish you had done more
+    prototyping before it was too late, but prototyping in C++ is by no means
+    "rapid".
+*   Your tests are slow as they depend on too many libraries or use expensive
+    resources (e.g. a database).
+*   Your tests are brittle as some resources they use are unreliable (e.g. the
+    network).
+*   You want to test how your code handles a failure (e.g. a file checksum
+    error), but it's not easy to cause one.
+*   You need to make sure that your module interacts with other modules in the
+    right way, but it's hard to observe the interaction; therefore you resort to
+    observing the side effects at the end of the action, but it's awkward at
+    best.
+*   You want to "mock out" your dependencies, except that they don't have mock
+    implementations yet; and, frankly, you aren't thrilled by some of those
+    hand-written mocks.
+
+We encourage you to use gMock as
+
+*   a *design* tool, for it lets you experiment with your interface design early
+    and often. More iterations lead to better designs!
+*   a *testing* tool to cut your tests' outbound dependencies and probe the
+    interaction between your module and its collaborators.
+
+## Getting Started
+
+gMock is bundled with googletest.
+
+## A Case for Mock Turtles
+
+Let's look at an example. Suppose you are developing a graphics program that
+relies on a [LOGO](https://en.wikipedia.org/wiki/Logo_programming_language)-like
+API for drawing. How would you test that it does the right thing? Well, you can
+run it and compare the screen with a golden screen snapshot, but let's admit it:
+tests like this are expensive to run and fragile (What if you just upgraded to a
+shiny new graphics card that has better anti-aliasing? Suddenly you have to
+update all your golden images.). It would be too painful if all your tests are
+like this. Fortunately, you learned about
+[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) and know the right thing
+to do: instead of having your application talk to the system API directly, wrap
+the API in an interface (say, `Turtle`) and code to that interface:
+
+```cpp
+class Turtle {
+  ...
+  virtual ~Turtle() {}
+  virtual void PenUp() = 0;
+  virtual void PenDown() = 0;
+  virtual void Forward(int distance) = 0;
+  virtual void Turn(int degrees) = 0;
+  virtual void GoTo(int x, int y) = 0;
+  virtual int GetX() const = 0;
+  virtual int GetY() const = 0;
+};
+```
+
+(Note that the destructor of `Turtle` **must** be virtual, as is the case for
+**all** classes you intend to inherit from - otherwise the destructor of the
+derived class will not be called when you delete an object through a base
+pointer, and you'll get corrupted program states like memory leaks.)
+
+You can control whether the turtle's movement will leave a trace using `PenUp()`
+and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and
+`GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the
+turtle.
+
+Your program will normally use a real implementation of this interface. In
+tests, you can use a mock implementation instead. This allows you to easily
+check what drawing primitives your program is calling, with what arguments, and
+in which order. Tests written this way are much more robust (they won't break
+because your new machine does anti-aliasing differently), easier to read and
+maintain (the intent of a test is expressed in the code, not in some binary
+images), and run *much, much faster*.
+
+## Writing the Mock Class
+
+If you are lucky, the mocks you need to use have already been implemented by
+some nice people. If, however, you find yourself in the position to write a mock
+class, relax - gMock turns this task into a fun game! (Well, almost.)
+
+### How to Define It
+
+Using the `Turtle` interface as example, here are the simple steps you need to
+follow:
+
+*   Derive a class `MockTurtle` from `Turtle`.
+*   Take a *virtual* function of `Turtle` (while it's possible to
+    [mock non-virtual methods using templates](gmock_cook_book.md#MockingNonVirtualMethods),
+    it's much more involved).
+*   In the `public:` section of the child class, write `MOCK_METHOD();`
+*   Now comes the fun part: you take the function signature, cut-and-paste it
+    into the macro, and add two commas - one between the return type and the
+    name, another between the name and the argument list.
+*   If you're mocking a const method, add a 4th parameter containing `(const)`
+    (the parentheses are required).
+*   Since you're overriding a virtual method, we suggest adding the `override`
+    keyword. For const methods the 4th parameter becomes `(const, override)`,
+    for non-const methods just `(override)`. This isn't mandatory.
+*   Repeat until all virtual functions you want to mock are done. (It goes
+    without saying that *all* pure virtual methods in your abstract class must
+    be either mocked or overridden.)
+
+After the process, you should have something like:
+
+```cpp
+#include <gmock/gmock.h>  // Brings in gMock.
+
+class MockTurtle : public Turtle {
+ public:
+  ...
+  MOCK_METHOD(void, PenUp, (), (override));
+  MOCK_METHOD(void, PenDown, (), (override));
+  MOCK_METHOD(void, Forward, (int distance), (override));
+  MOCK_METHOD(void, Turn, (int degrees), (override));
+  MOCK_METHOD(void, GoTo, (int x, int y), (override));
+  MOCK_METHOD(int, GetX, (), (const, override));
+  MOCK_METHOD(int, GetY, (), (const, override));
+};
+```
+
+You don't need to define these mock methods somewhere else - the `MOCK_METHOD`
+macro will generate the definitions for you. It's that simple!
+
+### Where to Put It
+
+When you define a mock class, you need to decide where to put its definition.
+Some people put it in a `_test.cc`. This is fine when the interface being mocked
+(say, `Foo`) is owned by the same person or team. Otherwise, when the owner of
+`Foo` changes it, your test could break. (You can't really expect `Foo`'s
+maintainer to fix every test that uses `Foo`, can you?)
+
+Generally, you should not mock classes you don't own. If you must mock such a
+class owned by others, define the mock class in `Foo`'s Bazel package (usually
+the same directory or a `testing` sub-directory), and put it in a `.h` and a
+`cc_library` with `testonly=True`. Then everyone can reference them from their
+tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and
+only tests that depend on the changed methods need to be fixed.
+
+Another way to do it: you can introduce a thin layer `FooAdaptor` on top of
+`Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb
+changes in `Foo` much more easily. While this is more work initially, carefully
+choosing the adaptor interface can make your code easier to write and more
+readable (a net win in the long run), as you can choose `FooAdaptor` to fit your
+specific domain much better than `Foo` does.
+
+## Using Mocks in Tests
+
+Once you have a mock class, using it is easy. The typical work flow is:
+
+1.  Import the gMock names from the `testing` namespace such that you can use
+    them unqualified (You only have to do it once per file). Remember that
+    namespaces are a good idea.
+2.  Create some mock objects.
+3.  Specify your expectations on them (How many times will a method be called?
+    With what arguments? What should it do? etc.).
+4.  Exercise some code that uses the mocks; optionally, check the result using
+    googletest assertions. If a mock method is called more than expected or with
+    wrong arguments, you'll get an error immediately.
+5.  When a mock is destructed, gMock will automatically check whether all
+    expectations on it have been satisfied.
+
+Here's an example:
+
+```cpp
+#include "path/to/mock-turtle.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::AtLeast;                         // #1
+
+TEST(PainterTest, CanDrawSomething) {
+  MockTurtle turtle;                              // #2
+  EXPECT_CALL(turtle, PenDown())                  // #3
+      .Times(AtLeast(1));
+
+  Painter painter(&turtle);                       // #4
+
+  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));      // #5
+}
+```
+
+As you might have guessed, this test checks that `PenDown()` is called at least
+once. If the `painter` object didn't call this method, your test will fail with
+a message like this:
+
+```text
+path/to/my_test.cc:119: Failure
+Actual function call count doesn't match this expectation:
+Actually: never called;
+Expected: called at least once.
+Stack trace:
+...
+```
+
+**Tip 1:** If you run the test from an Emacs buffer, you can hit `<Enter>` on
+the line number to jump right to the failed expectation.
+
+**Tip 2:** If your mock objects are never deleted, the final verification won't
+happen. Therefore it's a good idea to turn on the heap checker in your tests
+when you allocate mocks on the heap. You get that automatically if you use the
+`gtest_main` library already.
+
+###### Expectation Ordering
+
+**Important note:** gMock requires expectations to be set **before** the mock
+functions are called, otherwise the behavior is **undefined**. Do not alternate
+between calls to `EXPECT_CALL()` and calls to the mock functions, and do not set
+any expectations on a mock after passing the mock to an API.
+
+This means `EXPECT_CALL()` should be read as expecting that a call will occur
+*in the future*, not that a call has occurred. Why does gMock work like that?
+Well, specifying the expectation beforehand allows gMock to report a violation
+as soon as it rises, when the context (stack trace, etc) is still available.
+This makes debugging much easier.
+
+Admittedly, this test is contrived and doesn't do much. You can easily achieve
+the same effect without using gMock. However, as we shall reveal soon, gMock
+allows you to do *so much more* with the mocks.
+
+## Setting Expectations
+
+The key to using a mock object successfully is to set the *right expectations*
+on it. If you set the expectations too strict, your test will fail as the result
+of unrelated changes. If you set them too loose, bugs can slip through. You want
+to do it just right such that your test can catch exactly the kind of bugs you
+intend it to catch. gMock provides the necessary means for you to do it "just
+right."
+
+### General Syntax
+
+In gMock we use the `EXPECT_CALL()` macro to set an expectation on a mock
+method. The general syntax is:
+
+```cpp
+EXPECT_CALL(mock_object, method(matchers))
+    .Times(cardinality)
+    .WillOnce(action)
+    .WillRepeatedly(action);
+```
+
+The macro has two arguments: first the mock object, and then the method and its
+arguments. Note that the two are separated by a comma (`,`), not a period (`.`).
+(Why using a comma? The answer is that it was necessary for technical reasons.)
+If the method is not overloaded, the macro can also be called without matchers:
+
+```cpp
+EXPECT_CALL(mock_object, non-overloaded-method)
+    .Times(cardinality)
+    .WillOnce(action)
+    .WillRepeatedly(action);
+```
+
+This syntax allows the test writer to specify "called with any arguments"
+without explicitly specifying the number or types of arguments. To avoid
+unintended ambiguity, this syntax may only be used for methods that are not
+overloaded.
+
+Either form of the macro can be followed by some optional *clauses* that provide
+more information about the expectation. We'll discuss how each clause works in
+the coming sections.
+
+This syntax is designed to make an expectation read like English. For example,
+you can probably guess that
+
+```cpp
+using ::testing::Return;
+...
+EXPECT_CALL(turtle, GetX())
+    .Times(5)
+    .WillOnce(Return(100))
+    .WillOnce(Return(150))
+    .WillRepeatedly(Return(200));
+```
+
+says that the `turtle` object's `GetX()` method will be called five times, it
+will return 100 the first time, 150 the second time, and then 200 every time.
+Some people like to call this style of syntax a Domain-Specific Language (DSL).
+
+{: .callout .note}
+**Note:** Why do we use a macro to do this? Well it serves two purposes: first
+it makes expectations easily identifiable (either by `grep` or by a human
+reader), and second it allows gMock to include the source file location of a
+failed expectation in messages, making debugging easier.
+
+### Matchers: What Arguments Do We Expect?
+
+When a mock function takes arguments, we may specify what arguments we are
+expecting, for example:
+
+```cpp
+// Expects the turtle to move forward by 100 units.
+EXPECT_CALL(turtle, Forward(100));
+```
+
+Oftentimes you do not want to be too specific. Remember that talk about tests
+being too rigid? Over specification leads to brittle tests and obscures the
+intent of tests. Therefore we encourage you to specify only what's necessary—no
+more, no less. If you aren't interested in the value of an argument, write `_`
+as the argument, which means "anything goes":
+
+```cpp
+using ::testing::_;
+...
+// Expects that the turtle jumps to somewhere on the x=50 line.
+EXPECT_CALL(turtle, GoTo(50, _));
+```
+
+`_` is an instance of what we call **matchers**. A matcher is like a predicate
+and can test whether an argument is what we'd expect. You can use a matcher
+inside `EXPECT_CALL()` wherever a function argument is expected. `_` is a
+convenient way of saying "any value".
+
+In the above examples, `100` and `50` are also matchers; implicitly, they are
+the same as `Eq(100)` and `Eq(50)`, which specify that the argument must be
+equal (using `operator==`) to the matcher argument. There are many
+[built-in matchers](reference/matchers.md) for common types (as well as
+[custom matchers](gmock_cook_book.md#NewMatchers)); for example:
+
+```cpp
+using ::testing::Ge;
+...
+// Expects the turtle moves forward by at least 100.
+EXPECT_CALL(turtle, Forward(Ge(100)));
+```
+
+If you don't care about *any* arguments, rather than specify `_` for each of
+them you may instead omit the parameter list:
+
+```cpp
+// Expects the turtle to move forward.
+EXPECT_CALL(turtle, Forward);
+// Expects the turtle to jump somewhere.
+EXPECT_CALL(turtle, GoTo);
+```
+
+This works for all non-overloaded methods; if a method is overloaded, you need
+to help gMock resolve which overload is expected by specifying the number of
+arguments and possibly also the
+[types of the arguments](gmock_cook_book.md#SelectOverload).
+
+### Cardinalities: How Many Times Will It Be Called?
+
+The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We
+call its argument a **cardinality** as it tells *how many times* the call should
+occur. It allows us to repeat an expectation many times without actually writing
+it as many times. More importantly, a cardinality can be "fuzzy", just like a
+matcher can be. This allows a user to express the intent of a test exactly.
+
+An interesting special case is when we say `Times(0)`. You may have guessed - it
+means that the function shouldn't be called with the given arguments at all, and
+gMock will report a googletest failure whenever the function is (wrongfully)
+called.
+
+We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the
+list of built-in cardinalities you can use, see
+[here](gmock_cheat_sheet.md#CardinalityList).
+
+The `Times()` clause can be omitted. **If you omit `Times()`, gMock will infer
+the cardinality for you.** The rules are easy to remember:
+
+*   If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the
+    `EXPECT_CALL()`, the inferred cardinality is `Times(1)`.
+*   If there are *n* `WillOnce()`'s but **no** `WillRepeatedly()`, where *n* >=
+    1, the cardinality is `Times(n)`.
+*   If there are *n* `WillOnce()`'s and **one** `WillRepeatedly()`, where *n* >=
+    0, the cardinality is `Times(AtLeast(n))`.
+
+**Quick quiz:** what do you think will happen if a function is expected to be
+called twice but actually called four times?
+
+### Actions: What Should It Do?
+
+Remember that a mock object doesn't really have a working implementation? We as
+users have to tell it what to do when a method is invoked. This is easy in
+gMock.
+
+First, if the return type of a mock function is a built-in type or a pointer,
+the function has a **default action** (a `void` function will just return, a
+`bool` function will return `false`, and other functions will return 0). In
+addition, in C++ 11 and above, a mock function whose return type is
+default-constructible (i.e. has a default constructor) has a default action of
+returning a default-constructed value. If you don't say anything, this behavior
+will be used.
+
+Second, if a mock function doesn't have a default action, or the default action
+doesn't suit you, you can specify the action to be taken each time the
+expectation matches using a series of `WillOnce()` clauses followed by an
+optional `WillRepeatedly()`. For example,
+
+```cpp
+using ::testing::Return;
+...
+EXPECT_CALL(turtle, GetX())
+     .WillOnce(Return(100))
+     .WillOnce(Return(200))
+     .WillOnce(Return(300));
+```
+
+says that `turtle.GetX()` will be called *exactly three times* (gMock inferred
+this from how many `WillOnce()` clauses we've written, since we didn't
+explicitly write `Times()`), and will return 100, 200, and 300 respectively.
+
+```cpp
+using ::testing::Return;
+...
+EXPECT_CALL(turtle, GetY())
+     .WillOnce(Return(100))
+     .WillOnce(Return(200))
+     .WillRepeatedly(Return(300));
+```
+
+says that `turtle.GetY()` will be called *at least twice* (gMock knows this as
+we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no
+explicit `Times()`), will return 100 and 200 respectively the first two times,
+and 300 from the third time on.
+
+Of course, if you explicitly write a `Times()`, gMock will not try to infer the
+cardinality itself. What if the number you specified is larger than there are
+`WillOnce()` clauses? Well, after all `WillOnce()`s are used up, gMock will do
+the *default* action for the function every time (unless, of course, you have a
+`WillRepeatedly()`.).
+
+What can we do inside `WillOnce()` besides `Return()`? You can return a
+reference using `ReturnRef(`*`variable`*`)`, or invoke a pre-defined function,
+among [others](gmock_cook_book.md#using-actions).
+
+**Important note:** The `EXPECT_CALL()` statement evaluates the action clause
+only once, even though the action may be performed many times. Therefore you
+must be careful about side effects. The following may not do what you want:
+
+```cpp
+using ::testing::Return;
+...
+int n = 100;
+EXPECT_CALL(turtle, GetX())
+    .Times(4)
+    .WillRepeatedly(Return(n++));
+```
+
+Instead of returning 100, 101, 102, ..., consecutively, this mock function will
+always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)`
+will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will
+return the same pointer every time. If you want the side effect to happen every
+time, you need to define a custom action, which we'll teach in the
+[cook book](gmock_cook_book.md).
+
+Time for another quiz! What do you think the following means?
+
+```cpp
+using ::testing::Return;
+...
+EXPECT_CALL(turtle, GetY())
+    .Times(4)
+    .WillOnce(Return(100));
+```
+
+Obviously `turtle.GetY()` is expected to be called four times. But if you think
+it will return 100 every time, think twice! Remember that one `WillOnce()`
+clause will be consumed each time the function is invoked and the default action
+will be taken afterwards. So the right answer is that `turtle.GetY()` will
+return 100 the first time, but **return 0 from the second time on**, as
+returning 0 is the default action for `int` functions.
+
+### Using Multiple Expectations {#MultiExpectations}
+
+So far we've only shown examples where you have a single expectation. More
+realistically, you'll specify expectations on multiple mock methods which may be
+from multiple mock objects.
+
+By default, when a mock method is invoked, gMock will search the expectations in
+the **reverse order** they are defined, and stop when an active expectation that
+matches the arguments is found (you can think of it as "newer rules override
+older ones."). If the matching expectation cannot take any more calls, you will
+get an upper-bound-violated failure. Here's an example:
+
+```cpp
+using ::testing::_;
+...
+EXPECT_CALL(turtle, Forward(_));  // #1
+EXPECT_CALL(turtle, Forward(10))  // #2
+    .Times(2);
+```
+
+If `Forward(10)` is called three times in a row, the third time it will be an
+error, as the last matching expectation (#2) has been saturated. If, however,
+the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK,
+as now #1 will be the matching expectation.
+
+{: .callout .note}
+**Note:** Why does gMock search for a match in the *reverse* order of the
+expectations? The reason is that this allows a user to set up the default
+expectations in a mock object's constructor or the test fixture's set-up phase
+and then customize the mock by writing more specific expectations in the test
+body. So, if you have two expectations on the same method, you want to put the
+one with more specific matchers **after** the other, or the more specific rule
+would be shadowed by the more general one that comes after it.
+
+{: .callout .tip}
+**Tip:** It is very common to start with a catch-all expectation for a method
+and `Times(AnyNumber())` (omitting arguments, or with `_` for all arguments, if
+overloaded). This makes any calls to the method expected. This is not necessary
+for methods that are not mentioned at all (these are "uninteresting"), but is
+useful for methods that have some expectations, but for which other calls are
+ok. See
+[Understanding Uninteresting vs Unexpected Calls](gmock_cook_book.md#uninteresting-vs-unexpected).
+
+### Ordered vs Unordered Calls {#OrderedCalls}
+
+By default, an expectation can match a call even though an earlier expectation
+hasn't been satisfied. In other words, the calls don't have to occur in the
+order the expectations are specified.
+
+Sometimes, you may want all the expected calls to occur in a strict order. To
+say this in gMock is easy:
+
+```cpp
+using ::testing::InSequence;
+...
+TEST(FooTest, DrawsLineSegment) {
+  ...
+  {
+    InSequence seq;
+
+    EXPECT_CALL(turtle, PenDown());
+    EXPECT_CALL(turtle, Forward(100));
+    EXPECT_CALL(turtle, PenUp());
+  }
+  Foo();
+}
+```
+
+By creating an object of type `InSequence`, all expectations in its scope are
+put into a *sequence* and have to occur *sequentially*. Since we are just
+relying on the constructor and destructor of this object to do the actual work,
+its name is really irrelevant.
+
+In this example, we test that `Foo()` calls the three expected functions in the
+order as written. If a call is made out-of-order, it will be an error.
+
+(What if you care about the relative order of some of the calls, but not all of
+them? Can you specify an arbitrary partial order? The answer is ... yes! The
+details can be found [here](gmock_cook_book.md#OrderedCalls).)
+
+### All Expectations Are Sticky (Unless Said Otherwise) {#StickyExpectations}
+
+Now let's do a quick quiz to see how well you can use this mock stuff already.
+How would you test that the turtle is asked to go to the origin *exactly twice*
+(you want to ignore any other instructions it receives)?
+
+After you've come up with your answer, take a look at ours and compare notes
+(solve it yourself first - don't cheat!):
+
+```cpp
+using ::testing::_;
+using ::testing::AnyNumber;
+...
+EXPECT_CALL(turtle, GoTo(_, _))  // #1
+     .Times(AnyNumber());
+EXPECT_CALL(turtle, GoTo(0, 0))  // #2
+     .Times(2);
+```
+
+Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, gMock will
+see that the arguments match expectation #2 (remember that we always pick the
+last matching expectation). Now, since we said that there should be only two
+such calls, gMock will report an error immediately. This is basically what we've
+told you in the [Using Multiple Expectations](#MultiExpectations) section above.
+
+This example shows that **expectations in gMock are "sticky" by default**, in
+the sense that they remain active even after we have reached their invocation
+upper bounds. This is an important rule to remember, as it affects the meaning
+of the spec, and is **different** to how it's done in many other mocking
+frameworks (Why'd we do that? Because we think our rule makes the common cases
+easier to express and understand.).
+
+Simple? Let's see if you've really understood it: what does the following code
+say?
+
+```cpp
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+      .WillOnce(Return(10*i));
+}
+```
+
+If you think it says that `turtle.GetX()` will be called `n` times and will
+return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we
+said, expectations are sticky. So, the second time `turtle.GetX()` is called,
+the last (latest) `EXPECT_CALL()` statement will match, and will immediately
+lead to an "upper bound violated" error - this piece of code is not very useful!
+
+One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is
+to explicitly say that the expectations are *not* sticky. In other words, they
+should *retire* as soon as they are saturated:
+
+```cpp
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+      .WillOnce(Return(10*i))
+      .RetiresOnSaturation();
+}
+```
+
+And, there's a better way to do it: in this case, we expect the calls to occur
+in a specific order, and we line up the actions to match the order. Since the
+order is important here, we should make it explicit using a sequence:
+
+```cpp
+using ::testing::InSequence;
+using ::testing::Return;
+...
+{
+  InSequence s;
+
+  for (int i = 1; i <= n; i++) {
+    EXPECT_CALL(turtle, GetX())
+        .WillOnce(Return(10*i))
+        .RetiresOnSaturation();
+  }
+}
+```
+
+By the way, the other situation where an expectation may *not* be sticky is when
+it's in a sequence - as soon as another expectation that comes after it in the
+sequence has been used, it automatically retires (and will never be used to
+match any call).
+
+### Uninteresting Calls
+
+A mock object may have many methods, and not all of them are that interesting.
+For example, in some tests we may not care about how many times `GetX()` and
+`GetY()` get called.
+
+In gMock, if you are not interested in a method, just don't say anything about
+it. If a call to this method occurs, you'll see a warning in the test output,
+but it won't be a failure. This is called "naggy" behavior; to change, see
+[The Nice, the Strict, and the Naggy](gmock_cook_book.md#NiceStrictNaggy).
diff --git a/3rd-party/googletest/docs/index.md b/3rd-party/googletest/docs/index.md
new file mode 100644
index 0000000..b162c74
--- /dev/null
+++ b/3rd-party/googletest/docs/index.md
@@ -0,0 +1,22 @@
+# GoogleTest User's Guide
+
+## Welcome to GoogleTest!
+
+GoogleTest is Google's C++ testing and mocking framework. This user's guide has
+the following contents:
+
+*   [GoogleTest Primer](primer.md) - Teaches you how to write simple tests using
+    GoogleTest. Read this first if you are new to GoogleTest.
+*   [GoogleTest Advanced](advanced.md) - Read this when you've finished the
+    Primer and want to utilize GoogleTest to its full potential.
+*   [GoogleTest Samples](samples.md) - Describes some GoogleTest samples.
+*   [GoogleTest FAQ](faq.md) - Have a question? Want some tips? Check here
+    first.
+*   [Mocking for Dummies](gmock_for_dummies.md) - Teaches you how to create mock
+    objects and use them in tests.
+*   [Mocking Cookbook](gmock_cook_book.md) - Includes tips and approaches to
+    common mocking use cases.
+*   [Mocking Cheat Sheet](gmock_cheat_sheet.md) - A handy reference for
+    matchers, actions, invariants, and more.
+*   [Mocking FAQ](gmock_faq.md) - Contains answers to some mocking-specific
+    questions.
diff --git a/3rd-party/googletest/docs/pkgconfig.md b/3rd-party/googletest/docs/pkgconfig.md
new file mode 100644
index 0000000..bf05d59
--- /dev/null
+++ b/3rd-party/googletest/docs/pkgconfig.md
@@ -0,0 +1,144 @@
+## Using GoogleTest from various build systems
+
+GoogleTest comes with pkg-config files that can be used to determine all
+necessary flags for compiling and linking to GoogleTest (and GoogleMock).
+Pkg-config is a standardised plain-text format containing
+
+*   the includedir (-I) path
+*   necessary macro (-D) definitions
+*   further required flags (-pthread)
+*   the library (-L) path
+*   the library (-l) to link to
+
+All current build systems support pkg-config in one way or another. For all
+examples here we assume you want to compile the sample
+`samples/sample3_unittest.cc`.
+
+### CMake
+
+Using `pkg-config` in CMake is fairly easy:
+
+```cmake
+find_package(PkgConfig)
+pkg_search_module(GTEST REQUIRED gtest_main)
+
+add_executable(testapp)
+target_sources(testapp PRIVATE samples/sample3_unittest.cc)
+target_link_libraries(testapp PRIVATE ${GTEST_LDFLAGS})
+target_compile_options(testapp PRIVATE ${GTEST_CFLAGS})
+
+enable_testing()
+add_test(first_and_only_test testapp)
+```
+
+It is generally recommended that you use `target_compile_options` + `_CFLAGS`
+over `target_include_directories` + `_INCLUDE_DIRS` as the former includes not
+just -I flags (GoogleTest might require a macro indicating to internal headers
+that all libraries have been compiled with threading enabled. In addition,
+GoogleTest might also require `-pthread` in the compiling step, and as such
+splitting the pkg-config `Cflags` variable into include dirs and macros for
+`target_compile_definitions()` might still miss this). The same recommendation
+goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens
+to discard `-L` flags and `-pthread`.
+
+### Help! pkg-config can't find GoogleTest!
+
+Let's say you have a `CMakeLists.txt` along the lines of the one in this
+tutorial and you try to run `cmake`. It is very possible that you get a failure
+along the lines of:
+
+```
+-- Checking for one of the modules 'gtest_main'
+CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
+  None of the required 'gtest_main' found
+```
+
+These failures are common if you installed GoogleTest yourself and have not
+sourced it from a distro or other package manager. If so, you need to tell
+pkg-config where it can find the `.pc` files containing the information. Say you
+installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are
+installed under `/usr/local/lib64/pkgconfig`. If you set
+
+```
+export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
+```
+
+pkg-config will also try to look in `PKG_CONFIG_PATH` to find `gtest_main.pc`.
+
+### Using pkg-config in a cross-compilation setting
+
+Pkg-config can be used in a cross-compilation setting too. To do this, let's
+assume the final prefix of the cross-compiled installation will be `/usr`, and
+your sysroot is `/home/MYUSER/sysroot`. Configure and install GTest using
+
+```
+mkdir build && cmake -DCMAKE_INSTALL_PREFIX=/usr ..
+```
+
+Install into the sysroot using `DESTDIR`:
+
+```
+make -j install DESTDIR=/home/MYUSER/sysroot
+```
+
+Before we continue, it is recommended to **always** define the following two
+variables for pkg-config in a cross-compilation setting:
+
+```
+export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=yes
+export PKG_CONFIG_ALLOW_SYSTEM_LIBS=yes
+```
+
+otherwise `pkg-config` will filter `-I` and `-L` flags against standard prefixes
+such as `/usr` (see https://bugs.freedesktop.org/show_bug.cgi?id=28264#c3 for
+reasons why this stripping needs to occur usually).
+
+If you look at the generated pkg-config file, it will look something like
+
+```
+libdir=/usr/lib64
+includedir=/usr/include
+
+Name: gtest
+Description: GoogleTest (without main() function)
+Version: 1.11.0
+URL: https://github.com/google/googletest
+Libs: -L${libdir} -lgtest -lpthread
+Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=1 -lpthread
+```
+
+Notice that the sysroot is not included in `libdir` and `includedir`! If you try
+to run `pkg-config` with the correct
+`PKG_CONFIG_LIBDIR=/home/MYUSER/sysroot/usr/lib64/pkgconfig` against this `.pc`
+file, you will get
+
+```
+$ pkg-config --cflags gtest
+-DGTEST_HAS_PTHREAD=1 -lpthread -I/usr/include
+$ pkg-config --libs gtest
+-L/usr/lib64 -lgtest -lpthread
+```
+
+which is obviously wrong and points to the `CBUILD` and not `CHOST` root. In
+order to use this in a cross-compilation setting, we need to tell pkg-config to
+inject the actual sysroot into `-I` and `-L` variables. Let us now tell
+pkg-config about the actual sysroot
+
+```
+export PKG_CONFIG_DIR=
+export PKG_CONFIG_SYSROOT_DIR=/home/MYUSER/sysroot
+export PKG_CONFIG_LIBDIR=${PKG_CONFIG_SYSROOT_DIR}/usr/lib64/pkgconfig
+```
+
+and running `pkg-config` again we get
+
+```
+$ pkg-config --cflags gtest
+-DGTEST_HAS_PTHREAD=1 -lpthread -I/home/MYUSER/sysroot/usr/include
+$ pkg-config --libs gtest
+-L/home/MYUSER/sysroot/usr/lib64 -lgtest -lpthread
+```
+
+which contains the correct sysroot now. For a more comprehensive guide to also
+including `${CHOST}` in build system calls, see the excellent tutorial by Diego
+Elio Pettenò: <https://autotools.io/pkgconfig/cross-compiling.html>
diff --git a/3rd-party/googletest/docs/platforms.md b/3rd-party/googletest/docs/platforms.md
new file mode 100644
index 0000000..d35a7be
--- /dev/null
+++ b/3rd-party/googletest/docs/platforms.md
@@ -0,0 +1,8 @@
+# Supported Platforms
+
+GoogleTest follows Google's
+[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support).
+See
+[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md)
+for a list of currently supported versions compilers, platforms, and build
+tools.
diff --git a/3rd-party/googletest/docs/primer.md b/3rd-party/googletest/docs/primer.md
new file mode 100644
index 0000000..61806be
--- /dev/null
+++ b/3rd-party/googletest/docs/primer.md
@@ -0,0 +1,482 @@
+# GoogleTest Primer
+
+## Introduction: Why GoogleTest?
+
+*GoogleTest* helps you write better C++ tests.
+
+GoogleTest is a testing framework developed by the Testing Technology team with
+Google's specific requirements and constraints in mind. Whether you work on
+Linux, Windows, or a Mac, if you write C++ code, GoogleTest can help you. And it
+supports *any* kind of tests, not just unit tests.
+
+So what makes a good test, and how does GoogleTest fit in? We believe:
+
+1.  Tests should be *independent* and *repeatable*. It's a pain to debug a test
+    that succeeds or fails as a result of other tests. GoogleTest isolates the
+    tests by running each of them on a different object. When a test fails,
+    GoogleTest allows you to run it in isolation for quick debugging.
+2.  Tests should be well *organized* and reflect the structure of the tested
+    code. GoogleTest groups related tests into test suites that can share data
+    and subroutines. This common pattern is easy to recognize and makes tests
+    easy to maintain. Such consistency is especially helpful when people switch
+    projects and start to work on a new code base.
+3.  Tests should be *portable* and *reusable*. Google has a lot of code that is
+    platform-neutral; its tests should also be platform-neutral. GoogleTest
+    works on different OSes, with different compilers, with or without
+    exceptions, so GoogleTest tests can work with a variety of configurations.
+4.  When tests fail, they should provide as much *information* about the problem
+    as possible. GoogleTest doesn't stop at the first test failure. Instead, it
+    only stops the current test and continues with the next. You can also set up
+    tests that report non-fatal failures after which the current test continues.
+    Thus, you can detect and fix multiple bugs in a single run-edit-compile
+    cycle.
+5.  The testing framework should liberate test writers from housekeeping chores
+    and let them focus on the test *content*. GoogleTest automatically keeps
+    track of all tests defined, and doesn't require the user to enumerate them
+    in order to run them.
+6.  Tests should be *fast*. With GoogleTest, you can reuse shared resources
+    across tests and pay for the set-up/tear-down only once, without making
+    tests depend on each other.
+
+Since GoogleTest is based on the popular xUnit architecture, you'll feel right
+at home if you've used JUnit or PyUnit before. If not, it will take you about 10
+minutes to learn the basics and get started. So let's go!
+
+## Beware of the Nomenclature
+
+{: .callout .note}
+*Note:* There might be some confusion arising from different definitions of the
+terms *Test*, *Test Case* and *Test Suite*, so beware of misunderstanding these.
+
+Historically, GoogleTest started to use the term *Test Case* for grouping
+related tests, whereas current publications, including International Software
+Testing Qualifications Board ([ISTQB](https://www.istqb.org/)) materials and
+various textbooks on software quality, use the term
+*[Test Suite][istqb test suite]* for this.
+
+The related term *Test*, as it is used in GoogleTest, corresponds to the term
+*[Test Case][istqb test case]* of ISTQB and others.
+
+The term *Test* is commonly of broad enough sense, including ISTQB's definition
+of *Test Case*, so it's not much of a problem here. But the term *Test Case* as
+was used in Google Test is of contradictory sense and thus confusing.
+
+GoogleTest recently started replacing the term *Test Case* with *Test Suite*.
+The preferred API is *TestSuite*. The older TestCase API is being slowly
+deprecated and refactored away.
+
+So please be aware of the different definitions of the terms:
+
+
+Meaning                                                                              | GoogleTest Term         | [ISTQB](https://www.istqb.org/) Term
+:----------------------------------------------------------------------------------- | :---------------------- | :----------------------------------
+Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
+
+
+[istqb test case]: https://glossary.istqb.org/en_US/term/test-case-2
+[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite-1-3
+
+## Basic Concepts
+
+When using GoogleTest, you start by writing *assertions*, which are statements
+that check whether a condition is true. An assertion's result can be *success*,
+*nonfatal failure*, or *fatal failure*. If a fatal failure occurs, it aborts the
+current function; otherwise the program continues normally.
+
+*Tests* use assertions to verify the tested code's behavior. If a test crashes
+or has a failed assertion, then it *fails*; otherwise it *succeeds*.
+
+A *test suite* contains one or many tests. You should group your tests into test
+suites that reflect the structure of the tested code. When multiple tests in a
+test suite need to share common objects and subroutines, you can put them into a
+*test fixture* class.
+
+A *test program* can contain multiple test suites.
+
+We'll now explain how to write a test program, starting at the individual
+assertion level and building up to tests and test suites.
+
+## Assertions
+
+GoogleTest assertions are macros that resemble function calls. You test a class
+or function by making assertions about its behavior. When an assertion fails,
+GoogleTest prints the assertion's source file and line number location, along
+with a failure message. You may also supply a custom failure message which will
+be appended to GoogleTest's message.
+
+The assertions come in pairs that test the same thing but have different effects
+on the current function. `ASSERT_*` versions generate fatal failures when they
+fail, and **abort the current function**. `EXPECT_*` versions generate nonfatal
+failures, which don't abort the current function. Usually `EXPECT_*` are
+preferred, as they allow more than one failure to be reported in a test.
+However, you should use `ASSERT_*` if it doesn't make sense to continue when the
+assertion in question fails.
+
+Since a failed `ASSERT_*` returns from the current function immediately,
+possibly skipping clean-up code that comes after it, it may cause a space leak.
+Depending on the nature of the leak, it may or may not be worth fixing - so keep
+this in mind if you get a heap checker error in addition to assertion errors.
+
+To provide a custom failure message, simply stream it into the macro using the
+`<<` operator or a sequence of such operators. See the following example, using
+the [`ASSERT_EQ` and `EXPECT_EQ`](reference/assertions.md#EXPECT_EQ) macros to
+verify value equality:
+
+```c++
+ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
+
+for (int i = 0; i < x.size(); ++i) {
+  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
+}
+```
+
+Anything that can be streamed to an `ostream` can be streamed to an assertion
+macro--in particular, C strings and `string` objects. If a wide string
+(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
+streamed to an assertion, it will be translated to UTF-8 when printed.
+
+GoogleTest provides a collection of assertions for verifying the behavior of
+your code in various ways. You can check Boolean conditions, compare values
+based on relational operators, verify string values, floating-point values, and
+much more. There are even assertions that enable you to verify more complex
+states by providing custom predicates. For the complete list of assertions
+provided by GoogleTest, see the [Assertions Reference](reference/assertions.md).
+
+## Simple Tests
+
+To create a test:
+
+1.  Use the `TEST()` macro to define and name a test function. These are
+    ordinary C++ functions that don't return a value.
+2.  In this function, along with any valid C++ statements you want to include,
+    use the various GoogleTest assertions to check values.
+3.  The test's result is determined by the assertions; if any assertion in the
+    test fails (either fatally or non-fatally), or if the test crashes, the
+    entire test fails. Otherwise, it succeeds.
+
+```c++
+TEST(TestSuiteName, TestName) {
+  ... test body ...
+}
+```
+
+`TEST()` arguments go from general to specific. The *first* argument is the name
+of the test suite, and the *second* argument is the test's name within the test
+suite. Both names must be valid C++ identifiers, and they should not contain any
+underscores (`_`). A test's *full name* consists of its containing test suite
+and its individual name. Tests from different test suites can have the same
+individual name.
+
+For example, let's take a simple integer function:
+
+```c++
+int Factorial(int n);  // Returns the factorial of n
+```
+
+A test suite for this function might look like:
+
+```c++
+// Tests factorial of 0.
+TEST(FactorialTest, HandlesZeroInput) {
+  EXPECT_EQ(Factorial(0), 1);
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, HandlesPositiveInput) {
+  EXPECT_EQ(Factorial(1), 1);
+  EXPECT_EQ(Factorial(2), 2);
+  EXPECT_EQ(Factorial(3), 6);
+  EXPECT_EQ(Factorial(8), 40320);
+}
+```
+
+GoogleTest groups the test results by test suites, so logically related tests
+should be in the same test suite; in other words, the first argument to their
+`TEST()` should be the same. In the above example, we have two tests,
+`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
+suite `FactorialTest`.
+
+When naming your test suites and tests, you should follow the same convention as
+for
+[naming functions and classes](https://google.github.io/styleguide/cppguide.html#Function_Names).
+
+**Availability**: Linux, Windows, Mac.
+
+## Test Fixtures: Using the Same Data Configuration for Multiple Tests {#same-data-multiple-tests}
+
+If you find yourself writing two or more tests that operate on similar data, you
+can use a *test fixture*. This allows you to reuse the same configuration of
+objects for several different tests.
+
+To create a fixture:
+
+1.  Derive a class from `testing::Test` . Start its body with `protected:`, as
+    we'll want to access fixture members from sub-classes.
+2.  Inside the class, declare any objects you plan to use.
+3.  If necessary, write a default constructor or `SetUp()` function to prepare
+    the objects for each test. A common mistake is to spell `SetUp()` as
+    **`Setup()`** with a small `u` - Use `override` in C++11 to make sure you
+    spelled it correctly.
+4.  If necessary, write a destructor or `TearDown()` function to release any
+    resources you allocated in `SetUp()` . To learn when you should use the
+    constructor/destructor and when you should use `SetUp()/TearDown()`, read
+    the [FAQ](faq.md#CtorVsSetUp).
+5.  If needed, define subroutines for your tests to share.
+
+When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
+access objects and subroutines in the test fixture:
+
+```c++
+TEST_F(TestFixtureClassName, TestName) {
+  ... test body ...
+}
+```
+
+Unlike `TEST()`, in `TEST_F()` the first argument must be the name of the test
+fixture class. (`_F` stands for "Fixture"). No test suite name is specified for
+this macro.
+
+Unfortunately, the C++ macro system does not allow us to create a single macro
+that can handle both types of tests. Using the wrong macro causes a compiler
+error.
+
+Also, you must first define a test fixture class before using it in a
+`TEST_F()`, or you'll get the compiler error "`virtual outside class
+declaration`".
+
+For each test defined with `TEST_F()`, GoogleTest will create a *fresh* test
+fixture at runtime, immediately initialize it via `SetUp()`, run the test, clean
+up by calling `TearDown()`, and then delete the test fixture. Note that
+different tests in the same test suite have different test fixture objects, and
+GoogleTest always deletes a test fixture before it creates the next one.
+GoogleTest does **not** reuse the same test fixture for multiple tests. Any
+changes one test makes to the fixture do not affect other tests.
+
+As an example, let's write tests for a FIFO queue class named `Queue`, which has
+the following interface:
+
+```c++
+template <typename E>  // E is the element type.
+class Queue {
+ public:
+  Queue();
+  void Enqueue(const E& element);
+  E* Dequeue();  // Returns NULL if the queue is empty.
+  size_t size() const;
+  ...
+};
+```
+
+First, define a fixture class. By convention, you should give it the name
+`FooTest` where `Foo` is the class being tested.
+
+```c++
+class QueueTest : public testing::Test {
+ protected:
+  QueueTest() {
+     // q0_ remains empty
+     q1_.Enqueue(1);
+     q2_.Enqueue(2);
+     q2_.Enqueue(3);
+  }
+
+  // ~QueueTest() override = default;
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+```
+
+In this case, we don't need to define a destructor or a `TearDown()` method,
+because the implicit destructor generated by the compiler will perform all of
+the necessary cleanup.
+
+Now we'll write tests using `TEST_F()` and this fixture.
+
+```c++
+TEST_F(QueueTest, IsEmptyInitially) {
+  EXPECT_EQ(q0_.size(), 0);
+}
+
+TEST_F(QueueTest, DequeueWorks) {
+  int* n = q0_.Dequeue();
+  EXPECT_EQ(n, nullptr);
+
+  n = q1_.Dequeue();
+  ASSERT_NE(n, nullptr);
+  EXPECT_EQ(*n, 1);
+  EXPECT_EQ(q1_.size(), 0);
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_NE(n, nullptr);
+  EXPECT_EQ(*n, 2);
+  EXPECT_EQ(q2_.size(), 1);
+  delete n;
+}
+```
+
+The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
+to use `EXPECT_*` when you want the test to continue to reveal more errors after
+the assertion failure, and use `ASSERT_*` when continuing after failure doesn't
+make sense. For example, the second assertion in the `Dequeue` test is
+`ASSERT_NE(n, nullptr)`, as we need to dereference the pointer `n` later, which
+would lead to a segfault when `n` is `NULL`.
+
+When these tests run, the following happens:
+
+1.  GoogleTest constructs a `QueueTest` object (let's call it `t1`).
+2.  The first test (`IsEmptyInitially`) runs on `t1`.
+3.  `t1` is destructed.
+4.  The above steps are repeated on another `QueueTest` object, this time
+    running the `DequeueWorks` test.
+
+**Availability**: Linux, Windows, Mac.
+
+## Invoking the Tests
+
+`TEST()` and `TEST_F()` implicitly register their tests with GoogleTest. So,
+unlike with many other C++ testing frameworks, you don't have to re-list all
+your defined tests in order to run them.
+
+After defining your tests, you can run them with `RUN_ALL_TESTS()`, which
+returns `0` if all the tests are successful, or `1` otherwise. Note that
+`RUN_ALL_TESTS()` runs *all tests* in your link unit--they can be from different
+test suites, or even different source files.
+
+When invoked, the `RUN_ALL_TESTS()` macro:
+
+*   Saves the state of all GoogleTest flags.
+
+*   Creates a test fixture object for the first test.
+
+*   Initializes it via `SetUp()`.
+
+*   Runs the test on the fixture object.
+
+*   Cleans up the fixture via `TearDown()`.
+
+*   Deletes the fixture.
+
+*   Restores the state of all GoogleTest flags.
+
+*   Repeats the above steps for the next test, until all tests have run.
+
+If a fatal failure happens the subsequent steps will be skipped.
+
+{: .callout .important}
+> IMPORTANT: You must **not** ignore the return value of `RUN_ALL_TESTS()`, or
+> you will get a compiler error. The rationale for this design is that the
+> automated testing service determines whether a test has passed based on its
+> exit code, not on its stdout/stderr output; thus your `main()` function must
+> return the value of `RUN_ALL_TESTS()`.
+>
+> Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than
+> once conflicts with some advanced GoogleTest features (e.g., thread-safe
+> [death tests](advanced.md#death-tests)) and thus is not supported.
+
+**Availability**: Linux, Windows, Mac.
+
+## Writing the main() Function
+
+Most users should *not* need to write their own `main` function and instead link
+with `gtest_main` (as opposed to with `gtest`), which defines a suitable entry
+point. See the end of this section for details. The remainder of this section
+should only apply when you need to do something custom before the tests run that
+cannot be expressed within the framework of fixtures and test suites.
+
+If you write your own `main` function, it should return the value of
+`RUN_ALL_TESTS()`.
+
+You can start from this boilerplate:
+
+```c++
+#include "this/package/foo.h"
+
+#include <gtest/gtest.h>
+
+namespace my {
+namespace project {
+namespace {
+
+// The fixture for testing class Foo.
+class FooTest : public testing::Test {
+ protected:
+  // You can remove any or all of the following functions if their bodies would
+  // be empty.
+
+  FooTest() {
+     // You can do set-up work for each test here.
+  }
+
+  ~FooTest() override {
+     // You can do clean-up work that doesn't throw exceptions here.
+  }
+
+  // If the constructor and destructor are not enough for setting up
+  // and cleaning up each test, you can define the following methods:
+
+  void SetUp() override {
+     // Code here will be called immediately after the constructor (right
+     // before each test).
+  }
+
+  void TearDown() override {
+     // Code here will be called immediately after each test (right
+     // before the destructor).
+  }
+
+  // Class members declared here can be used by all tests in the test suite
+  // for Foo.
+};
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(FooTest, MethodBarDoesAbc) {
+  const std::string input_filepath = "this/package/testdata/myinputfile.dat";
+  const std::string output_filepath = "this/package/testdata/myoutputfile.dat";
+  Foo f;
+  EXPECT_EQ(f.Bar(input_filepath, output_filepath), 0);
+}
+
+// Tests that Foo does Xyz.
+TEST_F(FooTest, DoesXyz) {
+  // Exercises the Xyz feature of Foo.
+}
+
+}  // namespace
+}  // namespace project
+}  // namespace my
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+The `testing::InitGoogleTest()` function parses the command line for GoogleTest
+flags, and removes all recognized flags. This allows the user to control a test
+program's behavior via various flags, which we'll cover in the
+[AdvancedGuide](advanced.md). You **must** call this function before calling
+`RUN_ALL_TESTS()`, or the flags won't be properly initialized.
+
+On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
+in programs compiled in `UNICODE` mode as well.
+
+But maybe you think that writing all those `main` functions is too much work? We
+agree with you completely, and that's why Google Test provides a basic
+implementation of main(). If it fits your needs, then just link your test with
+the `gtest_main` library and you are good to go.
+
+{: .callout .note}
+NOTE: `ParseGUnitFlags()` is deprecated in favor of `InitGoogleTest()`.
+
+## Known Limitations
+
+*   Google Test is designed to be thread-safe. The implementation is thread-safe
+    on systems where the `pthreads` library is available. It is currently
+    *unsafe* to use Google Test assertions from two threads concurrently on
+    other systems (e.g. Windows). In most tests this is not an issue as usually
+    the assertions are done in the main thread. If you want to help, you can
+    volunteer to implement the necessary synchronization primitives in
+    `gtest-port.h` for your platform.
diff --git a/3rd-party/googletest/docs/quickstart-bazel.md b/3rd-party/googletest/docs/quickstart-bazel.md
new file mode 100644
index 0000000..d14f7c6
--- /dev/null
+++ b/3rd-party/googletest/docs/quickstart-bazel.md
@@ -0,0 +1,146 @@
+# 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++14.
+*   [Bazel](https://bazel.build/) 7.0 or higher, 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://bazel.build/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 Bazel workspace
+
+A
+[Bazel workspace](https://docs.bazel.build/versions/main/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
+`MODULE.bazel` 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 `MODULE.bazel` file to specify dependencies. As of Bazel
+7.0, the recommended way to consume GoogleTest is through the
+[Bazel Central Registry](https://registry.bazel.build/modules/googletest). To do
+this, create a `MODULE.bazel` file in the root directory of your Bazel workspace
+with the following content:
+
+```
+# MODULE.bazel
+
+# Choose the most recent version available at
+# https://registry.bazel.build/modules/googletest
+bazel_dep(name = "googletest", version = "1.15.0")
+```
+
+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:
+
+```
+cc_test(
+    name = "hello_test",
+    size = "small",
+    srcs = ["hello_test.cc"],
+    deps = [
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+```
+
+This `cc_test` rule declares the C++ test binary you want to build, and links to
+the GoogleTest library (`@googletest//:gtest"`) and the GoogleTest `main()`
+function (`@googletest//:gtest_main`). For more information about Bazel `BUILD`
+files, see the
+[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
+
+{: .callout .note}
+NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++14`
+to ensure that GoogleTest is compiled as C++14 instead of the compiler's default
+setting (which could be C++11). For MSVC, the equivalent would be
+`--cxxopt=/std:c++14`. See [Supported Platforms](platforms.md) for more details
+on supported language versions.
+
+Now you can build and run your test:
+
+<pre>
+<strong>$ bazel test --cxxopt=-std=c++14 --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/3rd-party/googletest/docs/quickstart-cmake.md b/3rd-party/googletest/docs/quickstart-cmake.md
new file mode 100644
index 0000000..4e422b7
--- /dev/null
+++ b/3rd-party/googletest/docs/quickstart-cmake.md
@@ -0,0 +1,157 @@
+# 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++14.
+*   [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++14
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+include(FetchContent)
+FetchContent_Declare(
+  googletest
+  URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.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, `03597a01ee50ed33e9dfd640b249b4be3799d395` 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::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/3rd-party/googletest/docs/reference/actions.md b/3rd-party/googletest/docs/reference/actions.md
new file mode 100644
index 0000000..ab81a12
--- /dev/null
+++ b/3rd-party/googletest/docs/reference/actions.md
@@ -0,0 +1,115 @@
+# Actions Reference
+
+[**Actions**](../gmock_for_dummies.md#actions-what-should-it-do) specify what a
+mock function should do when invoked. This page lists the built-in actions
+provided by GoogleTest. All actions are defined in the `::testing` namespace.
+
+## Returning a Value
+
+| Action                            | Description                                   |
+| :-------------------------------- | :-------------------------------------------- |
+| `Return()`                        | Return from a `void` mock function.           |
+| `Return(value)`                   | Return `value`. If the type of `value` is     different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. |
+| `ReturnArg<N>()`                  | Return the `N`-th (0-based) argument.         |
+| `ReturnNew<T>(a1, ..., ak)`       | Return `new T(a1, ..., ak)`; a different      object is created each time. |
+| `ReturnNull()`                    | Return a null pointer.                        |
+| `ReturnPointee(ptr)`              | Return the value pointed to by `ptr`.         |
+| `ReturnRef(variable)`             | Return a reference to `variable`.             |
+| `ReturnRefOfCopy(value)`          | Return a reference to a copy of `value`; the  copy lives as long as the action. |
+| `ReturnRoundRobin({a1, ..., ak})` | Each call will return the next `ai` in the list, starting at the beginning when the end of the list is reached. |
+
+## Side Effects
+
+| Action                             | Description                             |
+| :--------------------------------- | :-------------------------------------- |
+| `Assign(&variable, value)` | Assign `value` to variable. |
+| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
+| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
+| `SetArgReferee<N>(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. |
+| `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |
+| `SetArgumentPointee<N>(value)` | Same as `SetArgPointee<N>(value)`. Deprecated. Will be removed in v1.7.0. |
+| `SetArrayArgument<N>(first, last)` | Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range. |
+| `SetErrnoAndReturn(error, value)` | Set `errno` to `error` and return `value`. |
+| `Throw(exception)` | Throws the given exception, which can be any copyable value. Available since v1.1.0. |
+
+## Using a Function, Functor, or Lambda as an Action
+
+In the following, by "callable" we mean a free function, `std::function`,
+functor, or lambda.
+
+| Action                              | Description                            |
+| :---------------------------------- | :------------------------------------- |
+| `f` | Invoke `f` with the arguments passed to the mock function, where `f` is a callable. |
+| `Invoke(f)` | Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor. |
+| `Invoke(object_pointer, &class::method)` | Invoke the method on the object with the arguments passed to the mock function. |
+| `InvokeWithoutArgs(f)` | Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. |
+| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
+| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
+
+The return value of the invoked function is used as the return value of the
+action.
+
+When defining a callable to be used with `Invoke*()`, you can declare any unused
+parameters as `Unused`:
+
+```cpp
+using ::testing::Invoke;
+double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
+...
+EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
+```
+
+`Invoke(callback)` and `InvokeWithoutArgs(callback)` take ownership of
+`callback`, which must be permanent. The type of `callback` must be a base
+callback type instead of a derived one, e.g.
+
+```cpp
+  BlockingClosure* done = new BlockingClosure;
+  ... Invoke(done) ...;  // This won't compile!
+
+  Closure* done2 = new BlockingClosure;
+  ... Invoke(done2) ...;  // This works.
+```
+
+In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference,
+wrap it inside `std::ref()`. For example,
+
+```cpp
+using ::testing::InvokeArgument;
+...
+InvokeArgument<2>(5, string("Hi"), std::ref(foo))
+```
+
+calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by
+value, and `foo` by reference.
+
+## Default Action
+
+| Action        | Description                                            |
+| :------------ | :----------------------------------------------------- |
+| `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). |
+
+{: .callout .note}
+**Note:** due to technical reasons, `DoDefault()` cannot be used inside a
+composite action - trying to do so will result in a run-time error.
+
+## Composite Actions
+
+| Action                         | Description                                 |
+| :----------------------------- | :------------------------------------------ |
+| `DoAll(a1, a2, ..., an)`       | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void and will receive a  readonly view of the arguments. |
+| `IgnoreResult(a)`              | Perform action `a` and ignore its result. `a` must not return void. |
+| `WithArg<N>(a)`                | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. |
+| `WithArgs<N1, N2, ..., Nk>(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. |
+| `WithoutArgs(a)`               | Perform action `a` without any arguments. |
+
+## Defining Actions
+
+| Macro                              | Description                             |
+| :--------------------------------- | :-------------------------------------- |
+| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
+| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
+| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`. |
+
+The `ACTION*` macros cannot be used inside a function or class.
diff --git a/3rd-party/googletest/docs/reference/assertions.md b/3rd-party/googletest/docs/reference/assertions.md
new file mode 100644
index 0000000..492ff5e
--- /dev/null
+++ b/3rd-party/googletest/docs/reference/assertions.md
@@ -0,0 +1,633 @@
+# Assertions Reference
+
+This page lists the assertion macros provided by GoogleTest for verifying code
+behavior. To use them, add `#include <gtest/gtest.h>`.
+
+The majority of the macros listed below come as a pair with an `EXPECT_` variant
+and an `ASSERT_` variant. Upon failure, `EXPECT_` macros generate nonfatal
+failures and allow the current function to continue running, while `ASSERT_`
+macros generate fatal failures and abort the current function.
+
+All assertion macros support streaming a custom failure message into them with
+the `<<` operator, for example:
+
+```cpp
+EXPECT_TRUE(my_condition) << "My condition is not true";
+```
+
+Anything that can be streamed to an `ostream` can be streamed to an assertion
+macro—in particular, C strings and string objects. If a wide string (`wchar_t*`,
+`TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is streamed to an
+assertion, it will be translated to UTF-8 when printed.
+
+## Explicit Success and Failure {#success-failure}
+
+The assertions in this section generate a success or failure directly instead of
+testing a value or expression. These are useful when control flow, rather than a
+Boolean expression, determines the test's success or failure, as shown by the
+following example:
+
+```c++
+switch(expression) {
+  case 1:
+    ... some checks ...
+  case 2:
+    ... some other checks ...
+  default:
+    FAIL() << "We shouldn't get here.";
+}
+```
+
+### SUCCEED {#SUCCEED}
+
+`SUCCEED()`
+
+Generates a success. This *does not* make the overall test succeed. A test is
+considered successful only if none of its assertions fail during its execution.
+
+The `SUCCEED` assertion is purely documentary and currently doesn't generate any
+user-visible output. However, we may add `SUCCEED` messages to GoogleTest output
+in the future.
+
+### FAIL {#FAIL}
+
+`FAIL()`
+
+Generates a fatal failure, which returns from the current function.
+
+Can only be used in functions that return `void`. See
+[Assertion Placement](../advanced.md#assertion-placement) for more information.
+
+### ADD_FAILURE {#ADD_FAILURE}
+
+`ADD_FAILURE()`
+
+Generates a nonfatal failure, which allows the current function to continue
+running.
+
+### ADD_FAILURE_AT {#ADD_FAILURE_AT}
+
+`ADD_FAILURE_AT(`*`file_path`*`,`*`line_number`*`)`
+
+Generates a nonfatal failure at the file and line number specified.
+
+## Generalized Assertion {#generalized}
+
+The following assertion allows [matchers](matchers.md) to be used to verify
+values.
+
+### EXPECT_THAT {#EXPECT_THAT}
+
+`EXPECT_THAT(`*`value`*`,`*`matcher`*`)` \
+`ASSERT_THAT(`*`value`*`,`*`matcher`*`)`
+
+Verifies that *`value`* matches the [matcher](matchers.md) *`matcher`*.
+
+For example, the following code verifies that the string `value1` starts with
+`"Hello"`, `value2` matches a regular expression, and `value3` is between 5 and
+10:
+
+```cpp
+#include <gmock/gmock.h>
+
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::Lt;
+using ::testing::MatchesRegex;
+using ::testing::StartsWith;
+
+...
+EXPECT_THAT(value1, StartsWith("Hello"));
+EXPECT_THAT(value2, MatchesRegex("Line \\d+"));
+ASSERT_THAT(value3, AllOf(Gt(5), Lt(10)));
+```
+
+Matchers enable assertions of this form to read like English and generate
+informative failure messages. For example, if the above assertion on `value1`
+fails, the resulting message will be similar to the following:
+
+```
+Value of: value1
+  Actual: "Hi, world!"
+Expected: starts with "Hello"
+```
+
+GoogleTest provides a built-in library of matchers—see the
+[Matchers Reference](matchers.md). It is also possible to write your own
+matchers—see [Writing New Matchers Quickly](../gmock_cook_book.md#NewMatchers).
+The use of matchers makes `EXPECT_THAT` a powerful, extensible assertion.
+
+*The idea for this assertion was borrowed from Joe Walnes' Hamcrest project,
+which adds `assertThat()` to JUnit.*
+
+## Boolean Conditions {#boolean}
+
+The following assertions test Boolean conditions.
+
+### EXPECT_TRUE {#EXPECT_TRUE}
+
+`EXPECT_TRUE(`*`condition`*`)` \
+`ASSERT_TRUE(`*`condition`*`)`
+
+Verifies that *`condition`* is true.
+
+### EXPECT_FALSE {#EXPECT_FALSE}
+
+`EXPECT_FALSE(`*`condition`*`)` \
+`ASSERT_FALSE(`*`condition`*`)`
+
+Verifies that *`condition`* is false.
+
+## Binary Comparison {#binary-comparison}
+
+The following assertions compare two values. The value arguments must be
+comparable by the assertion's comparison operator, otherwise a compiler error
+will result.
+
+If an argument supports the `<<` operator, it will be called to print the
+argument when the assertion fails. Otherwise, GoogleTest will attempt to print
+them in the best way it can—see
+[Teaching GoogleTest How to Print Your Values](../advanced.md#teaching-googletest-how-to-print-your-values).
+
+Arguments are always evaluated exactly once, so it's OK for the arguments to
+have side effects. However, the argument evaluation order is undefined and
+programs should not depend on any particular argument evaluation order.
+
+These assertions work with both narrow and wide string objects (`string` and
+`wstring`).
+
+See also the [Floating-Point Comparison](#floating-point) assertions to compare
+floating-point numbers and avoid problems caused by rounding.
+
+### EXPECT_EQ {#EXPECT_EQ}
+
+`EXPECT_EQ(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_EQ(`*`val1`*`,`*`val2`*`)`
+
+Verifies that *`val1`*`==`*`val2`*.
+
+Does pointer equality on pointers. If used on two C strings, it tests if they
+are in the same memory location, not if they have the same value. Use
+[`EXPECT_STREQ`](#EXPECT_STREQ) to compare C strings (e.g. `const char*`) by
+value.
+
+When comparing a pointer to `NULL`, use `EXPECT_EQ(`*`ptr`*`, nullptr)` instead
+of `EXPECT_EQ(`*`ptr`*`, NULL)`.
+
+### EXPECT_NE {#EXPECT_NE}
+
+`EXPECT_NE(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_NE(`*`val1`*`,`*`val2`*`)`
+
+Verifies that *`val1`*`!=`*`val2`*.
+
+Does pointer equality on pointers. If used on two C strings, it tests if they
+are in different memory locations, not if they have different values. Use
+[`EXPECT_STRNE`](#EXPECT_STRNE) to compare C strings (e.g. `const char*`) by
+value.
+
+When comparing a pointer to `NULL`, use `EXPECT_NE(`*`ptr`*`, nullptr)` instead
+of `EXPECT_NE(`*`ptr`*`, NULL)`.
+
+### EXPECT_LT {#EXPECT_LT}
+
+`EXPECT_LT(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_LT(`*`val1`*`,`*`val2`*`)`
+
+Verifies that *`val1`*`<`*`val2`*.
+
+### EXPECT_LE {#EXPECT_LE}
+
+`EXPECT_LE(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_LE(`*`val1`*`,`*`val2`*`)`
+
+Verifies that *`val1`*`<=`*`val2`*.
+
+### EXPECT_GT {#EXPECT_GT}
+
+`EXPECT_GT(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_GT(`*`val1`*`,`*`val2`*`)`
+
+Verifies that *`val1`*`>`*`val2`*.
+
+### EXPECT_GE {#EXPECT_GE}
+
+`EXPECT_GE(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_GE(`*`val1`*`,`*`val2`*`)`
+
+Verifies that *`val1`*`>=`*`val2`*.
+
+## String Comparison {#c-strings}
+
+The following assertions compare two **C strings**. To compare two `string`
+objects, use [`EXPECT_EQ`](#EXPECT_EQ) or [`EXPECT_NE`](#EXPECT_NE) instead.
+
+These assertions also accept wide C strings (`wchar_t*`). If a comparison of two
+wide strings fails, their values will be printed as UTF-8 narrow strings.
+
+To compare a C string with `NULL`, use `EXPECT_EQ(`*`c_string`*`, nullptr)` or
+`EXPECT_NE(`*`c_string`*`, nullptr)`.
+
+### EXPECT_STREQ {#EXPECT_STREQ}
+
+`EXPECT_STREQ(`*`str1`*`,`*`str2`*`)` \
+`ASSERT_STREQ(`*`str1`*`,`*`str2`*`)`
+
+Verifies that the two C strings *`str1`* and *`str2`* have the same contents.
+
+### EXPECT_STRNE {#EXPECT_STRNE}
+
+`EXPECT_STRNE(`*`str1`*`,`*`str2`*`)` \
+`ASSERT_STRNE(`*`str1`*`,`*`str2`*`)`
+
+Verifies that the two C strings *`str1`* and *`str2`* have different contents.
+
+### EXPECT_STRCASEEQ {#EXPECT_STRCASEEQ}
+
+`EXPECT_STRCASEEQ(`*`str1`*`,`*`str2`*`)` \
+`ASSERT_STRCASEEQ(`*`str1`*`,`*`str2`*`)`
+
+Verifies that the two C strings *`str1`* and *`str2`* have the same contents,
+ignoring case.
+
+### EXPECT_STRCASENE {#EXPECT_STRCASENE}
+
+`EXPECT_STRCASENE(`*`str1`*`,`*`str2`*`)` \
+`ASSERT_STRCASENE(`*`str1`*`,`*`str2`*`)`
+
+Verifies that the two C strings *`str1`* and *`str2`* have different contents,
+ignoring case.
+
+## Floating-Point Comparison {#floating-point}
+
+The following assertions compare two floating-point values.
+
+Due to rounding errors, it is very unlikely that two floating-point values will
+match exactly, so `EXPECT_EQ` is not suitable. In general, for floating-point
+comparison to make sense, the user needs to carefully choose the error bound.
+
+GoogleTest also provides assertions that use a default error bound based on
+Units in the Last Place (ULPs). To learn more about ULPs, see the article
+[Comparing Floating Point Numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
+
+### EXPECT_FLOAT_EQ {#EXPECT_FLOAT_EQ}
+
+`EXPECT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)`
+
+Verifies that the two `float` values *`val1`* and *`val2`* are approximately
+equal, to within 4 ULPs from each other.
+
+### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
+
+`EXPECT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)` \
+`ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)`
+
+Verifies that the two `double` values *`val1`* and *`val2`* are approximately
+equal, to within 4 ULPs from each other.
+
+### EXPECT_NEAR {#EXPECT_NEAR}
+
+`EXPECT_NEAR(`*`val1`*`,`*`val2`*`,`*`abs_error`*`)` \
+`ASSERT_NEAR(`*`val1`*`,`*`val2`*`,`*`abs_error`*`)`
+
+Verifies that the difference between *`val1`* and *`val2`* does not exceed the
+absolute error bound *`abs_error`*.
+
+## Exception Assertions {#exceptions}
+
+The following assertions verify that a piece of code throws, or does not throw,
+an exception. Usage requires exceptions to be enabled in the build environment.
+
+Note that the piece of code under test can be a compound statement, for example:
+
+```cpp
+EXPECT_NO_THROW({
+  int n = 5;
+  DoSomething(&n);
+});
+```
+
+### EXPECT_THROW {#EXPECT_THROW}
+
+`EXPECT_THROW(`*`statement`*`,`*`exception_type`*`)` \
+`ASSERT_THROW(`*`statement`*`,`*`exception_type`*`)`
+
+Verifies that *`statement`* throws an exception of type *`exception_type`*.
+
+### EXPECT_ANY_THROW {#EXPECT_ANY_THROW}
+
+`EXPECT_ANY_THROW(`*`statement`*`)` \
+`ASSERT_ANY_THROW(`*`statement`*`)`
+
+Verifies that *`statement`* throws an exception of any type.
+
+### EXPECT_NO_THROW {#EXPECT_NO_THROW}
+
+`EXPECT_NO_THROW(`*`statement`*`)` \
+`ASSERT_NO_THROW(`*`statement`*`)`
+
+Verifies that *`statement`* does not throw any exception.
+
+## Predicate Assertions {#predicates}
+
+The following assertions enable more complex predicates to be verified while
+printing a more clear failure message than if `EXPECT_TRUE` were used alone.
+
+### EXPECT_PRED* {#EXPECT_PRED}
+
+`EXPECT_PRED1(`*`pred`*`,`*`val1`*`)` \
+`EXPECT_PRED2(`*`pred`*`,`*`val1`*`,`*`val2`*`)` \
+`EXPECT_PRED3(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
+`EXPECT_PRED4(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` \
+`EXPECT_PRED5(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
+
+`ASSERT_PRED1(`*`pred`*`,`*`val1`*`)` \
+`ASSERT_PRED2(`*`pred`*`,`*`val1`*`,`*`val2`*`)` \
+`ASSERT_PRED3(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
+`ASSERT_PRED4(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` \
+`ASSERT_PRED5(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
+
+Verifies that the predicate *`pred`* returns `true` when passed the given values
+as arguments.
+
+The parameter *`pred`* is a function or functor that accepts as many arguments
+as the corresponding macro accepts values. If *`pred`* returns `true` for the
+given arguments, the assertion succeeds, otherwise the assertion fails.
+
+When the assertion fails, it prints the value of each argument. Arguments are
+always evaluated exactly once.
+
+As an example, see the following code:
+
+```cpp
+// Returns true if m and n have no common divisors except 1.
+bool MutuallyPrime(int m, int n) { ... }
+...
+const int a = 3;
+const int b = 4;
+const int c = 10;
+...
+EXPECT_PRED2(MutuallyPrime, a, b);  // Succeeds
+EXPECT_PRED2(MutuallyPrime, b, c);  // Fails
+```
+
+In the above example, the first assertion succeeds, and the second fails with
+the following message:
+
+```
+MutuallyPrime(b, c) is false, where
+b is 4
+c is 10
+```
+
+Note that if the given predicate is an overloaded function or a function
+template, the assertion macro might not be able to determine which version to
+use, and it might be necessary to explicitly specify the type of the function.
+For example, for a Boolean function `IsPositive()` overloaded to take either a
+single `int` or `double` argument, it would be necessary to write one of the
+following:
+
+```cpp
+EXPECT_PRED1(static_cast<bool (*)(int)>(IsPositive), 5);
+EXPECT_PRED1(static_cast<bool (*)(double)>(IsPositive), 3.14);
+```
+
+Writing simply `EXPECT_PRED1(IsPositive, 5);` would result in a compiler error.
+Similarly, to use a template function, specify the template arguments:
+
+```cpp
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+...
+EXPECT_PRED1(IsNegative<int>, -5);  // Must specify type for IsNegative
+```
+
+If a template has multiple parameters, wrap the predicate in parentheses so the
+macro arguments are parsed correctly:
+
+```cpp
+ASSERT_PRED2((MyPredicate<int, int>), 5, 0);
+```
+
+### EXPECT_PRED_FORMAT* {#EXPECT_PRED_FORMAT}
+
+`EXPECT_PRED_FORMAT1(`*`pred_formatter`*`,`*`val1`*`)` \
+`EXPECT_PRED_FORMAT2(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`)` \
+`EXPECT_PRED_FORMAT3(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
+`EXPECT_PRED_FORMAT4(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)`
+\
+`EXPECT_PRED_FORMAT5(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
+
+`ASSERT_PRED_FORMAT1(`*`pred_formatter`*`,`*`val1`*`)` \
+`ASSERT_PRED_FORMAT2(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`)` \
+`ASSERT_PRED_FORMAT3(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
+`ASSERT_PRED_FORMAT4(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)`
+\
+`ASSERT_PRED_FORMAT5(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
+
+Verifies that the predicate *`pred_formatter`* succeeds when passed the given
+values as arguments.
+
+The parameter *`pred_formatter`* is a *predicate-formatter*, which is a function
+or functor with the signature:
+
+```cpp
+testing::AssertionResult PredicateFormatter(const char* expr1,
+                                            const char* expr2,
+                                            ...
+                                            const char* exprn,
+                                            T1 val1,
+                                            T2 val2,
+                                            ...
+                                            Tn valn);
+```
+
+where *`val1`*, *`val2`*, ..., *`valn`* are the values of the predicate
+arguments, and *`expr1`*, *`expr2`*, ..., *`exprn`* are the corresponding
+expressions as they appear in the source code. The types `T1`, `T2`, ..., `Tn`
+can be either value types or reference types; if an argument has type `T`, it
+can be declared as either `T` or `const T&`, whichever is appropriate. For more
+about the return type `testing::AssertionResult`, see
+[Using a Function That Returns an AssertionResult](../advanced.md#using-a-function-that-returns-an-assertionresult).
+
+As an example, see the following code:
+
+```cpp
+// Returns the smallest prime common divisor of m and n,
+// or 1 when m and n are mutually prime.
+int SmallestPrimeCommonDivisor(int m, int n) { ... }
+
+// Returns true if m and n have no common divisors except 1.
+bool MutuallyPrime(int m, int n) { ... }
+
+// A predicate-formatter for asserting that two integers are mutually prime.
+testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
+                                             const char* n_expr,
+                                             int m,
+                                             int n) {
+  if (MutuallyPrime(m, n)) return testing::AssertionSuccess();
+
+  return testing::AssertionFailure() << m_expr << " and " << n_expr
+      << " (" << m << " and " << n << ") are not mutually prime, "
+      << "as they have a common divisor " << SmallestPrimeCommonDivisor(m, n);
+}
+
+...
+const int a = 3;
+const int b = 4;
+const int c = 10;
+...
+EXPECT_PRED_FORMAT2(AssertMutuallyPrime, a, b);  // Succeeds
+EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);  // Fails
+```
+
+In the above example, the final assertion fails and the predicate-formatter
+produces the following failure message:
+
+```
+b and c (4 and 10) are not mutually prime, as they have a common divisor 2
+```
+
+## Windows HRESULT Assertions {#HRESULT}
+
+The following assertions test for `HRESULT` success or failure. For example:
+
+```cpp
+CComPtr<IShellDispatch2> shell;
+ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
+CComVariant empty;
+ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
+```
+
+The generated output contains the human-readable error message associated with
+the returned `HRESULT` code.
+
+### EXPECT_HRESULT_SUCCEEDED {#EXPECT_HRESULT_SUCCEEDED}
+
+`EXPECT_HRESULT_SUCCEEDED(`*`expression`*`)` \
+`ASSERT_HRESULT_SUCCEEDED(`*`expression`*`)`
+
+Verifies that *`expression`* is a success `HRESULT`.
+
+### EXPECT_HRESULT_FAILED {#EXPECT_HRESULT_FAILED}
+
+`EXPECT_HRESULT_FAILED(`*`expression`*`)` \
+`ASSERT_HRESULT_FAILED(`*`expression`*`)`
+
+Verifies that *`expression`* is a failure `HRESULT`.
+
+## Death Assertions {#death}
+
+The following assertions verify that a piece of code causes the process to
+terminate. For context, see [Death Tests](../advanced.md#death-tests).
+
+These assertions spawn a new process and execute the code under test in that
+process. How that happens depends on the platform and the variable
+`::testing::GTEST_FLAG(death_test_style)`, which is initialized from the
+command-line flag `--gtest_death_test_style`.
+
+*   On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the
+    child, after which:
+    *   If the variable's value is `"fast"`, the death test statement is
+        immediately executed.
+    *   If the variable's value is `"threadsafe"`, the child process re-executes
+        the unit test binary just as it was originally invoked, but with some
+        extra flags to cause just the single death test under consideration to
+        be run.
+*   On Windows, the child is spawned using the `CreateProcess()` API, and
+    re-executes the binary to cause just the single death test under
+    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"`**.
+
+If the death test statement runs to completion without dying, the child process
+will nonetheless terminate, and the assertion fails.
+
+Note that the piece of code under test can be a compound statement, for example:
+
+```cpp
+EXPECT_DEATH({
+  int n = 5;
+  DoSomething(&n);
+}, "Error on line .* of DoSomething()");
+```
+
+### EXPECT_DEATH {#EXPECT_DEATH}
+
+`EXPECT_DEATH(`*`statement`*`,`*`matcher`*`)` \
+`ASSERT_DEATH(`*`statement`*`,`*`matcher`*`)`
+
+Verifies that *`statement`* causes the process to terminate with a nonzero exit
+status and produces `stderr` output that matches *`matcher`*.
+
+The parameter *`matcher`* is either a [matcher](matchers.md) for a `const
+std::string&`, or a regular expression (see
+[Regular Expression Syntax](../advanced.md#regular-expression-syntax))—a bare
+string *`s`* (with no matcher) is treated as
+[`ContainsRegex(s)`](matchers.md#string-matchers), **not**
+[`Eq(s)`](matchers.md#generic-comparison).
+
+For example, the following code verifies that calling `DoSomething(42)` causes
+the process to die with an error message that contains the text `My error`:
+
+```cpp
+EXPECT_DEATH(DoSomething(42), "My error");
+```
+
+### EXPECT_DEATH_IF_SUPPORTED {#EXPECT_DEATH_IF_SUPPORTED}
+
+`EXPECT_DEATH_IF_SUPPORTED(`*`statement`*`,`*`matcher`*`)` \
+`ASSERT_DEATH_IF_SUPPORTED(`*`statement`*`,`*`matcher`*`)`
+
+If death tests are supported, behaves the same as
+[`EXPECT_DEATH`](#EXPECT_DEATH). Otherwise, verifies nothing.
+
+### EXPECT_DEBUG_DEATH {#EXPECT_DEBUG_DEATH}
+
+`EXPECT_DEBUG_DEATH(`*`statement`*`,`*`matcher`*`)` \
+`ASSERT_DEBUG_DEATH(`*`statement`*`,`*`matcher`*`)`
+
+In debug mode, behaves the same as [`EXPECT_DEATH`](#EXPECT_DEATH). When not in
+debug mode (i.e. `NDEBUG` is defined), just executes *`statement`*.
+
+### EXPECT_EXIT {#EXPECT_EXIT}
+
+`EXPECT_EXIT(`*`statement`*`,`*`predicate`*`,`*`matcher`*`)` \
+`ASSERT_EXIT(`*`statement`*`,`*`predicate`*`,`*`matcher`*`)`
+
+Verifies that *`statement`* causes the process to terminate with an exit status
+that satisfies *`predicate`*, and produces `stderr` output that matches
+*`matcher`*.
+
+The parameter *`predicate`* is a function or functor that accepts an `int` exit
+status and returns a `bool`. GoogleTest provides two predicates to handle common
+cases:
+
+```cpp
+// Returns true if the program exited normally with the given exit status code.
+::testing::ExitedWithCode(exit_code);
+
+// Returns true if the program was killed by the given signal.
+// Not available on Windows.
+::testing::KilledBySignal(signal_number);
+```
+
+The parameter *`matcher`* is either a [matcher](matchers.md) for a `const
+std::string&`, or a regular expression (see
+[Regular Expression Syntax](../advanced.md#regular-expression-syntax))—a bare
+string *`s`* (with no matcher) is treated as
+[`ContainsRegex(s)`](matchers.md#string-matchers), **not**
+[`Eq(s)`](matchers.md#generic-comparison).
+
+For example, the following code verifies that calling `NormalExit()` causes the
+process to print a message containing the text `Success` to `stderr` and exit
+with exit status code 0:
+
+```cpp
+EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success");
+```
diff --git a/3rd-party/googletest/docs/reference/matchers.md b/3rd-party/googletest/docs/reference/matchers.md
new file mode 100644
index 0000000..243e3f9
--- /dev/null
+++ b/3rd-party/googletest/docs/reference/matchers.md
@@ -0,0 +1,302 @@
+# Matchers Reference
+
+A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or
+`EXPECT_CALL()`, or use it to validate a value directly using two macros:
+
+| Macro                                | Description                           |
+| :----------------------------------- | :------------------------------------ |
+| `EXPECT_THAT(actual_value, matcher)` | Asserts that `actual_value` matches `matcher`. |
+| `ASSERT_THAT(actual_value, matcher)` | The same as `EXPECT_THAT(actual_value, matcher)`, except that it generates a **fatal** failure. |
+
+{: .callout .warning}
+**WARNING:** Equality matching via `EXPECT_THAT(actual_value, expected_value)`
+is supported, however note that implicit conversions can cause surprising
+results. For example, `EXPECT_THAT(some_bool, "some string")` will compile and
+may pass unintentionally.
+
+**BEST PRACTICE:** Prefer to make the comparison explicit via
+`EXPECT_THAT(actual_value, Eq(expected_value))` or `EXPECT_EQ(actual_value,
+expected_value)`.
+
+Built-in matchers (where `argument` is the function argument, e.g.
+`actual_value` in the example above, or when used in the context of
+`EXPECT_CALL(mock_object, method(matchers))`, the arguments of `method`) are
+divided into several categories. All matchers are defined in the `::testing`
+namespace unless otherwise noted.
+
+## Wildcard
+
+Matcher                     | Description
+:-------------------------- | :-----------------------------------------------
+`_`                         | `argument` can be any value of the correct type.
+`A<type>()` or `An<type>()` | `argument` can be any value of type `type`.
+
+## Generic Comparison
+
+| Matcher                | Description                                         |
+| :--------------------- | :-------------------------------------------------- |
+| `Eq(value)` or `value` | `argument == value`                                 |
+| `Ge(value)`            | `argument >= value`                                 |
+| `Gt(value)`            | `argument > value`                                  |
+| `Le(value)`            | `argument <= value`                                 |
+| `Lt(value)`            | `argument < value`                                  |
+| `Ne(value)`            | `argument != value`                                 |
+| `IsFalse()`            | `argument` evaluates to `false` in a Boolean context. |
+| `IsTrue()`             | `argument` evaluates to `true` in a Boolean context. |
+| `IsNull()`             | `argument` is a `NULL` pointer (raw or smart).      |
+| `NotNull()`            | `argument` is a non-null pointer (raw or smart).    |
+| `Optional(m)`          | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)|
+| `VariantWith<T>(m)`    | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. |
+| `Ref(variable)`        | `argument` is a reference to `variable`.            |
+| `TypedEq<type>(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. |
+
+Except `Ref()`, these matchers make a *copy* of `value` in case it's modified or
+destructed later. If the compiler complains that `value` doesn't have a public
+copy constructor, try wrap it in `std::ref()`, e.g.
+`Eq(std::ref(non_copyable_value))`. If you do that, make sure
+`non_copyable_value` is not changed afterwards, or the meaning of your matcher
+will be changed.
+
+`IsTrue` and `IsFalse` are useful when you need to use a matcher, or for types
+that can be explicitly converted to Boolean, but are not implicitly converted to
+Boolean. In other cases, you can use the basic
+[`EXPECT_TRUE` and `EXPECT_FALSE`](assertions.md#boolean) assertions.
+
+## Floating-Point Matchers {#FpMatchers}
+
+| Matcher                          | Description                        |
+| :------------------------------- | :--------------------------------- |
+| `DoubleEq(a_double)`             | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal. |
+| `FloatEq(a_float)`               | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. |
+| `NanSensitiveDoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. |
+| `NanSensitiveFloatEq(a_float)`   | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. |
+| `IsNan()`   | `argument` is any floating-point type with a NaN value. |
+
+The above matchers use ULP-based comparison (the same as used in googletest).
+They automatically pick a reasonable error bound based on the absolute value of
+the expected value. `DoubleEq()` and `FloatEq()` conform to the IEEE standard,
+which requires comparing two NaNs for equality to return false. The
+`NanSensitive*` version instead treats two NaNs as equal, which is often what a
+user wants.
+
+| Matcher                                           | Description              |
+| :------------------------------------------------ | :----------------------- |
+| `DoubleNear(a_double, max_abs_error)`             | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal. |
+| `FloatNear(a_float, max_abs_error)`               | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal. |
+| `NanSensitiveDoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal. |
+| `NanSensitiveFloatNear(a_float, max_abs_error)`   | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal. |
+
+## String Matchers
+
+The `argument` can be either a C string or a C++ string object:
+
+| Matcher                 | Description                                        |
+| :---------------------- | :------------------------------------------------- |
+| `ContainsRegex(string)`  | `argument` matches the given regular expression.  |
+| `EndsWith(suffix)`       | `argument` ends with string `suffix`.             |
+| `HasSubstr(string)`      | `argument` contains `string` as a sub-string.     |
+| `IsEmpty()`              | `argument` is an empty string.                    |
+| `MatchesRegex(string)`   | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. |
+| `StartsWith(prefix)`     | `argument` starts with string `prefix`.           |
+| `StrCaseEq(string)`      | `argument` is equal to `string`, ignoring case.   |
+| `StrCaseNe(string)`      | `argument` is not equal to `string`, ignoring case. |
+| `StrEq(string)`          | `argument` is equal to `string`.                  |
+| `StrNe(string)`          | `argument` is not equal to `string`.              |
+| `WhenBase64Unescaped(m)` | `argument` is a base-64 escaped string whose unescaped string matches `m`.  The web-safe format from [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648#section-5) is supported. |
+
+`ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They
+use the regular expression syntax defined
+[here](../advanced.md#regular-expression-syntax). All of these matchers, except
+`ContainsRegex()` and `MatchesRegex()` work for wide strings as well.
+
+## Container Matchers
+
+Most STL-style containers support `==`, so you can use `Eq(expected_container)`
+or simply `expected_container` to match a container exactly. If you want to
+write the elements in-line, match them more flexibly, or get more informative
+messages, you can use:
+
+| Matcher                                   | Description                      |
+| :---------------------------------------- | :------------------------------- |
+| `BeginEndDistanceIs(m)` | `argument` is a container whose `begin()` and `end()` iterators are separated by a number of increments matching `m`. E.g. `BeginEndDistanceIs(2)` or `BeginEndDistanceIs(Lt(2))`. For containers that define a `size()` method, `SizeIs(m)` may be more efficient. |
+| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
+| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. |
+| `Contains(e).Times(n)` | `argument` contains elements that match `e`, which can be either a value or a matcher, and the number of matches is `n`, which can be either a value or a matcher. Unlike the plain `Contains` and `Each` this allows to check for arbitrary occurrences including testing for absence with `Contains(e).Times(0)`. |
+| `Each(e)` | `argument` is a container where *every* element matches `e`, which can be either a value or a matcher. |
+| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the *i*-th element matches `ei`, which can be a value or a matcher. |
+| `ElementsAreArray({e0, e1, ..., en})`, `ElementsAreArray(a_container)`, `ElementsAreArray(begin, end)`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
+| `IsEmpty()` | `argument` is an empty container (`container.empty()`). |
+| `IsSubsetOf({e0, e1, ..., en})`, `IsSubsetOf(a_container)`, `IsSubsetOf(begin, end)`, `IsSubsetOf(array)`, or `IsSubsetOf(array, count)` | `argument` matches `UnorderedElementsAre(x0, x1, ..., xk)` for some subset `{x0, x1, ..., xk}` of the expected matchers. |
+| `IsSupersetOf({e0, e1, ..., en})`, `IsSupersetOf(a_container)`, `IsSupersetOf(begin, end)`, `IsSupersetOf(array)`, or `IsSupersetOf(array, count)` | Some subset of `argument` matches `UnorderedElementsAre(`expected matchers`)`. |
+| `Pointwise(m, container)`, `Pointwise(m, {e0, e1, ..., en})` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. |
+| `SizeIs(m)` | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`. |
+| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under *some* permutation of the elements, each element matches an `ei` (for a different `i`), which can be a value or a matcher. |
+| `UnorderedElementsAreArray({e0, e1, ..., en})`, `UnorderedElementsAreArray(a_container)`, `UnorderedElementsAreArray(begin, end)`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
+| `UnorderedPointwise(m, container)`, `UnorderedPointwise(m, {e0, e1, ..., en})` | Like `Pointwise(m, container)`, but ignores the order of elements. |
+| `WhenSorted(m)` | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(ElementsAre(1, 2, 3))` verifies that `argument` contains elements 1, 2, and 3, ignoring order. |
+| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater(), ElementsAre(3, 2, 1))`. |
+
+**Notes:**
+
+*   These matchers can also match:
+    1.  a native array passed by reference (e.g. in `Foo(const int (&a)[5])`),
+        and
+    2.  an array passed as a pointer and a count (e.g. in `Bar(const T* buffer,
+        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, ...)` 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
+    MATCHER(FooEq, "") {
+      return std::get<0>(arg).Equals(std::get<1>(arg));
+    }
+    ...
+    EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
+    ```
+
+## Member Matchers
+
+| Matcher                         | Description                                |
+| :------------------------------ | :----------------------------------------- |
+| `Field(&class::field, m)`       | `argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. |
+| `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 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.
+
+## Matching the Result of a Function, Functor, or Callback
+
+| Matcher          | Description                                       |
+| :--------------- | :------------------------------------------------ |
+| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. |
+| `ResultOf(result_description, f, m)` | The same as the two-parameter version, but provides a better error message.
+
+## Pointer Matchers
+
+| Matcher                   | Description                                     |
+| :------------------------ | :---------------------------------------------- |
+| `Address(m)`              | the result of `std::addressof(argument)` matches `m`. |
+| `Pointee(m)`              | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. |
+| `Pointer(m)`              | `argument` (either a smart pointer or a raw pointer) contains a pointer that matches `m`. `m` will match against the raw pointer regardless of the type of `argument`. |
+| `WhenDynamicCastTo<T>(m)` | when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`. |
+
+## Multi-argument Matchers {#MultiArgMatchers}
+
+Technically, all matchers match a *single* value. A "multi-argument" matcher is
+just one that matches a *tuple*. The following matchers can be used to match a
+tuple `(x, y)`:
+
+Matcher | Description
+:------ | :----------
+`Eq()`  | `x == y`
+`Ge()`  | `x >= y`
+`Gt()`  | `x > y`
+`Le()`  | `x <= y`
+`Lt()`  | `x < y`
+`Ne()`  | `x != y`
+
+You can use the following selectors to pick a subset of the arguments (or
+reorder them) to participate in the matching:
+
+| Matcher                    | Description                                     |
+| :------------------------- | :---------------------------------------------- |
+| `AllArgs(m)`               | Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`. |
+| `Args<N1, N2, ..., Nk>(m)` | The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`. |
+
+## Composite Matchers
+
+You can make a matcher from one or more other matchers:
+
+| Matcher                          | Description                             |
+| :------------------------------- | :-------------------------------------- |
+| `AllOf(m1, m2, ..., mn)` | `argument` matches all of the matchers `m1` to `mn`. |
+| `AllOfArray({m0, m1, ..., mn})`, `AllOfArray(a_container)`, `AllOfArray(begin, end)`, `AllOfArray(array)`, or `AllOfArray(array, count)` | The same as `AllOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
+| `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. |
+| `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
+| `Not(m)` | `argument` doesn't match matcher `m`. |
+| `Conditional(cond, m1, m2)` | Matches matcher `m1` if `cond` evaluates to true, else matches `m2`.|
+
+## Adapters for Matchers
+
+| Matcher                 | Description                           |
+| :---------------------- | :------------------------------------ |
+| `MatcherCast<T>(m)`     | casts matcher `m` to type `Matcher<T>`. |
+| `SafeMatcherCast<T>(m)` | [safely casts](../gmock_cook_book.md#SafeMatcherCast) matcher `m` to type `Matcher<T>`. |
+| `Truly(predicate)`      | `predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor. |
+
+`AddressSatisfies(callback)` and `Truly(callback)` take ownership of `callback`,
+which must be a permanent callback.
+
+## Using Matchers as Predicates {#MatchersAsPredicatesCheat}
+
+| Matcher                       | Description                                 |
+| :---------------------------- | :------------------------------------------ |
+| `Matches(m)(value)` | evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor. |
+| `ExplainMatchResult(m, value, result_listener)` | evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`. |
+| `Value(value, m)` | evaluates to `true` if `value` matches `m`. |
+
+## Defining Matchers
+
+| Macro                                | Description                           |
+| :----------------------------------- | :------------------------------------ |
+| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
+| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a matcher `IsDivisibleBy(n)` to match a number divisible by `n`. |
+| `MATCHER_P2(IsBetween, a, b, absl::StrCat(negation ? "isn't" : "is", " between ", PrintToString(a), " and ", PrintToString(b))) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
+
+**Notes:**
+
+1.  The `MATCHER*` macros cannot be used inside a function or class.
+2.  The matcher body must be *purely functional* (i.e. it cannot have any side
+    effect, and the result must not depend on anything other than the value
+    being matched and the matcher parameters).
+3.  You can use `PrintToString(x)` to convert a value `x` of any type to a
+    string.
+4.  You can use `ExplainMatchResult()` in a custom matcher to wrap another
+    matcher, for example:
+
+    ```cpp
+    MATCHER_P(NestedPropertyMatches, matcher, "") {
+      return ExplainMatchResult(matcher, arg.nested().property(), result_listener);
+    }
+    ```
+
+5.  You can use `DescribeMatcher<>` to describe another matcher. For example:
+
+    ```cpp
+    MATCHER_P(XAndYThat, matcher,
+              "X that " + DescribeMatcher<int>(matcher, negation) +
+                  (negation ? " or" : " and") + " Y that " +
+                  DescribeMatcher<double>(matcher, negation)) {
+      return ExplainMatchResult(matcher, arg.x(), result_listener) &&
+             ExplainMatchResult(matcher, arg.y(), result_listener);
+    }
+    ```
diff --git a/3rd-party/googletest/docs/reference/mocking.md b/3rd-party/googletest/docs/reference/mocking.md
new file mode 100644
index 0000000..ab37ebf
--- /dev/null
+++ b/3rd-party/googletest/docs/reference/mocking.md
@@ -0,0 +1,588 @@
+# Mocking Reference
+
+This page lists the facilities provided by GoogleTest for creating and working
+with mock objects. To use them, add `#include <gmock/gmock.h>`.
+
+## Macros {#macros}
+
+GoogleTest defines the following macros for working with mocks.
+
+### MOCK_METHOD {#MOCK_METHOD}
+
+`MOCK_METHOD(`*`return_type`*`,`*`method_name`*`, (`*`args...`*`));` \
+`MOCK_METHOD(`*`return_type`*`,`*`method_name`*`, (`*`args...`*`),
+(`*`specs...`*`));`
+
+Defines a mock method *`method_name`* with arguments `(`*`args...`*`)` and
+return type *`return_type`* within a mock class.
+
+The parameters of `MOCK_METHOD` mirror the method declaration. The optional
+fourth parameter *`specs...`* is a comma-separated list of qualifiers. The
+following qualifiers are accepted:
+
+| Qualifier                  | Meaning                                      |
+| -------------------------- | -------------------------------------------- |
+| `const`                    | Makes the mocked method a `const` method. Required if overriding a `const` method. |
+| `override`                 | Marks the method with `override`. Recommended if overriding a `virtual` method. |
+| `noexcept`                 | Marks the method with `noexcept`. Required if overriding a `noexcept` method. |
+| `Calltype(`*`calltype`*`)` | Sets the call type for the method, for example `Calltype(STDMETHODCALLTYPE)`. Useful on Windows. |
+| `ref(`*`qualifier`*`)`     | Marks the method with the given reference qualifier, for example `ref(&)` or `ref(&&)`. Required if overriding a method that has a reference qualifier. |
+
+Note that commas in arguments prevent `MOCK_METHOD` from parsing the arguments
+correctly if they are not appropriately surrounded by parentheses. See the
+following example:
+
+```cpp
+class MyMock {
+ public:
+  // The following 2 lines will not compile due to commas in the arguments:
+  MOCK_METHOD(std::pair<bool, int>, GetPair, ());              // Error!
+  MOCK_METHOD(bool, CheckMap, (std::map<int, double>, bool));  // Error!
+
+  // One solution - wrap arguments that contain commas in parentheses:
+  MOCK_METHOD((std::pair<bool, int>), GetPair, ());
+  MOCK_METHOD(bool, CheckMap, ((std::map<int, double>), bool));
+
+  // Another solution - use type aliases:
+  using BoolAndInt = std::pair<bool, int>;
+  MOCK_METHOD(BoolAndInt, GetPair, ());
+  using MapIntDouble = std::map<int, double>;
+  MOCK_METHOD(bool, CheckMap, (MapIntDouble, bool));
+};
+```
+
+`MOCK_METHOD` must be used in the `public:` section of a mock class definition,
+regardless of whether the method being mocked is `public`, `protected`, or
+`private` in the base class.
+
+### EXPECT_CALL {#EXPECT_CALL}
+
+`EXPECT_CALL(`*`mock_object`*`,`*`method_name`*`(`*`matchers...`*`))`
+
+Creates an [expectation](../gmock_for_dummies.md#setting-expectations) that the
+method *`method_name`* of the object *`mock_object`* is called with arguments
+that match the given matchers *`matchers...`*. `EXPECT_CALL` must precede any
+code that exercises the mock object.
+
+The parameter *`matchers...`* is a comma-separated list of
+[matchers](../gmock_for_dummies.md#matchers-what-arguments-do-we-expect) that
+correspond to each argument of the method *`method_name`*. The expectation will
+apply only to calls of *`method_name`* whose arguments match all of the
+matchers. If `(`*`matchers...`*`)` is omitted, the expectation behaves as if
+each argument's matcher were a [wildcard matcher (`_`)](matchers.md#wildcard).
+See the [Matchers Reference](matchers.md) for a list of all built-in matchers.
+
+The following chainable clauses can be used to modify the expectation, and they
+must be used in the following order:
+
+```cpp
+EXPECT_CALL(mock_object, method_name(matchers...))
+    .With(multi_argument_matcher)  // Can be used at most once
+    .Times(cardinality)            // Can be used at most once
+    .InSequence(sequences...)      // Can be used any number of times
+    .After(expectations...)        // Can be used any number of times
+    .WillOnce(action)              // Can be used any number of times
+    .WillRepeatedly(action)        // Can be used at most once
+    .RetiresOnSaturation();        // Can be used at most once
+```
+
+See details for each modifier clause below.
+
+#### With {#EXPECT_CALL.With}
+
+`.With(`*`multi_argument_matcher`*`)`
+
+Restricts the expectation to apply only to mock function calls whose arguments
+as a whole match the multi-argument matcher *`multi_argument_matcher`*.
+
+GoogleTest passes all of the arguments as one tuple into the matcher. The
+parameter *`multi_argument_matcher`* must thus be a matcher of type
+`Matcher<std::tuple<A1, ..., An>>`, where `A1, ..., An` are the types of the
+function arguments.
+
+For example, the following code sets the expectation that
+`my_mock.SetPosition()` is called with any two arguments, the first argument
+being less than the second:
+
+```cpp
+using ::testing::_;
+using ::testing::Lt;
+...
+EXPECT_CALL(my_mock, SetPosition(_, _))
+    .With(Lt());
+```
+
+GoogleTest provides some built-in matchers for 2-tuples, including the `Lt()`
+matcher above. See [Multi-argument Matchers](matchers.md#MultiArgMatchers).
+
+The `With` clause can be used at most once on an expectation and must be the
+first clause.
+
+#### Times {#EXPECT_CALL.Times}
+
+`.Times(`*`cardinality`*`)`
+
+Specifies how many times the mock function call is expected.
+
+The parameter *`cardinality`* represents the number of expected calls and can be
+one of the following, all defined in the `::testing` namespace:
+
+| Cardinality         | Meaning                                             |
+| ------------------- | --------------------------------------------------- |
+| `AnyNumber()`       | The function can be called any number of times.     |
+| `AtLeast(n)`        | The function call is expected at least *n* times.   |
+| `AtMost(n)`         | The function call is expected at most *n* times.    |
+| `Between(m, n)`     | The function call is expected between *m* and *n* times, inclusive. |
+| `Exactly(n)` or `n` | The function call is expected exactly *n* times. If *n* is 0, the call should never happen. |
+
+If the `Times` clause is omitted, GoogleTest infers the cardinality as follows:
+
+*   If neither [`WillOnce`](#EXPECT_CALL.WillOnce) nor
+    [`WillRepeatedly`](#EXPECT_CALL.WillRepeatedly) are specified, the inferred
+    cardinality is `Times(1)`.
+*   If there are *n* `WillOnce` clauses and no `WillRepeatedly` clause, where
+    *n* >= 1, the inferred cardinality is `Times(n)`.
+*   If there are *n* `WillOnce` clauses and one `WillRepeatedly` clause, where
+    *n* >= 0, the inferred cardinality is `Times(AtLeast(n))`.
+
+The `Times` clause can be used at most once on an expectation.
+
+#### InSequence {#EXPECT_CALL.InSequence}
+
+`.InSequence(`*`sequences...`*`)`
+
+Specifies that the mock function call is expected in a certain sequence.
+
+The parameter *`sequences...`* is any number of [`Sequence`](#Sequence) objects.
+Expected calls assigned to the same sequence are expected to occur in the order
+the expectations are declared.
+
+For example, the following code sets the expectation that the `Reset()` method
+of `my_mock` is called before both `GetSize()` and `Describe()`, and `GetSize()`
+and `Describe()` can occur in any order relative to each other:
+
+```cpp
+using ::testing::Sequence;
+Sequence s1, s2;
+...
+EXPECT_CALL(my_mock, Reset())
+    .InSequence(s1, s2);
+EXPECT_CALL(my_mock, GetSize())
+    .InSequence(s1);
+EXPECT_CALL(my_mock, Describe())
+    .InSequence(s2);
+```
+
+The `InSequence` clause can be used any number of times on an expectation.
+
+See also the [`InSequence` class](#InSequence).
+
+#### After {#EXPECT_CALL.After}
+
+`.After(`*`expectations...`*`)`
+
+Specifies that the mock function call is expected to occur after one or more
+other calls.
+
+The parameter *`expectations...`* can be up to five
+[`Expectation`](#Expectation) or [`ExpectationSet`](#ExpectationSet) objects.
+The mock function call is expected to occur after all of the given expectations.
+
+For example, the following code sets the expectation that the `Describe()`
+method of `my_mock` is called only after both `InitX()` and `InitY()` have been
+called.
+
+```cpp
+using ::testing::Expectation;
+...
+Expectation init_x = EXPECT_CALL(my_mock, InitX());
+Expectation init_y = EXPECT_CALL(my_mock, InitY());
+EXPECT_CALL(my_mock, Describe())
+    .After(init_x, init_y);
+```
+
+The `ExpectationSet` object is helpful when the number of prerequisites for an
+expectation is large or variable, for example:
+
+```cpp
+using ::testing::ExpectationSet;
+...
+ExpectationSet all_inits;
+// Collect all expectations of InitElement() calls
+for (int i = 0; i < element_count; i++) {
+  all_inits += EXPECT_CALL(my_mock, InitElement(i));
+}
+EXPECT_CALL(my_mock, Describe())
+    .After(all_inits);  // Expect Describe() call after all InitElement() calls
+```
+
+The `After` clause can be used any number of times on an expectation.
+
+#### WillOnce {#EXPECT_CALL.WillOnce}
+
+`.WillOnce(`*`action`*`)`
+
+Specifies the mock function's actual behavior when invoked, for a single
+matching function call.
+
+The parameter *`action`* represents the
+[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function
+call will perform. See the [Actions Reference](actions.md) for a list of
+built-in actions.
+
+The use of `WillOnce` implicitly sets a cardinality on the expectation when
+`Times` is not specified. See [`Times`](#EXPECT_CALL.Times).
+
+Each matching function call will perform the next action in the order declared.
+For example, the following code specifies that `my_mock.GetNumber()` is expected
+to be called exactly 3 times and will return `1`, `2`, and `3` respectively on
+the first, second, and third calls:
+
+```cpp
+using ::testing::Return;
+...
+EXPECT_CALL(my_mock, GetNumber())
+    .WillOnce(Return(1))
+    .WillOnce(Return(2))
+    .WillOnce(Return(3));
+```
+
+The `WillOnce` clause can be used any number of times on an expectation. Unlike
+`WillRepeatedly`, the action fed to each `WillOnce` call will be called at most
+once, so may be a move-only type and/or have an `&&`-qualified call operator.
+
+#### WillRepeatedly {#EXPECT_CALL.WillRepeatedly}
+
+`.WillRepeatedly(`*`action`*`)`
+
+Specifies the mock function's actual behavior when invoked, for all subsequent
+matching function calls. Takes effect after the actions specified in the
+[`WillOnce`](#EXPECT_CALL.WillOnce) clauses, if any, have been performed.
+
+The parameter *`action`* represents the
+[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function
+call will perform. See the [Actions Reference](actions.md) for a list of
+built-in actions.
+
+The use of `WillRepeatedly` implicitly sets a cardinality on the expectation
+when `Times` is not specified. See [`Times`](#EXPECT_CALL.Times).
+
+If any `WillOnce` clauses have been specified, matching function calls will
+perform those actions before the action specified by `WillRepeatedly`. See the
+following example:
+
+```cpp
+using ::testing::Return;
+...
+EXPECT_CALL(my_mock, GetName())
+    .WillRepeatedly(Return("John Doe"));  // Return "John Doe" on all calls
+
+EXPECT_CALL(my_mock, GetNumber())
+    .WillOnce(Return(42))        // Return 42 on the first call
+    .WillRepeatedly(Return(7));  // Return 7 on all subsequent calls
+```
+
+The `WillRepeatedly` clause can be used at most once on an expectation.
+
+#### RetiresOnSaturation {#EXPECT_CALL.RetiresOnSaturation}
+
+`.RetiresOnSaturation()`
+
+Indicates that the expectation will no longer be active after the expected
+number of matching function calls has been reached.
+
+The `RetiresOnSaturation` clause is only meaningful for expectations with an
+upper-bounded cardinality. The expectation will *retire* (no longer match any
+function calls) after it has been *saturated* (the upper bound has been
+reached). See the following example:
+
+```cpp
+using ::testing::_;
+using ::testing::AnyNumber;
+...
+EXPECT_CALL(my_mock, SetNumber(_))  // Expectation 1
+    .Times(AnyNumber());
+EXPECT_CALL(my_mock, SetNumber(7))  // Expectation 2
+    .Times(2)
+    .RetiresOnSaturation();
+```
+
+In the above example, the first two calls to `my_mock.SetNumber(7)` match
+expectation 2, which then becomes inactive and no longer matches any calls. A
+third call to `my_mock.SetNumber(7)` would then match expectation 1. Without
+`RetiresOnSaturation()` on expectation 2, a third call to `my_mock.SetNumber(7)`
+would match expectation 2 again, producing a failure since the limit of 2 calls
+was exceeded.
+
+The `RetiresOnSaturation` clause can be used at most once on an expectation and
+must be the last clause.
+
+### ON_CALL {#ON_CALL}
+
+`ON_CALL(`*`mock_object`*`,`*`method_name`*`(`*`matchers...`*`))`
+
+Defines what happens when the method *`method_name`* of the object
+*`mock_object`* is called with arguments that match the given matchers
+*`matchers...`*. Requires a modifier clause to specify the method's behavior.
+*Does not* set any expectations that the method will be called.
+
+The parameter *`matchers...`* is a comma-separated list of
+[matchers](../gmock_for_dummies.md#matchers-what-arguments-do-we-expect) that
+correspond to each argument of the method *`method_name`*. The `ON_CALL`
+specification will apply only to calls of *`method_name`* whose arguments match
+all of the matchers. If `(`*`matchers...`*`)` is omitted, the behavior is as if
+each argument's matcher were a [wildcard matcher (`_`)](matchers.md#wildcard).
+See the [Matchers Reference](matchers.md) for a list of all built-in matchers.
+
+The following chainable clauses can be used to set the method's behavior, and
+they must be used in the following order:
+
+```cpp
+ON_CALL(mock_object, method_name(matchers...))
+    .With(multi_argument_matcher)  // Can be used at most once
+    .WillByDefault(action);        // Required
+```
+
+See details for each modifier clause below.
+
+#### With {#ON_CALL.With}
+
+`.With(`*`multi_argument_matcher`*`)`
+
+Restricts the specification to only mock function calls whose arguments as a
+whole match the multi-argument matcher *`multi_argument_matcher`*.
+
+GoogleTest passes all of the arguments as one tuple into the matcher. The
+parameter *`multi_argument_matcher`* must thus be a matcher of type
+`Matcher<std::tuple<A1, ..., An>>`, where `A1, ..., An` are the types of the
+function arguments.
+
+For example, the following code sets the default behavior when
+`my_mock.SetPosition()` is called with any two arguments, the first argument
+being less than the second:
+
+```cpp
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Return;
+...
+ON_CALL(my_mock, SetPosition(_, _))
+    .With(Lt())
+    .WillByDefault(Return(true));
+```
+
+GoogleTest provides some built-in matchers for 2-tuples, including the `Lt()`
+matcher above. See [Multi-argument Matchers](matchers.md#MultiArgMatchers).
+
+The `With` clause can be used at most once with each `ON_CALL` statement.
+
+#### WillByDefault {#ON_CALL.WillByDefault}
+
+`.WillByDefault(`*`action`*`)`
+
+Specifies the default behavior of a matching mock function call.
+
+The parameter *`action`* represents the
+[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function
+call will perform. See the [Actions Reference](actions.md) for a list of
+built-in actions.
+
+For example, the following code specifies that by default, a call to
+`my_mock.Greet()` will return `"hello"`:
+
+```cpp
+using ::testing::Return;
+...
+ON_CALL(my_mock, Greet())
+    .WillByDefault(Return("hello"));
+```
+
+The action specified by `WillByDefault` is superseded by the actions specified
+on a matching `EXPECT_CALL` statement, if any. See the
+[`WillOnce`](#EXPECT_CALL.WillOnce) and
+[`WillRepeatedly`](#EXPECT_CALL.WillRepeatedly) clauses of `EXPECT_CALL`.
+
+The `WillByDefault` clause must be used exactly once with each `ON_CALL`
+statement.
+
+## Classes {#classes}
+
+GoogleTest defines the following classes for working with mocks.
+
+### DefaultValue {#DefaultValue}
+
+`::testing::DefaultValue<T>`
+
+Allows a user to specify the default value for a type `T` that is both copyable
+and publicly destructible (i.e. anything that can be used as a function return
+type). For mock functions with a return type of `T`, this default value is
+returned from function calls that do not specify an action.
+
+Provides the static methods `Set()`, `SetFactory()`, and `Clear()` to manage the
+default value:
+
+```cpp
+// Sets the default value to be returned. T must be copy constructible.
+DefaultValue<T>::Set(value);
+
+// Sets a factory. Will be invoked on demand. T must be move constructible.
+T MakeT();
+DefaultValue<T>::SetFactory(&MakeT);
+
+// Unsets the default value.
+DefaultValue<T>::Clear();
+```
+
+### NiceMock {#NiceMock}
+
+`::testing::NiceMock<T>`
+
+Represents a mock object that suppresses warnings on
+[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The
+template parameter `T` is any mock class, except for another `NiceMock`,
+`NaggyMock`, or `StrictMock`.
+
+Usage of `NiceMock<T>` is analogous to usage of `T`. `NiceMock<T>` is a subclass
+of `T`, so it can be used wherever an object of type `T` is accepted. In
+addition, `NiceMock<T>` can be constructed with any arguments that a constructor
+of `T` accepts.
+
+For example, the following code suppresses warnings on the mock `my_mock` of
+type `MockClass` if a method other than `DoSomething()` is called:
+
+```cpp
+using ::testing::NiceMock;
+...
+NiceMock<MockClass> my_mock("some", "args");
+EXPECT_CALL(my_mock, DoSomething());
+... code that uses my_mock ...
+```
+
+`NiceMock<T>` only works for mock methods defined using the `MOCK_METHOD` macro
+directly in the definition of class `T`. If a mock method is defined in a base
+class of `T`, a warning might still be generated.
+
+`NiceMock<T>` might not work correctly if the destructor of `T` is not virtual.
+
+### NaggyMock {#NaggyMock}
+
+`::testing::NaggyMock<T>`
+
+Represents a mock object that generates warnings on
+[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The
+template parameter `T` is any mock class, except for another `NiceMock`,
+`NaggyMock`, or `StrictMock`.
+
+Usage of `NaggyMock<T>` is analogous to usage of `T`. `NaggyMock<T>` is a
+subclass of `T`, so it can be used wherever an object of type `T` is accepted.
+In addition, `NaggyMock<T>` can be constructed with any arguments that a
+constructor of `T` accepts.
+
+For example, the following code generates warnings on the mock `my_mock` of type
+`MockClass` if a method other than `DoSomething()` is called:
+
+```cpp
+using ::testing::NaggyMock;
+...
+NaggyMock<MockClass> my_mock("some", "args");
+EXPECT_CALL(my_mock, DoSomething());
+... code that uses my_mock ...
+```
+
+Mock objects of type `T` by default behave the same way as `NaggyMock<T>`.
+
+### StrictMock {#StrictMock}
+
+`::testing::StrictMock<T>`
+
+Represents a mock object that generates test failures on
+[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The
+template parameter `T` is any mock class, except for another `NiceMock`,
+`NaggyMock`, or `StrictMock`.
+
+Usage of `StrictMock<T>` is analogous to usage of `T`. `StrictMock<T>` is a
+subclass of `T`, so it can be used wherever an object of type `T` is accepted.
+In addition, `StrictMock<T>` can be constructed with any arguments that a
+constructor of `T` accepts.
+
+For example, the following code generates a test failure on the mock `my_mock`
+of type `MockClass` if a method other than `DoSomething()` is called:
+
+```cpp
+using ::testing::StrictMock;
+...
+StrictMock<MockClass> my_mock("some", "args");
+EXPECT_CALL(my_mock, DoSomething());
+... code that uses my_mock ...
+```
+
+`StrictMock<T>` only works for mock methods defined using the `MOCK_METHOD`
+macro directly in the definition of class `T`. If a mock method is defined in a
+base class of `T`, a failure might not be generated.
+
+`StrictMock<T>` might not work correctly if the destructor of `T` is not
+virtual.
+
+### Sequence {#Sequence}
+
+`::testing::Sequence`
+
+Represents a chronological sequence of expectations. See the
+[`InSequence`](#EXPECT_CALL.InSequence) clause of `EXPECT_CALL` for usage.
+
+### InSequence {#InSequence}
+
+`::testing::InSequence`
+
+An object of this type causes all expectations encountered in its scope to be
+put in an anonymous sequence.
+
+This allows more convenient expression of multiple expectations in a single
+sequence:
+
+```cpp
+using ::testing::InSequence;
+{
+  InSequence seq;
+
+  // The following are expected to occur in the order declared.
+  EXPECT_CALL(...);
+  EXPECT_CALL(...);
+  ...
+  EXPECT_CALL(...);
+}
+```
+
+The name of the `InSequence` object does not matter.
+
+### Expectation {#Expectation}
+
+`::testing::Expectation`
+
+Represents a mock function call expectation as created by
+[`EXPECT_CALL`](#EXPECT_CALL):
+
+```cpp
+using ::testing::Expectation;
+Expectation my_expectation = EXPECT_CALL(...);
+```
+
+Useful for specifying sequences of expectations; see the
+[`After`](#EXPECT_CALL.After) clause of `EXPECT_CALL`.
+
+### ExpectationSet {#ExpectationSet}
+
+`::testing::ExpectationSet`
+
+Represents a set of mock function call expectations.
+
+Use the `+=` operator to add [`Expectation`](#Expectation) objects to the set:
+
+```cpp
+using ::testing::ExpectationSet;
+ExpectationSet my_expectations;
+my_expectations += EXPECT_CALL(...);
+```
+
+Useful for specifying sequences of expectations; see the
+[`After`](#EXPECT_CALL.After) clause of `EXPECT_CALL`.
diff --git a/3rd-party/googletest/docs/reference/testing.md b/3rd-party/googletest/docs/reference/testing.md
new file mode 100644
index 0000000..3ed5211
--- /dev/null
+++ b/3rd-party/googletest/docs/reference/testing.md
@@ -0,0 +1,1453 @@
+# Testing Reference
+
+<!--* toc_depth: 3 *-->
+
+This page lists the facilities provided by GoogleTest for writing test programs.
+To use them, add `#include <gtest/gtest.h>`.
+
+## Macros
+
+GoogleTest defines the following macros for writing tests.
+
+### TEST {#TEST}
+
+<pre>
+TEST(<em>TestSuiteName</em>, <em>TestName</em>) {
+  ... <em>statements</em> ...
+}
+</pre>
+
+Defines an individual test named *`TestName`* in the test suite
+*`TestSuiteName`*, consisting of the given statements.
+
+Both arguments *`TestSuiteName`* and *`TestName`* must be valid C++ identifiers
+and must not contain underscores (`_`). Tests in different test suites can have
+the same individual name.
+
+The statements within the test body can be any code under test.
+[Assertions](assertions.md) used within the test body determine the outcome of
+the test.
+
+### TEST_F {#TEST_F}
+
+<pre>
+TEST_F(<em>TestFixtureName</em>, <em>TestName</em>) {
+  ... <em>statements</em> ...
+}
+</pre>
+
+Defines an individual test named *`TestName`* that uses the test fixture class
+*`TestFixtureName`*. The test suite name is *`TestFixtureName`*.
+
+Both arguments *`TestFixtureName`* and *`TestName`* must be valid C++
+identifiers and must not contain underscores (`_`). *`TestFixtureName`* must be
+the name of a test fixture class—see
+[Test Fixtures](../primer.md#same-data-multiple-tests).
+
+The statements within the test body can be any code under test.
+[Assertions](assertions.md) used within the test body determine the outcome of
+the test.
+
+### TEST_P {#TEST_P}
+
+<pre>
+TEST_P(<em>TestFixtureName</em>, <em>TestName</em>) {
+  ... <em>statements</em> ...
+}
+</pre>
+
+Defines an individual value-parameterized test named *`TestName`* that uses the
+test fixture class *`TestFixtureName`*. The test suite name is
+*`TestFixtureName`*.
+
+Both arguments *`TestFixtureName`* and *`TestName`* must be valid C++
+identifiers and must not contain underscores (`_`). *`TestFixtureName`* must be
+the name of a value-parameterized test fixture class—see
+[Value-Parameterized Tests](../advanced.md#value-parameterized-tests).
+
+The statements within the test body can be any code under test. Within the test
+body, the test parameter can be accessed with the `GetParam()` function (see
+[`WithParamInterface`](#WithParamInterface)). For example:
+
+```cpp
+TEST_P(MyTestSuite, DoesSomething) {
+  ...
+  EXPECT_TRUE(DoSomething(GetParam()));
+  ...
+}
+```
+
+[Assertions](assertions.md) used within the test body determine the outcome of
+the test.
+
+See also [`INSTANTIATE_TEST_SUITE_P`](#INSTANTIATE_TEST_SUITE_P).
+
+### INSTANTIATE_TEST_SUITE_P {#INSTANTIATE_TEST_SUITE_P}
+
+`INSTANTIATE_TEST_SUITE_P(`*`InstantiationName`*`,`*`TestSuiteName`*`,`*`param_generator`*`)`
+\
+`INSTANTIATE_TEST_SUITE_P(`*`InstantiationName`*`,`*`TestSuiteName`*`,`*`param_generator`*`,`*`name_generator`*`)`
+
+Instantiates the value-parameterized test suite *`TestSuiteName`* (defined with
+[`TEST_P`](#TEST_P)).
+
+The argument *`InstantiationName`* is a unique name for the instantiation of the
+test suite, to distinguish between multiple instantiations. In test output, the
+instantiation name is added as a prefix to the test suite name
+*`TestSuiteName`*. If *`InstantiationName`* is empty
+(`INSTANTIATE_TEST_SUITE_P(, ...)`), no prefix is added.
+
+The argument *`param_generator`* is one of the following GoogleTest-provided
+functions that generate the test parameters, all defined in the `::testing`
+namespace:
+
+<span id="param-generators"></span>
+
+| Parameter Generator | Behavior                                             |
+| ------------------- | ---------------------------------------------------- |
+| `Range(begin, end [, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. |
+| `Values(v1, v2, ..., vN)`    | Yields values `{v1, v2, ..., vN}`.          |
+| `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. |
+| `Bool()`                     | Yields sequence `{false, true}`.            |
+| `Combine(g1, g2, ..., gN)`   | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. |
+| `ConvertGenerator<T>(g)`     | Yields values generated by generator `g`, `static_cast` to `T`. |
+
+The optional last argument *`name_generator`* is a function or functor that
+generates custom test name suffixes based on the test parameters. The function
+must accept an argument of type
+[`TestParamInfo<class ParamType>`](#TestParamInfo) and return a `std::string`.
+The test name suffix can only contain alphanumeric characters and underscores.
+GoogleTest provides [`PrintToStringParamName`](#PrintToStringParamName), or a
+custom function can be used for more control:
+
+```cpp
+INSTANTIATE_TEST_SUITE_P(
+    MyInstantiation, MyTestSuite,
+    testing::Values(...),
+    [](const testing::TestParamInfo<MyTestSuite::ParamType>& info) {
+      // Can use info.param here to generate the test suffix
+      std::string name = ...
+      return name;
+    });
+```
+
+For more information, see
+[Value-Parameterized Tests](../advanced.md#value-parameterized-tests).
+
+See also
+[`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST).
+
+### TYPED_TEST_SUITE {#TYPED_TEST_SUITE}
+
+`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)`
+`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`,`*`NameGenerator`*`)`
+
+Defines a typed test suite based on the test fixture *`TestFixtureName`*. The
+test suite name is *`TestFixtureName`*.
+
+The argument *`TestFixtureName`* is a fixture class template, parameterized by a
+type, for example:
+
+```cpp
+template <typename T>
+class MyFixture : public testing::Test {
+ public:
+  ...
+  using List = std::list<T>;
+  static T shared_;
+  T value_;
+};
+```
+
+The argument *`Types`* is a [`Types`](#Types) object representing the list of
+types to run the tests on, for example:
+
+```cpp
+using MyTypes = ::testing::Types<char, int, unsigned int>;
+TYPED_TEST_SUITE(MyFixture, MyTypes);
+```
+
+The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE`
+macro to parse correctly.
+
+The optional third argument *`NameGenerator`* allows specifying a class that
+exposes a templated static function `GetName(int)`. For example:
+
+```cpp
+class NameGenerator {
+ public:
+  template <typename T>
+  static std::string GetName(int) {
+    if constexpr (std::is_same_v<T, char>) return "char";
+    if constexpr (std::is_same_v<T, int>) return "int";
+    if constexpr (std::is_same_v<T, unsigned int>) return "unsignedInt";
+  }
+};
+TYPED_TEST_SUITE(MyFixture, MyTypes, NameGenerator);
+```
+
+See also [`TYPED_TEST`](#TYPED_TEST) and
+[Typed Tests](../advanced.md#typed-tests) for more information.
+
+### TYPED_TEST {#TYPED_TEST}
+
+<pre>
+TYPED_TEST(<em>TestSuiteName</em>, <em>TestName</em>) {
+  ... <em>statements</em> ...
+}
+</pre>
+
+Defines an individual typed test named *`TestName`* in the typed test suite
+*`TestSuiteName`*. The test suite must be defined with
+[`TYPED_TEST_SUITE`](#TYPED_TEST_SUITE).
+
+Within the test body, the special name `TypeParam` refers to the type parameter,
+and `TestFixture` refers to the fixture class. See the following example:
+
+```cpp
+TYPED_TEST(MyFixture, Example) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of MyFixture via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the 'TestFixture::'
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+  // prefix. The 'typename' is required to satisfy the compiler.
+  typename TestFixture::List values;
+
+  values.push_back(n);
+  ...
+}
+```
+
+For more information, see [Typed Tests](../advanced.md#typed-tests).
+
+### TYPED_TEST_SUITE_P {#TYPED_TEST_SUITE_P}
+
+`TYPED_TEST_SUITE_P(`*`TestFixtureName`*`)`
+
+Defines a type-parameterized test suite based on the test fixture
+*`TestFixtureName`*. The test suite name is *`TestFixtureName`*.
+
+The argument *`TestFixtureName`* is a fixture class template, parameterized by a
+type. See [`TYPED_TEST_SUITE`](#TYPED_TEST_SUITE) for an example.
+
+See also [`TYPED_TEST_P`](#TYPED_TEST_P) and
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more
+information.
+
+### TYPED_TEST_P {#TYPED_TEST_P}
+
+<pre>
+TYPED_TEST_P(<em>TestSuiteName</em>, <em>TestName</em>) {
+  ... <em>statements</em> ...
+}
+</pre>
+
+Defines an individual type-parameterized test named *`TestName`* in the
+type-parameterized test suite *`TestSuiteName`*. The test suite must be defined
+with [`TYPED_TEST_SUITE_P`](#TYPED_TEST_SUITE_P).
+
+Within the test body, the special name `TypeParam` refers to the type parameter,
+and `TestFixture` refers to the fixture class. See [`TYPED_TEST`](#TYPED_TEST)
+for an example.
+
+See also [`REGISTER_TYPED_TEST_SUITE_P`](#REGISTER_TYPED_TEST_SUITE_P) and
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more
+information.
+
+### REGISTER_TYPED_TEST_SUITE_P {#REGISTER_TYPED_TEST_SUITE_P}
+
+`REGISTER_TYPED_TEST_SUITE_P(`*`TestSuiteName`*`,`*`TestNames...`*`)`
+
+Registers the type-parameterized tests *`TestNames...`* of the test suite
+*`TestSuiteName`*. The test suite and tests must be defined with
+[`TYPED_TEST_SUITE_P`](#TYPED_TEST_SUITE_P) and [`TYPED_TEST_P`](#TYPED_TEST_P).
+
+For example:
+
+```cpp
+// Define the test suite and tests.
+TYPED_TEST_SUITE_P(MyFixture);
+TYPED_TEST_P(MyFixture, HasPropertyA) { ... }
+TYPED_TEST_P(MyFixture, HasPropertyB) { ... }
+
+// Register the tests in the test suite.
+REGISTER_TYPED_TEST_SUITE_P(MyFixture, HasPropertyA, HasPropertyB);
+```
+
+See also [`INSTANTIATE_TYPED_TEST_SUITE_P`](#INSTANTIATE_TYPED_TEST_SUITE_P) and
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more
+information.
+
+### INSTANTIATE_TYPED_TEST_SUITE_P {#INSTANTIATE_TYPED_TEST_SUITE_P}
+
+`INSTANTIATE_TYPED_TEST_SUITE_P(`*`InstantiationName`*`,`*`TestSuiteName`*`,`*`Types`*`)`
+
+Instantiates the type-parameterized test suite *`TestSuiteName`*. The test suite
+must be registered with
+[`REGISTER_TYPED_TEST_SUITE_P`](#REGISTER_TYPED_TEST_SUITE_P).
+
+The argument *`InstantiationName`* is a unique name for the instantiation of the
+test suite, to distinguish between multiple instantiations. In test output, the
+instantiation name is added as a prefix to the test suite name
+*`TestSuiteName`*. If *`InstantiationName`* is empty
+(`INSTANTIATE_TYPED_TEST_SUITE_P(, ...)`), no prefix is added.
+
+The argument *`Types`* is a [`Types`](#Types) object representing the list of
+types to run the tests on, for example:
+
+```cpp
+using MyTypes = ::testing::Types<char, int, unsigned int>;
+INSTANTIATE_TYPED_TEST_SUITE_P(MyInstantiation, MyFixture, MyTypes);
+```
+
+The type alias (`using` or `typedef`) is necessary for the
+`INSTANTIATE_TYPED_TEST_SUITE_P` macro to parse correctly.
+
+For more information, see
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests).
+
+### FRIEND_TEST {#FRIEND_TEST}
+
+`FRIEND_TEST(`*`TestSuiteName`*`,`*`TestName`*`)`
+
+Within a class body, declares an individual test as a friend of the class,
+enabling the test to access private class members.
+
+If the class is defined in a namespace, then in order to be friends of the
+class, test fixtures and tests must be defined in the exact same namespace,
+without inline or anonymous namespaces.
+
+For example, if the class definition looks like the following:
+
+```cpp
+namespace my_namespace {
+
+class MyClass {
+  friend class MyClassTest;
+  FRIEND_TEST(MyClassTest, HasPropertyA);
+  FRIEND_TEST(MyClassTest, HasPropertyB);
+  ... definition of class MyClass ...
+};
+
+}  // namespace my_namespace
+```
+
+Then the test code should look like:
+
+```cpp
+namespace my_namespace {
+
+class MyClassTest : public testing::Test {
+  ...
+};
+
+TEST_F(MyClassTest, HasPropertyA) { ... }
+TEST_F(MyClassTest, HasPropertyB) { ... }
+
+}  // namespace my_namespace
+```
+
+See [Testing Private Code](../advanced.md#testing-private-code) for more
+information.
+
+### SCOPED_TRACE {#SCOPED_TRACE}
+
+`SCOPED_TRACE(`*`message`*`)`
+
+Causes the current file name, line number, and the given message *`message`* to
+be added to the failure message for each assertion failure that occurs in the
+scope.
+
+For more information, see
+[Adding Traces to Assertions](../advanced.md#adding-traces-to-assertions).
+
+See also the [`ScopedTrace` class](#ScopedTrace).
+
+### GTEST_SKIP {#GTEST_SKIP}
+
+`GTEST_SKIP()`
+
+Prevents further test execution at runtime.
+
+Can be used in individual test cases or in the `SetUp()` methods of test
+environments or test fixtures (classes derived from the
+[`Environment`](#Environment) or [`Test`](#Test) classes). If used in a global
+test environment `SetUp()` method, it skips all tests in the test program. If
+used in a test fixture `SetUp()` method, it skips all tests in the corresponding
+test suite.
+
+Similar to assertions, `GTEST_SKIP` allows streaming a custom message into it.
+
+See [Skipping Test Execution](../advanced.md#skipping-test-execution) for more
+information.
+
+### GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST {#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST}
+
+`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(`*`TestSuiteName`*`)`
+
+Allows the value-parameterized test suite *`TestSuiteName`* to be
+uninstantiated.
+
+By default, every [`TEST_P`](#TEST_P) call without a corresponding
+[`INSTANTIATE_TEST_SUITE_P`](#INSTANTIATE_TEST_SUITE_P) call causes a failing
+test in the test suite `GoogleTestVerification`.
+`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST` suppresses this failure for the
+given test suite.
+
+## Classes and types
+
+GoogleTest defines the following classes and types to help with writing tests.
+
+### AssertionResult {#AssertionResult}
+
+`testing::AssertionResult`
+
+A class for indicating whether an assertion was successful.
+
+When the assertion wasn't successful, the `AssertionResult` object stores a
+non-empty failure message that can be retrieved with the object's `message()`
+method.
+
+To create an instance of this class, use one of the factory functions
+[`AssertionSuccess()`](#AssertionSuccess) or
+[`AssertionFailure()`](#AssertionFailure).
+
+### AssertionException {#AssertionException}
+
+`testing::AssertionException`
+
+Exception which can be thrown from
+[`TestEventListener::OnTestPartResult`](#TestEventListener::OnTestPartResult).
+
+### EmptyTestEventListener {#EmptyTestEventListener}
+
+`testing::EmptyTestEventListener`
+
+Provides an empty implementation of all methods in the
+[`TestEventListener`](#TestEventListener) interface, such that a subclass only
+needs to override the methods it cares about.
+
+### Environment {#Environment}
+
+`testing::Environment`
+
+Represents a global test environment. See
+[Global Set-Up and Tear-Down](../advanced.md#global-set-up-and-tear-down).
+
+#### Protected Methods {#Environment-protected}
+
+##### SetUp {#Environment::SetUp}
+
+`virtual void Environment::SetUp()`
+
+Override this to define how to set up the environment.
+
+##### TearDown {#Environment::TearDown}
+
+`virtual void Environment::TearDown()`
+
+Override this to define how to tear down the environment.
+
+### ScopedTrace {#ScopedTrace}
+
+`testing::ScopedTrace`
+
+An instance of this class causes a trace to be included in every test failure
+message generated by code in the scope of the lifetime of the `ScopedTrace`
+instance. The effect is undone with the destruction of the instance.
+
+The `ScopedTrace` constructor has the following form:
+
+```cpp
+template <typename T>
+ScopedTrace(const char* file, int line, const T& message)
+```
+
+Example usage:
+
+```cpp
+testing::ScopedTrace trace("file.cc", 123, "message");
+```
+
+The resulting trace includes the given source file path and line number, and the
+given message. The `message` argument can be anything streamable to
+`std::ostream`.
+
+See also [`SCOPED_TRACE`](#SCOPED_TRACE).
+
+### Test {#Test}
+
+`testing::Test`
+
+The abstract class that all tests inherit from. `Test` is not copyable.
+
+#### Public Methods {#Test-public}
+
+##### SetUpTestSuite {#Test::SetUpTestSuite}
+
+`static void Test::SetUpTestSuite()`
+
+Performs shared setup for all tests in the test suite. GoogleTest calls
+`SetUpTestSuite()` before running the first test in the test suite.
+
+##### TearDownTestSuite {#Test::TearDownTestSuite}
+
+`static void Test::TearDownTestSuite()`
+
+Performs shared teardown for all tests in the test suite. GoogleTest calls
+`TearDownTestSuite()` after running the last test in the test suite.
+
+##### HasFatalFailure {#Test::HasFatalFailure}
+
+`static bool Test::HasFatalFailure()`
+
+Returns true if and only if the current test has a fatal failure.
+
+##### HasNonfatalFailure {#Test::HasNonfatalFailure}
+
+`static bool Test::HasNonfatalFailure()`
+
+Returns true if and only if the current test has a nonfatal failure.
+
+##### HasFailure {#Test::HasFailure}
+
+`static bool Test::HasFailure()`
+
+Returns true if and only if the current test has any failure, either fatal or
+nonfatal.
+
+##### IsSkipped {#Test::IsSkipped}
+
+`static bool Test::IsSkipped()`
+
+Returns true if and only if the current test was skipped.
+
+##### RecordProperty {#Test::RecordProperty}
+
+`static void Test::RecordProperty(const std::string& key, const std::string&
+value)` \
+`static void Test::RecordProperty(const std::string& key, int value)`
+
+Logs a property for the current test, test suite, or entire invocation of the
+test program. Only the last value for a given key is logged.
+
+The key must be a valid XML attribute name, and cannot conflict with the ones
+already used by GoogleTest (`name`, `file`, `line`, `status`, `time`,
+`classname`, `type_param`, and `value_param`).
+
+`RecordProperty` is `public static` so it can be called from utility functions
+that are not members of the test fixture.
+
+Calls to `RecordProperty` made during the lifespan of the test (from the moment
+its constructor starts to the moment its destructor finishes) are output in XML
+as attributes of the `<testcase>` element. Properties recorded from a fixture's
+`SetUpTestSuite` or `TearDownTestSuite` methods are logged as attributes of the
+corresponding `<testsuite>` element. Calls to `RecordProperty` made in the
+global context (before or after invocation of `RUN_ALL_TESTS` or from the
+`SetUp`/`TearDown` methods of registered `Environment` objects) are output as
+attributes of the `<testsuites>` element.
+
+#### Protected Methods {#Test-protected}
+
+##### SetUp {#Test::SetUp}
+
+`virtual void Test::SetUp()`
+
+Override this to perform test fixture setup. GoogleTest calls `SetUp()` before
+running each individual test.
+
+##### TearDown {#Test::TearDown}
+
+`virtual void Test::TearDown()`
+
+Override this to perform test fixture teardown. GoogleTest calls `TearDown()`
+after running each individual test.
+
+### TestWithParam {#TestWithParam}
+
+`testing::TestWithParam<T>`
+
+A convenience class which inherits from both [`Test`](#Test) and
+[`WithParamInterface<T>`](#WithParamInterface).
+
+### TestSuite {#TestSuite}
+
+Represents a test suite. `TestSuite` is not copyable.
+
+#### Public Methods {#TestSuite-public}
+
+##### name {#TestSuite::name}
+
+`const char* TestSuite::name() const`
+
+Gets the name of the test suite.
+
+##### type_param {#TestSuite::type_param}
+
+`const char* TestSuite::type_param() const`
+
+Returns the name of the parameter type, or `NULL` if this is not a typed or
+type-parameterized test suite. See [Typed Tests](../advanced.md#typed-tests) and
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests).
+
+##### should_run {#TestSuite::should_run}
+
+`bool TestSuite::should_run() const`
+
+Returns true if any test in this test suite should run.
+
+##### successful_test_count {#TestSuite::successful_test_count}
+
+`int TestSuite::successful_test_count() const`
+
+Gets the number of successful tests in this test suite.
+
+##### skipped_test_count {#TestSuite::skipped_test_count}
+
+`int TestSuite::skipped_test_count() const`
+
+Gets the number of skipped tests in this test suite.
+
+##### failed_test_count {#TestSuite::failed_test_count}
+
+`int TestSuite::failed_test_count() const`
+
+Gets the number of failed tests in this test suite.
+
+##### reportable_disabled_test_count {#TestSuite::reportable_disabled_test_count}
+
+`int TestSuite::reportable_disabled_test_count() const`
+
+Gets the number of disabled tests that will be reported in the XML report.
+
+##### disabled_test_count {#TestSuite::disabled_test_count}
+
+`int TestSuite::disabled_test_count() const`
+
+Gets the number of disabled tests in this test suite.
+
+##### reportable_test_count {#TestSuite::reportable_test_count}
+
+`int TestSuite::reportable_test_count() const`
+
+Gets the number of tests to be printed in the XML report.
+
+##### test_to_run_count {#TestSuite::test_to_run_count}
+
+`int TestSuite::test_to_run_count() const`
+
+Get the number of tests in this test suite that should run.
+
+##### total_test_count {#TestSuite::total_test_count}
+
+`int TestSuite::total_test_count() const`
+
+Gets the number of all tests in this test suite.
+
+##### Passed {#TestSuite::Passed}
+
+`bool TestSuite::Passed() const`
+
+Returns true if and only if the test suite passed.
+
+##### Failed {#TestSuite::Failed}
+
+`bool TestSuite::Failed() const`
+
+Returns true if and only if the test suite failed.
+
+##### elapsed_time {#TestSuite::elapsed_time}
+
+`TimeInMillis TestSuite::elapsed_time() const`
+
+Returns the elapsed time, in milliseconds.
+
+##### start_timestamp {#TestSuite::start_timestamp}
+
+`TimeInMillis TestSuite::start_timestamp() const`
+
+Gets the time of the test suite start, in ms from the start of the UNIX epoch.
+
+##### GetTestInfo {#TestSuite::GetTestInfo}
+
+`const TestInfo* TestSuite::GetTestInfo(int i) const`
+
+Returns the [`TestInfo`](#TestInfo) for the `i`-th test among all the tests. `i`
+can range from 0 to `total_test_count() - 1`. If `i` is not in that range,
+returns `NULL`.
+
+##### ad_hoc_test_result {#TestSuite::ad_hoc_test_result}
+
+`const TestResult& TestSuite::ad_hoc_test_result() const`
+
+Returns the [`TestResult`](#TestResult) that holds test properties recorded
+during execution of `SetUpTestSuite` and `TearDownTestSuite`.
+
+### TestInfo {#TestInfo}
+
+`testing::TestInfo`
+
+Stores information about a test.
+
+#### Public Methods {#TestInfo-public}
+
+##### test_suite_name {#TestInfo::test_suite_name}
+
+`const char* TestInfo::test_suite_name() const`
+
+Returns the test suite name.
+
+##### name {#TestInfo::name}
+
+`const char* TestInfo::name() const`
+
+Returns the test name.
+
+##### type_param {#TestInfo::type_param}
+
+`const char* TestInfo::type_param() const`
+
+Returns the name of the parameter type, or `NULL` if this is not a typed or
+type-parameterized test. See [Typed Tests](../advanced.md#typed-tests) and
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests).
+
+##### value_param {#TestInfo::value_param}
+
+`const char* TestInfo::value_param() const`
+
+Returns the text representation of the value parameter, or `NULL` if this is not
+a value-parameterized test. See
+[Value-Parameterized Tests](../advanced.md#value-parameterized-tests).
+
+##### file {#TestInfo::file}
+
+`const char* TestInfo::file() const`
+
+Returns the file name where this test is defined.
+
+##### line {#TestInfo::line}
+
+`int TestInfo::line() const`
+
+Returns the line where this test is defined.
+
+##### is_in_another_shard {#TestInfo::is_in_another_shard}
+
+`bool TestInfo::is_in_another_shard() const`
+
+Returns true if this test should not be run because it's in another shard.
+
+##### should_run {#TestInfo::should_run}
+
+`bool TestInfo::should_run() const`
+
+Returns true if this test should run, that is if the test is not disabled (or it
+is disabled but the `also_run_disabled_tests` flag has been specified) and its
+full name matches the user-specified filter.
+
+GoogleTest allows the user to filter the tests by their full names. Only the
+tests that match the filter will run. See
+[Running a Subset of the Tests](../advanced.md#running-a-subset-of-the-tests)
+for more information.
+
+##### is_reportable {#TestInfo::is_reportable}
+
+`bool TestInfo::is_reportable() const`
+
+Returns true if and only if this test will appear in the XML report.
+
+##### result {#TestInfo::result}
+
+`const TestResult* TestInfo::result() const`
+
+Returns the result of the test. See [`TestResult`](#TestResult).
+
+### TestParamInfo {#TestParamInfo}
+
+`testing::TestParamInfo<T>`
+
+Describes a parameter to a value-parameterized test. The type `T` is the type of
+the parameter.
+
+Contains the fields `param` and `index` which hold the value of the parameter
+and its integer index respectively.
+
+### UnitTest {#UnitTest}
+
+`testing::UnitTest`
+
+This class contains information about the test program.
+
+`UnitTest` is a singleton class. The only instance is created when
+`UnitTest::GetInstance()` is first called. This instance is never deleted.
+
+`UnitTest` is not copyable.
+
+#### Public Methods {#UnitTest-public}
+
+##### GetInstance {#UnitTest::GetInstance}
+
+`static UnitTest* UnitTest::GetInstance()`
+
+Gets the singleton `UnitTest` object. The first time this method is called, a
+`UnitTest` object is constructed and returned. Consecutive calls will return the
+same object.
+
+##### original_working_dir {#UnitTest::original_working_dir}
+
+`const char* UnitTest::original_working_dir() const`
+
+Returns the working directory when the first [`TEST()`](#TEST) or
+[`TEST_F()`](#TEST_F) was executed. The `UnitTest` object owns the string.
+
+##### current_test_suite {#UnitTest::current_test_suite}
+
+`const TestSuite* UnitTest::current_test_suite() const`
+
+Returns the [`TestSuite`](#TestSuite) object for the test that's currently
+running, or `NULL` if no test is running.
+
+##### current_test_info {#UnitTest::current_test_info}
+
+`const TestInfo* UnitTest::current_test_info() const`
+
+Returns the [`TestInfo`](#TestInfo) object for the test that's currently
+running, or `NULL` if no test is running.
+
+##### random_seed {#UnitTest::random_seed}
+
+`int UnitTest::random_seed() const`
+
+Returns the random seed used at the start of the current test run.
+
+##### successful_test_suite_count {#UnitTest::successful_test_suite_count}
+
+`int UnitTest::successful_test_suite_count() const`
+
+Gets the number of successful test suites.
+
+##### failed_test_suite_count {#UnitTest::failed_test_suite_count}
+
+`int UnitTest::failed_test_suite_count() const`
+
+Gets the number of failed test suites.
+
+##### total_test_suite_count {#UnitTest::total_test_suite_count}
+
+`int UnitTest::total_test_suite_count() const`
+
+Gets the number of all test suites.
+
+##### test_suite_to_run_count {#UnitTest::test_suite_to_run_count}
+
+`int UnitTest::test_suite_to_run_count() const`
+
+Gets the number of all test suites that contain at least one test that should
+run.
+
+##### successful_test_count {#UnitTest::successful_test_count}
+
+`int UnitTest::successful_test_count() const`
+
+Gets the number of successful tests.
+
+##### skipped_test_count {#UnitTest::skipped_test_count}
+
+`int UnitTest::skipped_test_count() const`
+
+Gets the number of skipped tests.
+
+##### failed_test_count {#UnitTest::failed_test_count}
+
+`int UnitTest::failed_test_count() const`
+
+Gets the number of failed tests.
+
+##### reportable_disabled_test_count {#UnitTest::reportable_disabled_test_count}
+
+`int UnitTest::reportable_disabled_test_count() const`
+
+Gets the number of disabled tests that will be reported in the XML report.
+
+##### disabled_test_count {#UnitTest::disabled_test_count}
+
+`int UnitTest::disabled_test_count() const`
+
+Gets the number of disabled tests.
+
+##### reportable_test_count {#UnitTest::reportable_test_count}
+
+`int UnitTest::reportable_test_count() const`
+
+Gets the number of tests to be printed in the XML report.
+
+##### total_test_count {#UnitTest::total_test_count}
+
+`int UnitTest::total_test_count() const`
+
+Gets the number of all tests.
+
+##### test_to_run_count {#UnitTest::test_to_run_count}
+
+`int UnitTest::test_to_run_count() const`
+
+Gets the number of tests that should run.
+
+##### start_timestamp {#UnitTest::start_timestamp}
+
+`TimeInMillis UnitTest::start_timestamp() const`
+
+Gets the time of the test program start, in ms from the start of the UNIX epoch.
+
+##### elapsed_time {#UnitTest::elapsed_time}
+
+`TimeInMillis UnitTest::elapsed_time() const`
+
+Gets the elapsed time, in milliseconds.
+
+##### Passed {#UnitTest::Passed}
+
+`bool UnitTest::Passed() const`
+
+Returns true if and only if the unit test passed (i.e. all test suites passed).
+
+##### Failed {#UnitTest::Failed}
+
+`bool UnitTest::Failed() const`
+
+Returns true if and only if the unit test failed (i.e. some test suite failed or
+something outside of all tests failed).
+
+##### GetTestSuite {#UnitTest::GetTestSuite}
+
+`const TestSuite* UnitTest::GetTestSuite(int i) const`
+
+Gets the [`TestSuite`](#TestSuite) object for the `i`-th test suite among all
+the test suites. `i` can range from 0 to `total_test_suite_count() - 1`. If `i`
+is not in that range, returns `NULL`.
+
+##### ad_hoc_test_result {#UnitTest::ad_hoc_test_result}
+
+`const TestResult& UnitTest::ad_hoc_test_result() const`
+
+Returns the [`TestResult`](#TestResult) containing information on test failures
+and properties logged outside of individual test suites.
+
+##### listeners {#UnitTest::listeners}
+
+`TestEventListeners& UnitTest::listeners()`
+
+Returns the list of event listeners that can be used to track events inside
+GoogleTest. See [`TestEventListeners`](#TestEventListeners).
+
+### TestEventListener {#TestEventListener}
+
+`testing::TestEventListener`
+
+The interface for tracing execution of tests. The methods below are listed in
+the order the corresponding events are fired.
+
+#### Public Methods {#TestEventListener-public}
+
+##### OnTestProgramStart {#TestEventListener::OnTestProgramStart}
+
+`virtual void TestEventListener::OnTestProgramStart(const UnitTest& unit_test)`
+
+Fired before any test activity starts.
+
+##### OnTestIterationStart {#TestEventListener::OnTestIterationStart}
+
+`virtual void TestEventListener::OnTestIterationStart(const UnitTest& unit_test,
+int iteration)`
+
+Fired before each iteration of tests starts. There may be more than one
+iteration if `GTEST_FLAG(repeat)` is set. `iteration` is the iteration index,
+starting from 0.
+
+##### OnEnvironmentsSetUpStart {#TestEventListener::OnEnvironmentsSetUpStart}
+
+`virtual void TestEventListener::OnEnvironmentsSetUpStart(const UnitTest&
+unit_test)`
+
+Fired before environment set-up for each iteration of tests starts.
+
+##### OnEnvironmentsSetUpEnd {#TestEventListener::OnEnvironmentsSetUpEnd}
+
+`virtual void TestEventListener::OnEnvironmentsSetUpEnd(const UnitTest&
+unit_test)`
+
+Fired after environment set-up for each iteration of tests ends.
+
+##### OnTestSuiteStart {#TestEventListener::OnTestSuiteStart}
+
+`virtual void TestEventListener::OnTestSuiteStart(const TestSuite& test_suite)`
+
+Fired before the test suite starts.
+
+##### OnTestStart {#TestEventListener::OnTestStart}
+
+`virtual void TestEventListener::OnTestStart(const TestInfo& test_info)`
+
+Fired before the test starts.
+
+##### OnTestPartResult {#TestEventListener::OnTestPartResult}
+
+`virtual void TestEventListener::OnTestPartResult(const TestPartResult&
+test_part_result)`
+
+Fired after a failed assertion or a `SUCCEED()` invocation. If you want to throw
+an exception from this function to skip to the next test, it must be an
+[`AssertionException`](#AssertionException) or inherited from it.
+
+##### OnTestEnd {#TestEventListener::OnTestEnd}
+
+`virtual void TestEventListener::OnTestEnd(const TestInfo& test_info)`
+
+Fired after the test ends.
+
+##### OnTestSuiteEnd {#TestEventListener::OnTestSuiteEnd}
+
+`virtual void TestEventListener::OnTestSuiteEnd(const TestSuite& test_suite)`
+
+Fired after the test suite ends.
+
+##### OnEnvironmentsTearDownStart {#TestEventListener::OnEnvironmentsTearDownStart}
+
+`virtual void TestEventListener::OnEnvironmentsTearDownStart(const UnitTest&
+unit_test)`
+
+Fired before environment tear-down for each iteration of tests starts.
+
+##### OnEnvironmentsTearDownEnd {#TestEventListener::OnEnvironmentsTearDownEnd}
+
+`virtual void TestEventListener::OnEnvironmentsTearDownEnd(const UnitTest&
+unit_test)`
+
+Fired after environment tear-down for each iteration of tests ends.
+
+##### OnTestIterationEnd {#TestEventListener::OnTestIterationEnd}
+
+`virtual void TestEventListener::OnTestIterationEnd(const UnitTest& unit_test,
+int iteration)`
+
+Fired after each iteration of tests finishes.
+
+##### OnTestProgramEnd {#TestEventListener::OnTestProgramEnd}
+
+`virtual void TestEventListener::OnTestProgramEnd(const UnitTest& unit_test)`
+
+Fired after all test activities have ended.
+
+### TestEventListeners {#TestEventListeners}
+
+`testing::TestEventListeners`
+
+Lets users add listeners to track events in GoogleTest.
+
+#### Public Methods {#TestEventListeners-public}
+
+##### Append {#TestEventListeners::Append}
+
+`void TestEventListeners::Append(TestEventListener* listener)`
+
+Appends an event listener to the end of the list. GoogleTest assumes ownership
+of the listener (i.e. it will delete the listener when the test program
+finishes).
+
+##### Release {#TestEventListeners::Release}
+
+`TestEventListener* TestEventListeners::Release(TestEventListener* listener)`
+
+Removes the given event listener from the list and returns it. It then becomes
+the caller's responsibility to delete the listener. Returns `NULL` if the
+listener is not found in the list.
+
+##### default_result_printer {#TestEventListeners::default_result_printer}
+
+`TestEventListener* TestEventListeners::default_result_printer() const`
+
+Returns the standard listener responsible for the default console output. Can be
+removed from the listeners list to shut down default console output. Note that
+removing this object from the listener list with
+[`Release()`](#TestEventListeners::Release) transfers its ownership to the
+caller and makes this function return `NULL` the next time.
+
+##### default_xml_generator {#TestEventListeners::default_xml_generator}
+
+`TestEventListener* TestEventListeners::default_xml_generator() const`
+
+Returns the standard listener responsible for the default XML output controlled
+by the `--gtest_output=xml` flag. Can be removed from the listeners list by
+users who want to shut down the default XML output controlled by this flag and
+substitute it with custom one. Note that removing this object from the listener
+list with [`Release()`](#TestEventListeners::Release) transfers its ownership to
+the caller and makes this function return `NULL` the next time.
+
+### TestPartResult {#TestPartResult}
+
+`testing::TestPartResult`
+
+A copyable object representing the result of a test part (i.e. an assertion or
+an explicit `FAIL()`, `ADD_FAILURE()`, or `SUCCESS()`).
+
+#### Public Methods {#TestPartResult-public}
+
+##### type {#TestPartResult::type}
+
+`Type TestPartResult::type() const`
+
+Gets the outcome of the test part.
+
+The return type `Type` is an enum defined as follows:
+
+```cpp
+enum Type {
+  kSuccess,          // Succeeded.
+  kNonFatalFailure,  // Failed but the test can continue.
+  kFatalFailure,     // Failed and the test should be terminated.
+  kSkip              // Skipped.
+};
+```
+
+##### file_name {#TestPartResult::file_name}
+
+`const char* TestPartResult::file_name() const`
+
+Gets the name of the source file where the test part took place, or `NULL` if
+it's unknown.
+
+##### line_number {#TestPartResult::line_number}
+
+`int TestPartResult::line_number() const`
+
+Gets the line in the source file where the test part took place, or `-1` if it's
+unknown.
+
+##### summary {#TestPartResult::summary}
+
+`const char* TestPartResult::summary() const`
+
+Gets the summary of the failure message.
+
+##### message {#TestPartResult::message}
+
+`const char* TestPartResult::message() const`
+
+Gets the message associated with the test part.
+
+##### skipped {#TestPartResult::skipped}
+
+`bool TestPartResult::skipped() const`
+
+Returns true if and only if the test part was skipped.
+
+##### passed {#TestPartResult::passed}
+
+`bool TestPartResult::passed() const`
+
+Returns true if and only if the test part passed.
+
+##### nonfatally_failed {#TestPartResult::nonfatally_failed}
+
+`bool TestPartResult::nonfatally_failed() const`
+
+Returns true if and only if the test part non-fatally failed.
+
+##### fatally_failed {#TestPartResult::fatally_failed}
+
+`bool TestPartResult::fatally_failed() const`
+
+Returns true if and only if the test part fatally failed.
+
+##### failed {#TestPartResult::failed}
+
+`bool TestPartResult::failed() const`
+
+Returns true if and only if the test part failed.
+
+### TestProperty {#TestProperty}
+
+`testing::TestProperty`
+
+A copyable object representing a user-specified test property which can be
+output as a key/value string pair.
+
+#### Public Methods {#TestProperty-public}
+
+##### key {#key}
+
+`const char* key() const`
+
+Gets the user-supplied key.
+
+##### value {#value}
+
+`const char* value() const`
+
+Gets the user-supplied value.
+
+##### SetValue {#SetValue}
+
+`void SetValue(const std::string& new_value)`
+
+Sets a new value, overriding the previous one.
+
+### TestResult {#TestResult}
+
+`testing::TestResult`
+
+Contains information about the result of a single test.
+
+`TestResult` is not copyable.
+
+#### Public Methods {#TestResult-public}
+
+##### total_part_count {#TestResult::total_part_count}
+
+`int TestResult::total_part_count() const`
+
+Gets the number of all test parts. This is the sum of the number of successful
+test parts and the number of failed test parts.
+
+##### test_property_count {#TestResult::test_property_count}
+
+`int TestResult::test_property_count() const`
+
+Returns the number of test properties.
+
+##### Passed {#TestResult::Passed}
+
+`bool TestResult::Passed() const`
+
+Returns true if and only if the test passed (i.e. no test part failed).
+
+##### Skipped {#TestResult::Skipped}
+
+`bool TestResult::Skipped() const`
+
+Returns true if and only if the test was skipped.
+
+##### Failed {#TestResult::Failed}
+
+`bool TestResult::Failed() const`
+
+Returns true if and only if the test failed.
+
+##### HasFatalFailure {#TestResult::HasFatalFailure}
+
+`bool TestResult::HasFatalFailure() const`
+
+Returns true if and only if the test fatally failed.
+
+##### HasNonfatalFailure {#TestResult::HasNonfatalFailure}
+
+`bool TestResult::HasNonfatalFailure() const`
+
+Returns true if and only if the test has a non-fatal failure.
+
+##### elapsed_time {#TestResult::elapsed_time}
+
+`TimeInMillis TestResult::elapsed_time() const`
+
+Returns the elapsed time, in milliseconds.
+
+##### start_timestamp {#TestResult::start_timestamp}
+
+`TimeInMillis TestResult::start_timestamp() const`
+
+Gets the time of the test case start, in ms from the start of the UNIX epoch.
+
+##### GetTestPartResult {#TestResult::GetTestPartResult}
+
+`const TestPartResult& TestResult::GetTestPartResult(int i) const`
+
+Returns the [`TestPartResult`](#TestPartResult) for the `i`-th test part result
+among all the results. `i` can range from 0 to `total_part_count() - 1`. If `i`
+is not in that range, aborts the program.
+
+##### GetTestProperty {#TestResult::GetTestProperty}
+
+`const TestProperty& TestResult::GetTestProperty(int i) const`
+
+Returns the [`TestProperty`](#TestProperty) object for the `i`-th test property.
+`i` can range from 0 to `test_property_count() - 1`. If `i` is not in that
+range, aborts the program.
+
+### TimeInMillis {#TimeInMillis}
+
+`testing::TimeInMillis`
+
+An integer type representing time in milliseconds.
+
+### Types {#Types}
+
+`testing::Types<T...>`
+
+Represents a list of types for use in typed tests and type-parameterized tests.
+
+The template argument `T...` can be any number of types, for example:
+
+```
+testing::Types<char, int, unsigned int>
+```
+
+See [Typed Tests](../advanced.md#typed-tests) and
+[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more
+information.
+
+### WithParamInterface {#WithParamInterface}
+
+`testing::WithParamInterface<T>`
+
+The pure interface class that all value-parameterized tests inherit from.
+
+A value-parameterized test fixture class must inherit from both [`Test`](#Test)
+and `WithParamInterface`. In most cases that just means inheriting from
+[`TestWithParam`](#TestWithParam), but more complicated test hierarchies may
+need to inherit from `Test` and `WithParamInterface` at different levels.
+
+This interface defines the type alias `ParamType` for the parameter type `T` and
+has support for accessing the test parameter value via the `GetParam()` method:
+
+```
+static const ParamType& GetParam()
+```
+
+For more information, see
+[Value-Parameterized Tests](../advanced.md#value-parameterized-tests).
+
+## Functions
+
+GoogleTest defines the following functions to help with writing and running
+tests.
+
+### InitGoogleTest {#InitGoogleTest}
+
+`void testing::InitGoogleTest(int* argc, char** argv)` \
+`void testing::InitGoogleTest(int* argc, wchar_t** argv)` \
+`void testing::InitGoogleTest()`
+
+Initializes GoogleTest. This must be called before calling
+[`RUN_ALL_TESTS()`](#RUN_ALL_TESTS). In particular, it parses the command line
+for the flags that GoogleTest recognizes. Whenever a GoogleTest flag is seen, it
+is removed from `argv`, and `*argc` is decremented. Keep in mind that `argv`
+must terminate with a `NULL` pointer (i.e. `argv[argc]` is `NULL`), which is
+already the case with the default `argv` passed to `main`.
+
+No value is returned. Instead, the GoogleTest flag variables are updated.
+
+The `InitGoogleTest(int* argc, wchar_t** argv)` overload can be used in Windows
+programs compiled in `UNICODE` mode.
+
+The argument-less `InitGoogleTest()` overload can be used on Arduino/embedded
+platforms where there is no `argc`/`argv`.
+
+### AddGlobalTestEnvironment {#AddGlobalTestEnvironment}
+
+`Environment* testing::AddGlobalTestEnvironment(Environment* env)`
+
+Adds a test environment to the test program. Must be called before
+[`RUN_ALL_TESTS()`](#RUN_ALL_TESTS) is called. See
+[Global Set-Up and Tear-Down](../advanced.md#global-set-up-and-tear-down) for
+more information.
+
+See also [`Environment`](#Environment).
+
+### RegisterTest {#RegisterTest}
+
+```cpp
+template <typename Factory>
+TestInfo* testing::RegisterTest(const char* test_suite_name, const char* test_name,
+                                  const char* type_param, const char* value_param,
+                                  const char* file, int line, Factory factory)
+```
+
+Dynamically registers a test with the framework.
+
+The `factory` argument is a factory callable (move-constructible) object or
+function pointer that creates a new instance of the `Test` object. It handles
+ownership to the caller. The signature of the callable is `Fixture*()`, where
+`Fixture` is the test fixture class for the test. All tests registered with the
+same `test_suite_name` must return the same fixture type. This is checked at
+runtime.
+
+The framework will infer the fixture class from the factory and will call the
+`SetUpTestSuite` and `TearDownTestSuite` methods for it.
+
+Must be called before [`RUN_ALL_TESTS()`](#RUN_ALL_TESTS) is invoked, otherwise
+behavior is undefined.
+
+See
+[Registering tests programmatically](../advanced.md#registering-tests-programmatically)
+for more information.
+
+### RUN_ALL_TESTS {#RUN_ALL_TESTS}
+
+`int RUN_ALL_TESTS()`
+
+Use this function in `main()` to run all tests. It returns `0` if all tests are
+successful, or `1` otherwise.
+
+`RUN_ALL_TESTS()` should be invoked after the command line has been parsed by
+[`InitGoogleTest()`](#InitGoogleTest).
+
+This function was formerly a macro; thus, it is in the global namespace and has
+an all-caps name.
+
+### AssertionSuccess {#AssertionSuccess}
+
+`AssertionResult testing::AssertionSuccess()`
+
+Creates a successful assertion result. See
+[`AssertionResult`](#AssertionResult).
+
+### AssertionFailure {#AssertionFailure}
+
+`AssertionResult testing::AssertionFailure()`
+
+Creates a failed assertion result. Use the `<<` operator to store a failure
+message:
+
+```cpp
+testing::AssertionFailure() << "My failure message";
+```
+
+See [`AssertionResult`](#AssertionResult).
+
+### StaticAssertTypeEq {#StaticAssertTypeEq}
+
+`testing::StaticAssertTypeEq<T1, T2>()`
+
+Compile-time assertion for type equality. Compiles if and only if `T1` and `T2`
+are the same type. The value it returns is irrelevant.
+
+See [Type Assertions](../advanced.md#type-assertions) for more information.
+
+### PrintToString {#PrintToString}
+
+`std::string testing::PrintToString(x)`
+
+Prints any value `x` using GoogleTest's value printer.
+
+See
+[Teaching GoogleTest How to Print Your Values](../advanced.md#teaching-googletest-how-to-print-your-values)
+for more information.
+
+### PrintToStringParamName {#PrintToStringParamName}
+
+`std::string testing::PrintToStringParamName(TestParamInfo<T>& info)`
+
+A built-in parameterized test name generator which returns the result of
+[`PrintToString`](#PrintToString) called on `info.param`. Does not work when the
+test parameter is a `std::string` or C string. See
+[Specifying Names for Value-Parameterized Test Parameters](../advanced.md#specifying-names-for-value-parameterized-test-parameters)
+for more information.
+
+See also [`TestParamInfo`](#TestParamInfo) and
+[`INSTANTIATE_TEST_SUITE_P`](#INSTANTIATE_TEST_SUITE_P).
diff --git a/3rd-party/googletest/docs/samples.md b/3rd-party/googletest/docs/samples.md
new file mode 100644
index 0000000..dedc590
--- /dev/null
+++ b/3rd-party/googletest/docs/samples.md
@@ -0,0 +1,22 @@
+# Googletest Samples
+
+If you're like us, you'd like to look at
+[googletest samples.](https://github.com/google/googletest/blob/main/googletest/samples)
+The sample directory has a number of well-commented samples showing how to use a
+variety of googletest features.
+
+*   Sample #1 shows the basic steps of using googletest to test C++ functions.
+*   Sample #2 shows a more complex unit test for a class with multiple member
+    functions.
+*   Sample #3 uses a test fixture.
+*   Sample #4 teaches you how to use googletest and `googletest.h` together to
+    get the best of both libraries.
+*   Sample #5 puts shared testing logic in a base test fixture, and reuses it in
+    derived fixtures.
+*   Sample #6 demonstrates type-parameterized tests.
+*   Sample #7 teaches the basics of value-parameterized tests.
+*   Sample #8 shows using `Combine()` in value-parameterized tests.
+*   Sample #9 shows use of the listener API to modify Google Test's console
+    output and the use of its reflection API to inspect test results.
+*   Sample #10 shows use of the listener API to implement a primitive memory
+    leak checker.
diff --git a/3rd-party/googletest/fake_fuchsia_sdk.bzl b/3rd-party/googletest/fake_fuchsia_sdk.bzl
new file mode 100644
index 0000000..2024dc6
--- /dev/null
+++ b/3rd-party/googletest/fake_fuchsia_sdk.bzl
@@ -0,0 +1,33 @@
+"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
+
+This is needed since bazel queries on targets that depend on //:gtest (eg:
+`bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not
+defined when bazel is evaluating the transitive closure of the query target.
+
+See https://github.com/google/googletest/issues/4472.
+"""
+
+def _fake_fuchsia_sdk_impl(repo_ctx):
+    for stub_target in repo_ctx.attr._stub_build_targets:
+        stub_package = stub_target
+        stub_target_name = stub_target.split("/")[-1]
+        repo_ctx.file("%s/BUILD.bazel" % stub_package, """
+filegroup(
+    name = "%s",
+)
+""" % stub_target_name)
+
+fake_fuchsia_sdk = repository_rule(
+    doc = "Used to create a fake @fuchsia_sdk repository with stub build targets.",
+    implementation = _fake_fuchsia_sdk_impl,
+    attrs = {
+        "_stub_build_targets": attr.string_list(
+            doc = "The stub build targets to initialize.",
+            default = [
+                "pkg/fdio",
+                "pkg/syslog",
+                "pkg/zx",
+            ],
+        ),
+    },
+)
diff --git a/3rd-party/googletest/googlemock/CMakeLists.txt b/3rd-party/googletest/googlemock/CMakeLists.txt
new file mode 100644
index 0000000..99b2411
--- /dev/null
+++ b/3rd-party/googletest/googlemock/CMakeLists.txt
@@ -0,0 +1,210 @@
+########################################################################
+# Note: CMake support is community-based. The maintainers do not use CMake
+# internally.
+#
+# CMake build script for Google Mock.
+#
+# To run the tests for Google Mock itself on Linux, use 'make test' or
+# ctest. You can select which tests to run using 'ctest -R regex'.
+# For more options, run 'ctest --help'.
+
+option(gmock_build_tests "Build all of Google Mock's own tests." OFF)
+
+# A directory to find Google Test sources.
+if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt")
+  set(gtest_dir gtest)
+else()
+  set(gtest_dir ../googletest)
+endif()
+
+# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
+include("${gtest_dir}/cmake/hermetic_build.cmake" OPTIONAL)
+
+if (COMMAND pre_project_set_up_hermetic_build)
+  # Google Test also calls hermetic setup functions from add_subdirectory,
+  # although its changes will not affect things at the current scope.
+  pre_project_set_up_hermetic_build()
+endif()
+
+########################################################################
+#
+# Project-wide settings
+
+# Name of the project.
+#
+# CMake files in this project can refer to the root source directory
+# as ${gmock_SOURCE_DIR} and to the root binary directory as
+# ${gmock_BINARY_DIR}.
+# Language "C" is required for find_package(Threads).
+cmake_minimum_required(VERSION 3.13)
+project(gmock VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
+
+if (COMMAND set_up_hermetic_build)
+  set_up_hermetic_build()
+endif()
+
+# Instructs CMake to process Google Test's CMakeLists.txt and add its
+# targets to the current scope. We are placing Google Test's binary
+# directory in a subdirectory of our own as VC compilation may break
+# if they are the same (the default).
+add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/${gtest_dir}")
+
+
+# These commands only run if this is the main project
+if(CMAKE_PROJECT_NAME STREQUAL "gmock" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution")
+  # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
+  # make it prominent in the GUI.
+  option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
+else()
+  mark_as_advanced(gmock_build_tests)
+endif()
+
+# Although Google Test's CMakeLists.txt calls this function, the
+# changes there don't affect the current scope. Therefore we have to
+# call it again here.
+config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake
+
+# Adds Google Mock's and Google Test's header directories to the search path.
+# Get Google Test's include dirs from the target, gtest_SOURCE_DIR is broken
+# when using fetch-content with the name "GTest".
+get_target_property(gtest_include_dirs gtest INCLUDE_DIRECTORIES)
+set(gmock_build_include_dirs
+  "${gmock_SOURCE_DIR}/include"
+  "${gmock_SOURCE_DIR}"
+  "${gtest_include_dirs}")
+include_directories(${gmock_build_include_dirs})
+
+########################################################################
+#
+# Defines the gmock & gmock_main libraries. User tests should link
+# with one of them.
+
+# Google Mock libraries. We build them using more strict warnings than what
+# are used for other targets, to ensure that Google Mock can be compiled by
+# a user aggressive about warnings.
+if (MSVC)
+  cxx_library(gmock
+              "${cxx_strict}"
+              "${gtest_dir}/src/gtest-all.cc"
+              src/gmock-all.cc)
+
+  cxx_library(gmock_main
+              "${cxx_strict}"
+              "${gtest_dir}/src/gtest-all.cc"
+              src/gmock-all.cc
+              src/gmock_main.cc)
+else()
+  cxx_library(gmock "${cxx_strict}" src/gmock-all.cc)
+  target_link_libraries(gmock PUBLIC gtest)
+  set_target_properties(gmock PROPERTIES VERSION ${GOOGLETEST_VERSION})
+  cxx_library(gmock_main "${cxx_strict}" src/gmock_main.cc)
+  target_link_libraries(gmock_main PUBLIC gmock)
+  set_target_properties(gmock_main PROPERTIES VERSION ${GOOGLETEST_VERSION})
+endif()
+
+string(REPLACE ";" "$<SEMICOLON>" dirs "${gmock_build_include_dirs}")
+target_include_directories(gmock SYSTEM INTERFACE
+  "$<BUILD_INTERFACE:${dirs}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+target_include_directories(gmock_main SYSTEM INTERFACE
+  "$<BUILD_INTERFACE:${dirs}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+
+########################################################################
+#
+# Install rules.
+install_project(gmock gmock_main)
+
+########################################################################
+#
+# Google Mock's own tests.
+#
+# You can skip this section if you aren't interested in testing
+# Google Mock itself.
+#
+# The tests are not built by default. To build them, set the
+# gmock_build_tests option to ON. You can do it by running ccmake
+# or specifying the -Dgmock_build_tests=ON flag when running cmake.
+
+if (gmock_build_tests)
+  # This must be set in the root directory for the tests to be run by
+  # 'make test' or ctest.
+  enable_testing()
+
+  if (MINGW OR CYGWIN)
+    add_compile_options("-Wa,-mbig-obj")
+  endif()
+
+  ############################################################
+  # C++ tests built with standard compiler flags.
+
+  cxx_test(gmock-actions_test gmock_main)
+  cxx_test(gmock-cardinalities_test gmock_main)
+  cxx_test(gmock_ex_test gmock_main)
+  cxx_test(gmock-function-mocker_test gmock_main)
+  cxx_test(gmock-internal-utils_test gmock_main)
+  cxx_test(gmock-matchers-arithmetic_test gmock_main)
+  cxx_test(gmock-matchers-comparisons_test gmock_main)
+  cxx_test(gmock-matchers-containers_test gmock_main)
+  cxx_test(gmock-matchers-misc_test gmock_main)
+  cxx_test(gmock-more-actions_test gmock_main)
+  cxx_test(gmock-nice-strict_test gmock_main)
+  cxx_test(gmock-port_test gmock_main)
+  cxx_test(gmock-spec-builders_test gmock_main)
+  cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc)
+  cxx_test(gmock_test gmock_main)
+
+  if (DEFINED GTEST_HAS_PTHREAD)
+    cxx_test(gmock_stress_test gmock)
+  endif()
+
+  # gmock_all_test is commented to save time building and running tests.
+  # Uncomment if necessary.
+  # cxx_test(gmock_all_test gmock_main)
+
+  ############################################################
+  # C++ tests built with non-standard compiler flags.
+
+  if (MSVC)
+    cxx_library(gmock_main_no_exception "${cxx_no_exception}"
+      "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+    cxx_library(gmock_main_no_rtti "${cxx_no_rtti}"
+      "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+  else()
+    cxx_library(gmock_main_no_exception "${cxx_no_exception}" src/gmock_main.cc)
+    target_link_libraries(gmock_main_no_exception PUBLIC gmock)
+
+    cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" src/gmock_main.cc)
+    target_link_libraries(gmock_main_no_rtti PUBLIC gmock)
+  endif()
+  cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}"
+    gmock_main_no_exception test/gmock-more-actions_test.cc)
+
+  cxx_test_with_flags(gmock_no_rtti_test "${cxx_no_rtti}"
+    gmock_main_no_rtti test/gmock-spec-builders_test.cc)
+
+  cxx_shared_library(shared_gmock_main "${cxx_default}"
+    "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+  # Tests that a binary can be built with Google Mock as a shared library. On
+  # some system configurations, it may not possible to run the binary without
+  # knowing more details about the system configurations. We do not try to run
+  # this binary. To get a more robust shared library coverage, configure with
+  # -DBUILD_SHARED_LIBS=ON.
+  cxx_executable_with_flags(shared_gmock_test_ "${cxx_default}"
+    shared_gmock_main test/gmock-spec-builders_test.cc)
+  set_target_properties(shared_gmock_test_
+    PROPERTIES
+    COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+
+  ############################################################
+  # Python tests.
+
+  cxx_executable(gmock_leak_test_ test gmock_main)
+  py_test(gmock_leak_test)
+
+  cxx_executable(gmock_output_test_ test gmock)
+  py_test(gmock_output_test)
+endif()
diff --git a/3rd-party/googletest/googlemock/README.md b/3rd-party/googletest/googlemock/README.md
new file mode 100644
index 0000000..e1103b1
--- /dev/null
+++ b/3rd-party/googletest/googlemock/README.md
@@ -0,0 +1,40 @@
+# Googletest Mocking (gMock) Framework
+
+### Overview
+
+Google's framework for writing and using C++ mock classes. It can help you
+derive better designs of your system and write better tests.
+
+It is inspired by:
+
+*   [jMock](http://www.jmock.org/)
+*   [EasyMock](https://easymock.org/)
+*   [Hamcrest](https://code.google.com/p/hamcrest/)
+
+It is designed with C++'s specifics in mind.
+
+gMock:
+
+-   Provides a declarative syntax for defining mocks.
+-   Can define partial (hybrid) mocks, which are a cross of real and mock
+    objects.
+-   Handles functions of arbitrary types and overloaded functions.
+-   Comes with a rich set of matchers for validating function arguments.
+-   Uses an intuitive syntax for controlling the behavior of a mock.
+-   Does automatic verification of expectations (no record-and-replay needed).
+-   Allows arbitrary (partial) ordering constraints on function calls to be
+    expressed.
+-   Lets a user extend it by defining new matchers and actions.
+-   Does not use exceptions.
+-   Is easy to learn and use.
+
+Details and examples can be found here:
+
+*   [gMock for Dummies](https://google.github.io/googletest/gmock_for_dummies.html)
+*   [Legacy gMock FAQ](https://google.github.io/googletest/gmock_faq.html)
+*   [gMock Cookbook](https://google.github.io/googletest/gmock_cook_book.html)
+*   [gMock Cheat Sheet](https://google.github.io/googletest/gmock_cheat_sheet.html)
+
+GoogleMock is a part of
+[GoogleTest C++ testing framework](https://github.com/google/googletest/) and a
+subject to the same requirements.
diff --git a/3rd-party/googletest/googlemock/cmake/gmock.pc.in b/3rd-party/googletest/googlemock/cmake/gmock.pc.in
new file mode 100644
index 0000000..23c67b5
--- /dev/null
+++ b/3rd-party/googletest/googlemock/cmake/gmock.pc.in
@@ -0,0 +1,10 @@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: gmock
+Description: GoogleMock (without main() function)
+Version: @PROJECT_VERSION@
+URL: https://github.com/google/googletest
+Requires: gtest = @PROJECT_VERSION@
+Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
diff --git a/3rd-party/googletest/googlemock/cmake/gmock_main.pc.in b/3rd-party/googletest/googlemock/cmake/gmock_main.pc.in
new file mode 100644
index 0000000..66ffea7
--- /dev/null
+++ b/3rd-party/googletest/googlemock/cmake/gmock_main.pc.in
@@ -0,0 +1,10 @@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: gmock_main
+Description: GoogleMock (with main() function)
+Version: @PROJECT_VERSION@
+URL: https://github.com/google/googletest
+Requires: gmock = @PROJECT_VERSION@
+Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
diff --git a/3rd-party/googletest/googlemock/docs/README.md b/3rd-party/googletest/googlemock/docs/README.md
new file mode 100644
index 0000000..1bc57b7
--- /dev/null
+++ b/3rd-party/googletest/googlemock/docs/README.md
@@ -0,0 +1,4 @@
+# Content Moved
+
+We are working on updates to the GoogleTest documentation, which has moved to
+the top-level [docs](../../docs) directory.
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-actions.h b/3rd-party/googletest/googlemock/include/gmock/gmock-actions.h
new file mode 100644
index 0000000..aa47079
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-actions.h
@@ -0,0 +1,2360 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// The ACTION* family of macros can be used in a namespace scope to
+// define custom actions easily.  The syntax:
+//
+//   ACTION(name) { statements; }
+//
+// will define an action with the given name that executes the
+// statements.  The value returned by the statements will be used as
+// the return value of the action.  Inside the statements, you can
+// refer to the K-th (0-based) argument of the mock function by
+// 'argK', and refer to its type by 'argK_type'.  For example:
+//
+//   ACTION(IncrementArg1) {
+//     arg1_type temp = arg1;
+//     return ++(*temp);
+//   }
+//
+// allows you to write
+//
+//   ...WillOnce(IncrementArg1());
+//
+// You can also refer to the entire argument tuple and its type by
+// 'args' and 'args_type', and refer to the mock function type and its
+// return type by 'function_type' and 'return_type'.
+//
+// Note that you don't need to specify the types of the mock function
+// arguments.  However rest assured that your code is still type-safe:
+// you'll get a compiler error if *arg1 doesn't support the ++
+// operator, or if the type of ++(*arg1) isn't compatible with the
+// mock function's return type, for example.
+//
+// Sometimes you'll want to parameterize the action.   For that you can use
+// another macro:
+//
+//   ACTION_P(name, param_name) { statements; }
+//
+// For example:
+//
+//   ACTION_P(Add, n) { return arg0 + n; }
+//
+// will allow you to write:
+//
+//   ...WillOnce(Add(5));
+//
+// Note that you don't need to provide the type of the parameter
+// either.  If you need to reference the type of a parameter named
+// 'foo', you can write 'foo_type'.  For example, in the body of
+// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
+// of 'n'.
+//
+// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support
+// multi-parameter actions.
+//
+// For the purpose of typing, you can view
+//
+//   ACTION_Pk(Foo, p1, ..., pk) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// In particular, you can provide the template type arguments
+// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
+// although usually you can rely on the compiler to infer the types
+// for you automatically.  You can assign the result of expression
+// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
+// pk_type>.  This can be useful when composing actions.
+//
+// You can also overload actions with different numbers of parameters:
+//
+//   ACTION_P(Plus, a) { ... }
+//   ACTION_P2(Plus, a, b) { ... }
+//
+// While it's tempting to always use the ACTION* macros when defining
+// a new action, you should also consider implementing ActionInterface
+// or using MakePolymorphicAction() instead, especially if you need to
+// use the action a lot.  While these approaches require more work,
+// they give you more control on the types of the mock function
+// arguments and the action parameters, which in general leads to
+// better compiler error messages that pay off in the long run.  They
+// also allow overloading actions based on parameter types (as opposed
+// to just based on the number of parameters).
+//
+// CAVEAT:
+//
+// ACTION*() can only be used in a namespace scope as templates cannot be
+// declared inside of a local class.
+// Users can, however, define any local functors (e.g. a lambda) that
+// can be used as actions.
+//
+// MORE INFORMATION:
+//
+// To learn more about using these macros, please search for 'ACTION' on
+// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+
+#ifndef _WIN32_WCE
+#include <errno.h>
+#endif
+
+#include <algorithm>
+#include <exception>
+#include <functional>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gmock/internal/gmock-pp.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+
+namespace testing {
+
+// To implement an action Foo, define:
+//   1. a class FooAction that implements the ActionInterface interface, and
+//   2. a factory function that creates an Action object from a
+//      const FooAction*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Action objects can now be copied like plain values.
+
+namespace internal {
+
+// BuiltInDefaultValueGetter<T, true>::Get() returns a
+// default-constructed T value.  BuiltInDefaultValueGetter<T,
+// false>::Get() crashes with an error.
+//
+// This primary template is used when kDefaultConstructible is true.
+template <typename T, bool kDefaultConstructible>
+struct BuiltInDefaultValueGetter {
+  static T Get() { return T(); }
+};
+template <typename T>
+struct BuiltInDefaultValueGetter<T, false> {
+  static T Get() {
+    Assert(false, __FILE__, __LINE__,
+           "Default action undefined for the function return type.");
+#if defined(__GNUC__) || defined(__clang__)
+    __builtin_unreachable();
+#elif defined(_MSC_VER)
+    __assume(0);
+#else
+    return Invalid<T>();
+    // The above statement will never be reached, but is required in
+    // order for this function to compile.
+#endif
+  }
+};
+
+// BuiltInDefaultValue<T>::Get() returns the "built-in" default value
+// for type T, which is NULL when T is a raw pointer type, 0 when T is
+// a numeric type, false when T is bool, or "" when T is string or
+// std::string.  In addition, in C++11 and above, it turns a
+// default-constructed T value if T is default constructible.  For any
+// other type T, the built-in default T value is undefined, and the
+// function will abort the process.
+template <typename T>
+class BuiltInDefaultValue {
+ public:
+  // This function returns true if and only if type T has a built-in default
+  // value.
+  static bool Exists() { return ::std::is_default_constructible<T>::value; }
+
+  static T Get() {
+    return BuiltInDefaultValueGetter<
+        T, ::std::is_default_constructible<T>::value>::Get();
+  }
+};
+
+// This partial specialization says that we use the same built-in
+// default value for T and const T.
+template <typename T>
+class BuiltInDefaultValue<const T> {
+ public:
+  static bool Exists() { return BuiltInDefaultValue<T>::Exists(); }
+  static T Get() { return BuiltInDefaultValue<T>::Get(); }
+};
+
+// This partial specialization defines the default values for pointer
+// types.
+template <typename T>
+class BuiltInDefaultValue<T*> {
+ public:
+  static bool Exists() { return true; }
+  static T* Get() { return nullptr; }
+};
+
+// The following specializations define the default values for
+// specific types we care about.
+#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \
+  template <>                                                     \
+  class BuiltInDefaultValue<type> {                               \
+   public:                                                        \
+    static bool Exists() { return true; }                         \
+    static type Get() { return value; }                           \
+  }
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, );  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, "");
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
+
+// There's no need for a default action for signed wchar_t, as that
+// type is the same as wchar_t for gcc, and invalid for MSVC.
+//
+// There's also no need for a default action for unsigned wchar_t, as
+// that type is the same as unsigned int for gcc, and invalid for
+// MSVC.
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U);  // NOLINT
+#endif
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L);        // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long long, 0);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0);    // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0);
+
+#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_
+
+// Partial implementations of metaprogramming types from the standard library
+// not available in C++11.
+
+template <typename P>
+struct negation
+    // NOLINTNEXTLINE
+    : std::integral_constant<bool, bool(!P::value)> {};
+
+// Base case: with zero predicates the answer is always true.
+template <typename...>
+struct conjunction : std::true_type {};
+
+// With a single predicate, the answer is that predicate.
+template <typename P1>
+struct conjunction<P1> : P1 {};
+
+// With multiple predicates the answer is the first predicate if that is false,
+// and we recurse otherwise.
+template <typename P1, typename... Ps>
+struct conjunction<P1, Ps...>
+    : std::conditional<bool(P1::value), conjunction<Ps...>, P1>::type {};
+
+template <typename...>
+struct disjunction : std::false_type {};
+
+template <typename P1>
+struct disjunction<P1> : P1 {};
+
+template <typename P1, typename... Ps>
+struct disjunction<P1, Ps...>
+    // NOLINTNEXTLINE
+    : std::conditional<!bool(P1::value), disjunction<Ps...>, P1>::type {};
+
+template <typename...>
+using void_t = void;
+
+// Detects whether an expression of type `From` can be implicitly converted to
+// `To` according to [conv]. In C++17, [conv]/3 defines this as follows:
+//
+//     An expression e can be implicitly converted to a type T if and only if
+//     the declaration T t=e; is well-formed, for some invented temporary
+//     variable t ([dcl.init]).
+//
+// [conv]/2 implies we can use function argument passing to detect whether this
+// initialization is valid.
+//
+// Note that this is distinct from is_convertible, which requires this be valid:
+//
+//     To test() {
+//       return declval<From>();
+//     }
+//
+// In particular, is_convertible doesn't give the correct answer when `To` and
+// `From` are the same non-moveable type since `declval<From>` will be an rvalue
+// reference, defeating the guaranteed copy elision that would otherwise make
+// this function work.
+//
+// REQUIRES: `From` is not cv void.
+template <typename From, typename To>
+struct is_implicitly_convertible {
+ private:
+  // A function that accepts a parameter of type T. This can be called with type
+  // U successfully only if U is implicitly convertible to T.
+  template <typename T>
+  static void Accept(T);
+
+  // A function that creates a value of type T.
+  template <typename T>
+  static T Make();
+
+  // An overload be selected when implicit conversion from T to To is possible.
+  template <typename T, typename = decltype(Accept<To>(Make<T>()))>
+  static std::true_type TestImplicitConversion(int);
+
+  // A fallback overload selected in all other cases.
+  template <typename T>
+  static std::false_type TestImplicitConversion(...);
+
+ public:
+  using type = decltype(TestImplicitConversion<From>(0));
+  static constexpr bool value = type::value;
+};
+
+// Like std::invoke_result_t from C++17, but works only for objects with call
+// operators (not e.g. member function pointers, which we don't need specific
+// support for in OnceAction because std::function deals with them).
+template <typename F, typename... Args>
+using call_result_t = decltype(std::declval<F>()(std::declval<Args>()...));
+
+template <typename Void, typename R, typename F, typename... Args>
+struct is_callable_r_impl : std::false_type {};
+
+// Specialize the struct for those template arguments where call_result_t is
+// well-formed. When it's not, the generic template above is chosen, resulting
+// in std::false_type.
+template <typename R, typename F, typename... Args>
+struct is_callable_r_impl<void_t<call_result_t<F, Args...>>, R, F, Args...>
+    : std::conditional<
+          std::is_void<R>::value,  //
+          std::true_type,          //
+          is_implicitly_convertible<call_result_t<F, Args...>, R>>::type {};
+
+// Like std::is_invocable_r from C++17, but works only for objects with call
+// operators. See the note on call_result_t.
+template <typename R, typename F, typename... Args>
+using is_callable_r = is_callable_r_impl<void, R, F, Args...>;
+
+// Like std::as_const from C++17.
+template <typename T>
+typename std::add_const<T>::type& as_const(T& t) {
+  return t;
+}
+
+}  // namespace internal
+
+// Specialized for function types below.
+template <typename F>
+class OnceAction;
+
+// An action that can only be used once.
+//
+// This is accepted by WillOnce, which doesn't require the underlying action to
+// be copy-constructible (only move-constructible), and promises to invoke it as
+// an rvalue reference. This allows the action to work with move-only types like
+// std::move_only_function in a type-safe manner.
+//
+// For example:
+//
+//     // Assume we have some API that needs to accept a unique pointer to some
+//     // non-copyable object Foo.
+//     void AcceptUniquePointer(std::unique_ptr<Foo> foo);
+//
+//     // We can define an action that provides a Foo to that API. Because It
+//     // has to give away its unique pointer, it must not be called more than
+//     // once, so its call operator is &&-qualified.
+//     struct ProvideFoo {
+//       std::unique_ptr<Foo> foo;
+//
+//       void operator()() && {
+//         AcceptUniquePointer(std::move(Foo));
+//       }
+//     };
+//
+//     // This action can be used with WillOnce.
+//     EXPECT_CALL(mock, Call)
+//         .WillOnce(ProvideFoo{std::make_unique<Foo>(...)});
+//
+//     // But a call to WillRepeatedly will fail to compile. This is correct,
+//     // since the action cannot correctly be used repeatedly.
+//     EXPECT_CALL(mock, Call)
+//         .WillRepeatedly(ProvideFoo{std::make_unique<Foo>(...)});
+//
+// A less-contrived example would be an action that returns an arbitrary type,
+// whose &&-qualified call operator is capable of dealing with move-only types.
+template <typename Result, typename... Args>
+class OnceAction<Result(Args...)> final {
+ private:
+  // True iff we can use the given callable type (or lvalue reference) directly
+  // via StdFunctionAdaptor.
+  template <typename Callable>
+  using IsDirectlyCompatible = internal::conjunction<
+      // It must be possible to capture the callable in StdFunctionAdaptor.
+      std::is_constructible<typename std::decay<Callable>::type, Callable>,
+      // The callable must be compatible with our signature.
+      internal::is_callable_r<Result, typename std::decay<Callable>::type,
+                              Args...>>;
+
+  // True iff we can use the given callable type via StdFunctionAdaptor once we
+  // ignore incoming arguments.
+  template <typename Callable>
+  using IsCompatibleAfterIgnoringArguments = internal::conjunction<
+      // It must be possible to capture the callable in a lambda.
+      std::is_constructible<typename std::decay<Callable>::type, Callable>,
+      // The callable must be invocable with zero arguments, returning something
+      // convertible to Result.
+      internal::is_callable_r<Result, typename std::decay<Callable>::type>>;
+
+ public:
+  // Construct from a callable that is directly compatible with our mocked
+  // signature: it accepts our function type's arguments and returns something
+  // convertible to our result type.
+  template <typename Callable,
+            typename std::enable_if<
+                internal::conjunction<
+                    // Teach clang on macOS that we're not talking about a
+                    // copy/move constructor here. Otherwise it gets confused
+                    // when checking the is_constructible requirement of our
+                    // traits above.
+                    internal::negation<std::is_same<
+                        OnceAction, typename std::decay<Callable>::type>>,
+                    IsDirectlyCompatible<Callable>>  //
+                ::value,
+                int>::type = 0>
+  OnceAction(Callable&& callable)  // NOLINT
+      : function_(StdFunctionAdaptor<typename std::decay<Callable>::type>(
+            {}, std::forward<Callable>(callable))) {}
+
+  // As above, but for a callable that ignores the mocked function's arguments.
+  template <typename Callable,
+            typename std::enable_if<
+                internal::conjunction<
+                    // Teach clang on macOS that we're not talking about a
+                    // copy/move constructor here. Otherwise it gets confused
+                    // when checking the is_constructible requirement of our
+                    // traits above.
+                    internal::negation<std::is_same<
+                        OnceAction, typename std::decay<Callable>::type>>,
+                    // Exclude callables for which the overload above works.
+                    // We'd rather provide the arguments if possible.
+                    internal::negation<IsDirectlyCompatible<Callable>>,
+                    IsCompatibleAfterIgnoringArguments<Callable>>::value,
+                int>::type = 0>
+  OnceAction(Callable&& callable)  // NOLINT
+                                   // Call the constructor above with a callable
+                                   // that ignores the input arguments.
+      : OnceAction(IgnoreIncomingArguments<typename std::decay<Callable>::type>{
+            std::forward<Callable>(callable)}) {}
+
+  // We are naturally copyable because we store only an std::function, but
+  // semantically we should not be copyable.
+  OnceAction(const OnceAction&) = delete;
+  OnceAction& operator=(const OnceAction&) = delete;
+  OnceAction(OnceAction&&) = default;
+
+  // Invoke the underlying action callable with which we were constructed,
+  // handing it the supplied arguments.
+  Result Call(Args... args) && {
+    return function_(std::forward<Args>(args)...);
+  }
+
+ private:
+  // An adaptor that wraps a callable that is compatible with our signature and
+  // being invoked as an rvalue reference so that it can be used as an
+  // StdFunctionAdaptor. This throws away type safety, but that's fine because
+  // this is only used by WillOnce, which we know calls at most once.
+  //
+  // Once we have something like std::move_only_function from C++23, we can do
+  // away with this.
+  template <typename Callable>
+  class StdFunctionAdaptor final {
+   public:
+    // A tag indicating that the (otherwise universal) constructor is accepting
+    // the callable itself, instead of e.g. stealing calls for the move
+    // constructor.
+    struct CallableTag final {};
+
+    template <typename F>
+    explicit StdFunctionAdaptor(CallableTag, F&& callable)
+        : callable_(std::make_shared<Callable>(std::forward<F>(callable))) {}
+
+    // Rather than explicitly returning Result, we return whatever the wrapped
+    // callable returns. This allows for compatibility with existing uses like
+    // the following, when the mocked function returns void:
+    //
+    //     EXPECT_CALL(mock_fn_, Call)
+    //         .WillOnce([&] {
+    //            [...]
+    //            return 0;
+    //         });
+    //
+    // Such a callable can be turned into std::function<void()>. If we use an
+    // explicit return type of Result here then it *doesn't* work with
+    // std::function, because we'll get a "void function should not return a
+    // value" error.
+    //
+    // We need not worry about incompatible result types because the SFINAE on
+    // OnceAction already checks this for us. std::is_invocable_r_v itself makes
+    // the same allowance for void result types.
+    template <typename... ArgRefs>
+    internal::call_result_t<Callable, ArgRefs...> operator()(
+        ArgRefs&&... args) const {
+      return std::move(*callable_)(std::forward<ArgRefs>(args)...);
+    }
+
+   private:
+    // We must put the callable on the heap so that we are copyable, which
+    // std::function needs.
+    std::shared_ptr<Callable> callable_;
+  };
+
+  // An adaptor that makes a callable that accepts zero arguments callable with
+  // our mocked arguments.
+  template <typename Callable>
+  struct IgnoreIncomingArguments {
+    internal::call_result_t<Callable> operator()(Args&&...) {
+      return std::move(callable)();
+    }
+
+    Callable callable;
+  };
+
+  std::function<Result(Args...)> function_;
+};
+
+// When an unexpected function call is encountered, Google Mock will
+// let it return a default value if the user has specified one for its
+// return type, or if the return type has a built-in default value;
+// otherwise Google Mock won't know what value to return and will have
+// to abort the process.
+//
+// The DefaultValue<T> class allows a user to specify the
+// default value for a type T that is both copyable and publicly
+// destructible (i.e. anything that can be used as a function return
+// type).  The usage is:
+//
+//   // Sets the default value for type T to be foo.
+//   DefaultValue<T>::Set(foo);
+template <typename T>
+class DefaultValue {
+ public:
+  // Sets the default value for type T; requires T to be
+  // copy-constructable and have a public destructor.
+  static void Set(T x) {
+    delete producer_;
+    producer_ = new FixedValueProducer(x);
+  }
+
+  // Provides a factory function to be called to generate the default value.
+  // This method can be used even if T is only move-constructible, but it is not
+  // limited to that case.
+  typedef T (*FactoryFunction)();
+  static void SetFactory(FactoryFunction factory) {
+    delete producer_;
+    producer_ = new FactoryValueProducer(factory);
+  }
+
+  // Unsets the default value for type T.
+  static void Clear() {
+    delete producer_;
+    producer_ = nullptr;
+  }
+
+  // Returns true if and only if the user has set the default value for type T.
+  static bool IsSet() { return producer_ != nullptr; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T>::Exists();
+  }
+
+  // Returns the default value for type T if the user has set one;
+  // otherwise returns the built-in default value. Requires that Exists()
+  // is true, which ensures that the return value is well-defined.
+  static T Get() {
+    return producer_ == nullptr ? internal::BuiltInDefaultValue<T>::Get()
+                                : producer_->Produce();
+  }
+
+ private:
+  class ValueProducer {
+   public:
+    virtual ~ValueProducer() = default;
+    virtual T Produce() = 0;
+  };
+
+  class FixedValueProducer : public ValueProducer {
+   public:
+    explicit FixedValueProducer(T value) : value_(value) {}
+    T Produce() override { return value_; }
+
+   private:
+    const T value_;
+    FixedValueProducer(const FixedValueProducer&) = delete;
+    FixedValueProducer& operator=(const FixedValueProducer&) = delete;
+  };
+
+  class FactoryValueProducer : public ValueProducer {
+   public:
+    explicit FactoryValueProducer(FactoryFunction factory)
+        : factory_(factory) {}
+    T Produce() override { return factory_(); }
+
+   private:
+    const FactoryFunction factory_;
+    FactoryValueProducer(const FactoryValueProducer&) = delete;
+    FactoryValueProducer& operator=(const FactoryValueProducer&) = delete;
+  };
+
+  static ValueProducer* producer_;
+};
+
+// This partial specialization allows a user to set default values for
+// reference types.
+template <typename T>
+class DefaultValue<T&> {
+ public:
+  // Sets the default value for type T&.
+  static void Set(T& x) {  // NOLINT
+    address_ = &x;
+  }
+
+  // Unsets the default value for type T&.
+  static void Clear() { address_ = nullptr; }
+
+  // Returns true if and only if the user has set the default value for type T&.
+  static bool IsSet() { return address_ != nullptr; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T&>::Exists();
+  }
+
+  // Returns the default value for type T& if the user has set one;
+  // otherwise returns the built-in default value if there is one;
+  // otherwise aborts the process.
+  static T& Get() {
+    return address_ == nullptr ? internal::BuiltInDefaultValue<T&>::Get()
+                               : *address_;
+  }
+
+ private:
+  static T* address_;
+};
+
+// This specialization allows DefaultValue<void>::Get() to
+// compile.
+template <>
+class DefaultValue<void> {
+ public:
+  static bool Exists() { return true; }
+  static void Get() {}
+};
+
+// Points to the user-set default value for type T.
+template <typename T>
+typename DefaultValue<T>::ValueProducer* DefaultValue<T>::producer_ = nullptr;
+
+// Points to the user-set default value for type T&.
+template <typename T>
+T* DefaultValue<T&>::address_ = nullptr;
+
+// Implement this interface to define an action for function type F.
+template <typename F>
+class ActionInterface {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  ActionInterface() = default;
+  virtual ~ActionInterface() = default;
+
+  // Performs the action.  This method is not const, as in general an
+  // action can have side effects and be stateful.  For example, a
+  // get-the-next-element-from-the-collection action will need to
+  // remember the current element.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+
+ private:
+  ActionInterface(const ActionInterface&) = delete;
+  ActionInterface& operator=(const ActionInterface&) = delete;
+};
+
+template <typename F>
+class Action;
+
+// An Action<R(Args...)> is a copyable and IMMUTABLE (except by assignment)
+// object that represents an action to be taken when a mock function of type
+// R(Args...) is called. The implementation of Action<T> is just a
+// std::shared_ptr to const ActionInterface<T>. Don't inherit from Action! You
+// can view an object implementing ActionInterface<F> as a concrete action
+// (including its current state), and an Action<F> object as a handle to it.
+template <typename R, typename... Args>
+class Action<R(Args...)> {
+ private:
+  using F = R(Args...);
+
+  // Adapter class to allow constructing Action from a legacy ActionInterface.
+  // New code should create Actions from functors instead.
+  struct ActionAdapter {
+    // Adapter must be copyable to satisfy std::function requirements.
+    ::std::shared_ptr<ActionInterface<F>> impl_;
+
+    template <typename... InArgs>
+    typename internal::Function<F>::Result operator()(InArgs&&... args) {
+      return impl_->Perform(
+          ::std::forward_as_tuple(::std::forward<InArgs>(args)...));
+    }
+  };
+
+  template <typename G>
+  using IsCompatibleFunctor = std::is_constructible<std::function<F>, G>;
+
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  // Constructs a null Action.  Needed for storing Action objects in
+  // STL containers.
+  Action() = default;
+
+  // Construct an Action from a specified callable.
+  // This cannot take std::function directly, because then Action would not be
+  // directly constructible from lambda (it would require two conversions).
+  template <
+      typename G,
+      typename = typename std::enable_if<internal::disjunction<
+          IsCompatibleFunctor<G>, std::is_constructible<std::function<Result()>,
+                                                        G>>::value>::type>
+  Action(G&& fun) {  // NOLINT
+    Init(::std::forward<G>(fun), IsCompatibleFunctor<G>());
+  }
+
+  // Constructs an Action from its implementation.
+  explicit Action(ActionInterface<F>* impl)
+      : fun_(ActionAdapter{::std::shared_ptr<ActionInterface<F>>(impl)}) {}
+
+  // This constructor allows us to turn an Action<Func> object into an
+  // Action<F>, as long as F's arguments can be implicitly converted
+  // to Func's and Func's return type can be implicitly converted to F's.
+  template <typename Func>
+  Action(const Action<Func>& action)  // NOLINT
+      : fun_(action.fun_) {}
+
+  // Returns true if and only if this is the DoDefault() action.
+  bool IsDoDefault() const { return fun_ == nullptr; }
+
+  // Performs the action.  Note that this method is const even though
+  // the corresponding method in ActionInterface is not.  The reason
+  // is that a const Action<F> means that it cannot be re-bound to
+  // another concrete action, not that the concrete action it binds to
+  // cannot change state.  (Think of the difference between a const
+  // pointer and a pointer to const.)
+  Result Perform(ArgumentTuple args) const {
+    if (IsDoDefault()) {
+      internal::IllegalDoDefault(__FILE__, __LINE__);
+    }
+    return internal::Apply(fun_, ::std::move(args));
+  }
+
+  // An action can be used as a OnceAction, since it's obviously safe to call it
+  // once.
+  operator OnceAction<F>() const {  // NOLINT
+    // Return a OnceAction-compatible callable that calls Perform with the
+    // arguments it is provided. We could instead just return fun_, but then
+    // we'd need to handle the IsDoDefault() case separately.
+    struct OA {
+      Action<F> action;
+
+      R operator()(Args... args) && {
+        return action.Perform(
+            std::forward_as_tuple(std::forward<Args>(args)...));
+      }
+    };
+
+    return OA{*this};
+  }
+
+ private:
+  template <typename G>
+  friend class Action;
+
+  template <typename G>
+  void Init(G&& g, ::std::true_type) {
+    fun_ = ::std::forward<G>(g);
+  }
+
+  template <typename G>
+  void Init(G&& g, ::std::false_type) {
+    fun_ = IgnoreArgs<typename ::std::decay<G>::type>{::std::forward<G>(g)};
+  }
+
+  template <typename FunctionImpl>
+  struct IgnoreArgs {
+    template <typename... InArgs>
+    Result operator()(const InArgs&...) const {
+      return function_impl();
+    }
+
+    FunctionImpl function_impl;
+  };
+
+  // fun_ is an empty function if and only if this is the DoDefault() action.
+  ::std::function<F> fun_;
+};
+
+// The PolymorphicAction class template makes it easy to implement a
+// polymorphic action (i.e. an action that can be used in mock
+// functions of than one type, e.g. Return()).
+//
+// To define a polymorphic action, a user first provides a COPYABLE
+// implementation class that has a Perform() method template:
+//
+//   class FooAction {
+//    public:
+//     template <typename Result, typename ArgumentTuple>
+//     Result Perform(const ArgumentTuple& args) const {
+//       // Processes the arguments and returns a result, using
+//       // std::get<N>(args) to get the N-th (0-based) argument in the tuple.
+//     }
+//     ...
+//   };
+//
+// Then the user creates the polymorphic action using
+// MakePolymorphicAction(object) where object has type FooAction.  See
+// the definition of Return(void) and SetArgumentPointee<N>(value) for
+// complete examples.
+template <typename Impl>
+class PolymorphicAction {
+ public:
+  explicit PolymorphicAction(const Impl& impl) : impl_(impl) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new MonomorphicImpl<F>(impl_));
+  }
+
+ private:
+  template <typename F>
+  class MonomorphicImpl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    Result Perform(const ArgumentTuple& args) override {
+      return impl_.template Perform<Result>(args);
+    }
+
+   private:
+    Impl impl_;
+  };
+
+  Impl impl_;
+};
+
+// Creates an Action from its implementation and returns it.  The
+// created Action object owns the implementation.
+template <typename F>
+Action<F> MakeAction(ActionInterface<F>* impl) {
+  return Action<F>(impl);
+}
+
+// Creates a polymorphic action from its implementation.  This is
+// easier to use than the PolymorphicAction<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicAction(foo);
+// vs
+//   PolymorphicAction<TypeOfFoo>(foo);
+template <typename Impl>
+inline PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl) {
+  return PolymorphicAction<Impl>(impl);
+}
+
+namespace internal {
+
+// Helper struct to specialize ReturnAction to execute a move instead of a copy
+// on return. Useful for move-only types, but could be used on any type.
+template <typename T>
+struct ByMoveWrapper {
+  explicit ByMoveWrapper(T value) : payload(std::move(value)) {}
+  T payload;
+};
+
+// The general implementation of Return(R). Specializations follow below.
+template <typename R>
+class ReturnAction final {
+ public:
+  explicit ReturnAction(R value) : value_(std::move(value)) {}
+
+  template <typename U, typename... Args,
+            typename = typename std::enable_if<conjunction<
+                // See the requirements documented on Return.
+                negation<std::is_same<void, U>>,  //
+                negation<std::is_reference<U>>,   //
+                std::is_convertible<R, U>,        //
+                std::is_move_constructible<U>>::value>::type>
+  operator OnceAction<U(Args...)>() && {  // NOLINT
+    return Impl<U>(std::move(value_));
+  }
+
+  template <typename U, typename... Args,
+            typename = typename std::enable_if<conjunction<
+                // See the requirements documented on Return.
+                negation<std::is_same<void, U>>,   //
+                negation<std::is_reference<U>>,    //
+                std::is_convertible<const R&, U>,  //
+                std::is_copy_constructible<U>>::value>::type>
+  operator Action<U(Args...)>() const {  // NOLINT
+    return Impl<U>(value_);
+  }
+
+ private:
+  // Implements the Return(x) action for a mock function that returns type U.
+  template <typename U>
+  class Impl final {
+   public:
+    // The constructor used when the return value is allowed to move from the
+    // input value (i.e. we are converting to OnceAction).
+    explicit Impl(R&& input_value)
+        : state_(new State(std::move(input_value))) {}
+
+    // The constructor used when the return value is not allowed to move from
+    // the input value (i.e. we are converting to Action).
+    explicit Impl(const R& input_value) : state_(new State(input_value)) {}
+
+    U operator()() && { return std::move(state_->value); }
+    U operator()() const& { return state_->value; }
+
+   private:
+    // We put our state on the heap so that the compiler-generated copy/move
+    // constructors work correctly even when U is a reference-like type. This is
+    // necessary only because we eagerly create State::value (see the note on
+    // that symbol for details). If we instead had only the input value as a
+    // member then the default constructors would work fine.
+    //
+    // For example, when R is std::string and U is std::string_view, value is a
+    // reference to the string backed by input_value. The copy constructor would
+    // copy both, so that we wind up with a new input_value object (with the
+    // same contents) and a reference to the *old* input_value object rather
+    // than the new one.
+    struct State {
+      explicit State(const R& input_value_in)
+          : input_value(input_value_in),
+            // Make an implicit conversion to Result before initializing the U
+            // object we store, avoiding calling any explicit constructor of U
+            // from R.
+            //
+            // This simulates the language rules: a function with return type U
+            // that does `return R()` requires R to be implicitly convertible to
+            // U, and uses that path for the conversion, even U Result has an
+            // explicit constructor from R.
+            value(ImplicitCast_<U>(internal::as_const(input_value))) {}
+
+      // As above, but for the case where we're moving from the ReturnAction
+      // object because it's being used as a OnceAction.
+      explicit State(R&& input_value_in)
+          : input_value(std::move(input_value_in)),
+            // For the same reason as above we make an implicit conversion to U
+            // before initializing the value.
+            //
+            // Unlike above we provide the input value as an rvalue to the
+            // implicit conversion because this is a OnceAction: it's fine if it
+            // wants to consume the input value.
+            value(ImplicitCast_<U>(std::move(input_value))) {}
+
+      // A copy of the value originally provided by the user. We retain this in
+      // addition to the value of the mock function's result type below in case
+      // the latter is a reference-like type. See the std::string_view example
+      // in the documentation on Return.
+      R input_value;
+
+      // The value we actually return, as the type returned by the mock function
+      // itself.
+      //
+      // We eagerly initialize this here, rather than lazily doing the implicit
+      // conversion automatically each time Perform is called, for historical
+      // reasons: in 2009-11, commit a070cbd91c (Google changelist 13540126)
+      // made the Action<U()> conversion operator eagerly convert the R value to
+      // U, but without keeping the R alive. This broke the use case discussed
+      // in the documentation for Return, making reference-like types such as
+      // std::string_view not safe to use as U where the input type R is a
+      // value-like type such as std::string.
+      //
+      // The example the commit gave was not very clear, nor was the issue
+      // thread (https://github.com/google/googlemock/issues/86), but it seems
+      // the worry was about reference-like input types R that flatten to a
+      // value-like type U when being implicitly converted. An example of this
+      // is std::vector<bool>::reference, which is often a proxy type with an
+      // reference to the underlying vector:
+      //
+      //     // Helper method: have the mock function return bools according
+      //     // to the supplied script.
+      //     void SetActions(MockFunction<bool(size_t)>& mock,
+      //                     const std::vector<bool>& script) {
+      //       for (size_t i = 0; i < script.size(); ++i) {
+      //         EXPECT_CALL(mock, Call(i)).WillOnce(Return(script[i]));
+      //       }
+      //     }
+      //
+      //     TEST(Foo, Bar) {
+      //       // Set actions using a temporary vector, whose operator[]
+      //       // returns proxy objects that references that will be
+      //       // dangling once the call to SetActions finishes and the
+      //       // vector is destroyed.
+      //       MockFunction<bool(size_t)> mock;
+      //       SetActions(mock, {false, true});
+      //
+      //       EXPECT_FALSE(mock.AsStdFunction()(0));
+      //       EXPECT_TRUE(mock.AsStdFunction()(1));
+      //     }
+      //
+      // This eager conversion helps with a simple case like this, but doesn't
+      // fully make these types work in general. For example the following still
+      // uses a dangling reference:
+      //
+      //     TEST(Foo, Baz) {
+      //       MockFunction<std::vector<std::string>()> mock;
+      //
+      //       // Return the same vector twice, and then the empty vector
+      //       // thereafter.
+      //       auto action = Return(std::initializer_list<std::string>{
+      //           "taco", "burrito",
+      //       });
+      //
+      //       EXPECT_CALL(mock, Call)
+      //           .WillOnce(action)
+      //           .WillOnce(action)
+      //           .WillRepeatedly(Return(std::vector<std::string>{}));
+      //
+      //       EXPECT_THAT(mock.AsStdFunction()(),
+      //                   ElementsAre("taco", "burrito"));
+      //       EXPECT_THAT(mock.AsStdFunction()(),
+      //                   ElementsAre("taco", "burrito"));
+      //       EXPECT_THAT(mock.AsStdFunction()(), IsEmpty());
+      //     }
+      //
+      U value;
+    };
+
+    const std::shared_ptr<State> state_;
+  };
+
+  R value_;
+};
+
+// A specialization of ReturnAction<R> when R is ByMoveWrapper<T> for some T.
+//
+// This version applies the type system-defeating hack of moving from T even in
+// the const call operator, checking at runtime that it isn't called more than
+// once, since the user has declared their intent to do so by using ByMove.
+template <typename T>
+class ReturnAction<ByMoveWrapper<T>> final {
+ public:
+  explicit ReturnAction(ByMoveWrapper<T> wrapper)
+      : state_(new State(std::move(wrapper.payload))) {}
+
+  T operator()() const {
+    GTEST_CHECK_(!state_->called)
+        << "A ByMove() action must be performed at most once.";
+
+    state_->called = true;
+    return std::move(state_->value);
+  }
+
+ private:
+  // We store our state on the heap so that we are copyable as required by
+  // Action, despite the fact that we are stateful and T may not be copyable.
+  struct State {
+    explicit State(T&& value_in) : value(std::move(value_in)) {}
+
+    T value;
+    bool called = false;
+  };
+
+  const std::shared_ptr<State> state_;
+};
+
+// Implements the ReturnNull() action.
+class ReturnNullAction {
+ public:
+  // Allows ReturnNull() to be used in any pointer-returning function. In C++11
+  // this is enforced by returning nullptr, and in non-C++11 by asserting a
+  // pointer type on compile time.
+  template <typename Result, typename ArgumentTuple>
+  static Result Perform(const ArgumentTuple&) {
+    return nullptr;
+  }
+};
+
+// Implements the Return() action.
+class ReturnVoidAction {
+ public:
+  // Allows Return() to be used in any void-returning function.
+  template <typename Result, typename ArgumentTuple>
+  static void Perform(const ArgumentTuple&) {
+    static_assert(std::is_void<Result>::value, "Result should be void.");
+  }
+};
+
+// Implements the polymorphic ReturnRef(x) action, which can be used
+// in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefAction {
+ public:
+  // Constructs a ReturnRefAction object from the reference to be returned.
+  explicit ReturnRefAction(T& ref) : ref_(ref) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRef(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRef(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    static_assert(std::is_reference<Result>::value,
+                  "use Return instead of ReturnRef to return a value");
+    return Action<F>(new Impl<F>(ref_));
+  }
+
+ private:
+  // Implements the ReturnRef(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(T& ref) : ref_(ref) {}  // NOLINT
+
+    Result Perform(const ArgumentTuple&) override { return ref_; }
+
+   private:
+    T& ref_;
+  };
+
+  T& ref_;
+};
+
+// Implements the polymorphic ReturnRefOfCopy(x) action, which can be
+// used in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefOfCopyAction {
+ public:
+  // Constructs a ReturnRefOfCopyAction object from the reference to
+  // be returned.
+  explicit ReturnRefOfCopyAction(const T& value) : value_(value) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRefOfCopy(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRefOfCopy(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    static_assert(std::is_reference<Result>::value,
+                  "use Return instead of ReturnRefOfCopy to return a value");
+    return Action<F>(new Impl<F>(value_));
+  }
+
+ private:
+  // Implements the ReturnRefOfCopy(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const T& value) : value_(value) {}  // NOLINT
+
+    Result Perform(const ArgumentTuple&) override { return value_; }
+
+   private:
+    T value_;
+  };
+
+  const T value_;
+};
+
+// Implements the polymorphic ReturnRoundRobin(v) action, which can be
+// used in any function that returns the element_type of v.
+template <typename T>
+class ReturnRoundRobinAction {
+ public:
+  explicit ReturnRoundRobinAction(std::vector<T> values) {
+    GTEST_CHECK_(!values.empty())
+        << "ReturnRoundRobin requires at least one element.";
+    state_->values = std::move(values);
+  }
+
+  template <typename... Args>
+  T operator()(Args&&...) const {
+    return state_->Next();
+  }
+
+ private:
+  struct State {
+    T Next() {
+      T ret_val = values[i++];
+      if (i == values.size()) i = 0;
+      return ret_val;
+    }
+
+    std::vector<T> values;
+    size_t i = 0;
+  };
+  std::shared_ptr<State> state_ = std::make_shared<State>();
+};
+
+// Implements the polymorphic DoDefault() action.
+class DoDefaultAction {
+ public:
+  // This template type conversion operator allows DoDefault() to be
+  // used in any function.
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>();
+  }  // NOLINT
+};
+
+// Implements the Assign action to set a given pointer referent to a
+// particular value.
+template <typename T1, typename T2>
+class AssignAction {
+ public:
+  AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& /* args */) const {
+    *ptr_ = value_;
+  }
+
+ private:
+  T1* const ptr_;
+  const T2 value_;
+};
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetErrnoAndReturn action to simulate return from
+// various system calls and libc functions.
+template <typename T>
+class SetErrnoAndReturnAction {
+ public:
+  SetErrnoAndReturnAction(int errno_value, T result)
+      : errno_(errno_value), result_(result) {}
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& /* args */) const {
+    errno = errno_;
+    return result_;
+  }
+
+ private:
+  const int errno_;
+  const T result_;
+};
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetArgumentPointee<N>(x) action for any function
+// whose N-th argument (0-based) is a pointer to x's type.
+template <size_t N, typename A, typename = void>
+struct SetArgumentPointeeAction {
+  A value;
+
+  template <typename... Args>
+  void operator()(const Args&... args) const {
+    *::std::get<N>(std::tie(args...)) = value;
+  }
+};
+
+// Implements the Invoke(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+struct InvokeMethodAction {
+  Class* const obj_ptr;
+  const MethodPtr method_ptr;
+
+  template <typename... Args>
+  auto operator()(Args&&... args) const
+      -> decltype((obj_ptr->*method_ptr)(std::forward<Args>(args)...)) {
+    return (obj_ptr->*method_ptr)(std::forward<Args>(args)...);
+  }
+};
+
+// Implements the InvokeWithoutArgs(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  InvokeWithoutArgs(f) can be used as an
+// Action<F> as long as f's type is compatible with F.
+template <typename FunctionImpl>
+struct InvokeWithoutArgsAction {
+  FunctionImpl function_impl;
+
+  // Allows InvokeWithoutArgs(f) to be used as any action whose type is
+  // compatible with f.
+  template <typename... Args>
+  auto operator()(const Args&...) -> decltype(function_impl()) {
+    return function_impl();
+  }
+};
+
+// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+struct InvokeMethodWithoutArgsAction {
+  Class* const obj_ptr;
+  const MethodPtr method_ptr;
+
+  using ReturnType =
+      decltype((std::declval<Class*>()->*std::declval<MethodPtr>())());
+
+  template <typename... Args>
+  ReturnType operator()(const Args&...) const {
+    return (obj_ptr->*method_ptr)();
+  }
+};
+
+// Implements the IgnoreResult(action) action.
+template <typename A>
+class IgnoreResultAction {
+ public:
+  explicit IgnoreResultAction(const A& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename internal::Function<F>::Result Result;
+
+    // Asserts at compile time that F returns void.
+    static_assert(std::is_void<Result>::value, "Result type should be void.");
+
+    return Action<F>(new Impl<F>(action_));
+  }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const A& action) : action_(action) {}
+
+    void Perform(const ArgumentTuple& args) override {
+      // Performs the action and ignores its result.
+      action_.Perform(args);
+    }
+
+   private:
+    // Type OriginalFunction is the same as F except that its return
+    // type is IgnoredValue.
+    typedef
+        typename internal::Function<F>::MakeResultIgnoredValue OriginalFunction;
+
+    const Action<OriginalFunction> action_;
+  };
+
+  const A action_;
+};
+
+template <typename InnerAction, size_t... I>
+struct WithArgsAction {
+  InnerAction inner_action;
+
+  // The signature of the function as seen by the inner action, given an out
+  // action with the given result and argument types.
+  template <typename R, typename... Args>
+  using InnerSignature =
+      R(typename std::tuple_element<I, std::tuple<Args...>>::type...);
+
+  // Rather than a call operator, we must define conversion operators to
+  // particular action types. This is necessary for embedded actions like
+  // DoDefault(), which rely on an action conversion operators rather than
+  // providing a call operator because even with a particular set of arguments
+  // they don't have a fixed return type.
+
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          std::is_convertible<InnerAction,
+                              // Unfortunately we can't use the InnerSignature
+                              // alias here; MSVC complains about the I
+                              // parameter pack not being expanded (error C3520)
+                              // despite it being expanded in the type alias.
+                              // TupleElement is also an MSVC workaround.
+                              // See its definition for details.
+                              OnceAction<R(internal::TupleElement<
+                                           I, std::tuple<Args...>>...)>>::value,
+          int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    struct OA {
+      OnceAction<InnerSignature<R, Args...>> inner_action;
+
+      R operator()(Args&&... args) && {
+        return std::move(inner_action)
+            .Call(std::get<I>(
+                std::forward_as_tuple(std::forward<Args>(args)...))...);
+      }
+    };
+
+    return OA{std::move(inner_action)};
+  }
+
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          std::is_convertible<const InnerAction&,
+                              // Unfortunately we can't use the InnerSignature
+                              // alias here; MSVC complains about the I
+                              // parameter pack not being expanded (error C3520)
+                              // despite it being expanded in the type alias.
+                              // TupleElement is also an MSVC workaround.
+                              // See its definition for details.
+                              Action<R(internal::TupleElement<
+                                       I, std::tuple<Args...>>...)>>::value,
+          int>::type = 0>
+  operator Action<R(Args...)>() const {  // NOLINT
+    Action<InnerSignature<R, Args...>> converted(inner_action);
+
+    return [converted](Args&&... args) -> R {
+      return converted.Perform(std::forward_as_tuple(
+          std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...))...));
+    };
+  }
+};
+
+template <typename... Actions>
+class DoAllAction;
+
+// Base case: only a single action.
+template <typename FinalAction>
+class DoAllAction<FinalAction> {
+ public:
+  struct UserConstructorTag {};
+
+  template <typename T>
+  explicit DoAllAction(UserConstructorTag, T&& action)
+      : final_action_(std::forward<T>(action)) {}
+
+  // Rather than a call operator, we must define conversion operators to
+  // particular action types. This is necessary for embedded actions like
+  // DoDefault(), which rely on an action conversion operators rather than
+  // providing a call operator because even with a particular set of arguments
+  // they don't have a fixed return type.
+
+  // We support conversion to OnceAction whenever the sub-action does.
+  template <typename R, typename... Args,
+            typename std::enable_if<
+                std::is_convertible<FinalAction, OnceAction<R(Args...)>>::value,
+                int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    return std::move(final_action_);
+  }
+
+  // We also support conversion to OnceAction whenever the sub-action supports
+  // conversion to Action (since any Action can also be a OnceAction).
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<
+              negation<
+                  std::is_convertible<FinalAction, OnceAction<R(Args...)>>>,
+              std::is_convertible<FinalAction, Action<R(Args...)>>>::value,
+          int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    return Action<R(Args...)>(std::move(final_action_));
+  }
+
+  // We support conversion to Action whenever the sub-action does.
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          std::is_convertible<const FinalAction&, Action<R(Args...)>>::value,
+          int>::type = 0>
+  operator Action<R(Args...)>() const {  // NOLINT
+    return final_action_;
+  }
+
+ private:
+  FinalAction final_action_;
+};
+
+// Recursive case: support N actions by calling the initial action and then
+// calling through to the base class containing N-1 actions.
+template <typename InitialAction, typename... OtherActions>
+class DoAllAction<InitialAction, OtherActions...>
+    : private DoAllAction<OtherActions...> {
+ private:
+  using Base = DoAllAction<OtherActions...>;
+
+  // The type of reference that should be provided to an initial action for a
+  // mocked function parameter of type T.
+  //
+  // There are two quirks here:
+  //
+  //  *  Unlike most forwarding functions, we pass scalars through by value.
+  //     This isn't strictly necessary because an lvalue reference would work
+  //     fine too and be consistent with other non-reference types, but it's
+  //     perhaps less surprising.
+  //
+  //     For example if the mocked function has signature void(int), then it
+  //     might seem surprising for the user's initial action to need to be
+  //     convertible to Action<void(const int&)>. This is perhaps less
+  //     surprising for a non-scalar type where there may be a performance
+  //     impact, or it might even be impossible, to pass by value.
+  //
+  //  *  More surprisingly, `const T&` is often not a const reference type.
+  //     By the reference collapsing rules in C++17 [dcl.ref]/6, if T refers to
+  //     U& or U&& for some non-scalar type U, then InitialActionArgType<T> is
+  //     U&. In other words, we may hand over a non-const reference.
+  //
+  //     So for example, given some non-scalar type Obj we have the following
+  //     mappings:
+  //
+  //            T               InitialActionArgType<T>
+  //         -------            -----------------------
+  //         Obj                const Obj&
+  //         Obj&               Obj&
+  //         Obj&&              Obj&
+  //         const Obj          const Obj&
+  //         const Obj&         const Obj&
+  //         const Obj&&        const Obj&
+  //
+  //     In other words, the initial actions get a mutable view of an non-scalar
+  //     argument if and only if the mock function itself accepts a non-const
+  //     reference type. They are never given an rvalue reference to an
+  //     non-scalar type.
+  //
+  //     This situation makes sense if you imagine use with a matcher that is
+  //     designed to write through a reference. For example, if the caller wants
+  //     to fill in a reference argument and then return a canned value:
+  //
+  //         EXPECT_CALL(mock, Call)
+  //             .WillOnce(DoAll(SetArgReferee<0>(17), Return(19)));
+  //
+  template <typename T>
+  using InitialActionArgType =
+      typename std::conditional<std::is_scalar<T>::value, T, const T&>::type;
+
+ public:
+  struct UserConstructorTag {};
+
+  template <typename T, typename... U>
+  explicit DoAllAction(UserConstructorTag, T&& initial_action,
+                       U&&... other_actions)
+      : Base({}, std::forward<U>(other_actions)...),
+        initial_action_(std::forward<T>(initial_action)) {}
+
+  // We support conversion to OnceAction whenever both the initial action and
+  // the rest support conversion to OnceAction.
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<std::is_convertible<
+                          InitialAction,
+                          OnceAction<void(InitialActionArgType<Args>...)>>,
+                      std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
+          int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    // Return an action that first calls the initial action with arguments
+    // filtered through InitialActionArgType, then forwards arguments directly
+    // to the base class to deal with the remaining actions.
+    struct OA {
+      OnceAction<void(InitialActionArgType<Args>...)> initial_action;
+      OnceAction<R(Args...)> remaining_actions;
+
+      R operator()(Args... args) && {
+        std::move(initial_action)
+            .Call(static_cast<InitialActionArgType<Args>>(args)...);
+
+        return std::move(remaining_actions).Call(std::forward<Args>(args)...);
+      }
+    };
+
+    return OA{
+        std::move(initial_action_),
+        std::move(static_cast<Base&>(*this)),
+    };
+  }
+
+  // We also support conversion to OnceAction whenever the initial action
+  // supports conversion to Action (since any Action can also be a OnceAction).
+  //
+  // The remaining sub-actions must also be compatible, but we don't need to
+  // special case them because the base class deals with them.
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<
+              negation<std::is_convertible<
+                  InitialAction,
+                  OnceAction<void(InitialActionArgType<Args>...)>>>,
+              std::is_convertible<InitialAction,
+                                  Action<void(InitialActionArgType<Args>...)>>,
+              std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
+          int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    return DoAll(
+        Action<void(InitialActionArgType<Args>...)>(std::move(initial_action_)),
+        std::move(static_cast<Base&>(*this)));
+  }
+
+  // We support conversion to Action whenever both the initial action and the
+  // rest support conversion to Action.
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<
+              std::is_convertible<const InitialAction&,
+                                  Action<void(InitialActionArgType<Args>...)>>,
+              std::is_convertible<const Base&, Action<R(Args...)>>>::value,
+          int>::type = 0>
+  operator Action<R(Args...)>() const {  // NOLINT
+    // Return an action that first calls the initial action with arguments
+    // filtered through InitialActionArgType, then forwards arguments directly
+    // to the base class to deal with the remaining actions.
+    struct OA {
+      Action<void(InitialActionArgType<Args>...)> initial_action;
+      Action<R(Args...)> remaining_actions;
+
+      R operator()(Args... args) const {
+        initial_action.Perform(std::forward_as_tuple(
+            static_cast<InitialActionArgType<Args>>(args)...));
+
+        return remaining_actions.Perform(
+            std::forward_as_tuple(std::forward<Args>(args)...));
+      }
+    };
+
+    return OA{
+        initial_action_,
+        static_cast<const Base&>(*this),
+    };
+  }
+
+ private:
+  InitialAction initial_action_;
+};
+
+template <typename T, typename... Params>
+struct ReturnNewAction {
+  T* operator()() const {
+    return internal::Apply(
+        [](const Params&... unpacked_params) {
+          return new T(unpacked_params...);
+        },
+        params);
+  }
+  std::tuple<Params...> params;
+};
+
+template <size_t k>
+struct ReturnArgAction {
+  template <typename... Args,
+            typename = typename std::enable_if<(k < sizeof...(Args))>::type>
+  auto operator()(Args&&... args) const
+      -> decltype(std::get<k>(
+          std::forward_as_tuple(std::forward<Args>(args)...))) {
+    return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
+  }
+};
+
+template <size_t k, typename Ptr>
+struct SaveArgAction {
+  Ptr pointer;
+
+  template <typename... Args>
+  void operator()(const Args&... args) const {
+    *pointer = std::get<k>(std::tie(args...));
+  }
+};
+
+template <size_t k, typename Ptr>
+struct SaveArgPointeeAction {
+  Ptr pointer;
+
+  template <typename... Args>
+  void operator()(const Args&... args) const {
+    *pointer = *std::get<k>(std::tie(args...));
+  }
+};
+
+template <size_t k, typename T>
+struct SetArgRefereeAction {
+  T value;
+
+  template <typename... Args>
+  void operator()(Args&&... args) const {
+    using argk_type =
+        typename ::std::tuple_element<k, std::tuple<Args...>>::type;
+    static_assert(std::is_lvalue_reference<argk_type>::value,
+                  "Argument must be a reference type.");
+    std::get<k>(std::tie(args...)) = value;
+  }
+};
+
+template <size_t k, typename I1, typename I2>
+struct SetArrayArgumentAction {
+  I1 first;
+  I2 last;
+
+  template <typename... Args>
+  void operator()(const Args&... args) const {
+    auto value = std::get<k>(std::tie(args...));
+    for (auto it = first; it != last; ++it, (void)++value) {
+      *value = *it;
+    }
+  }
+};
+
+template <size_t k>
+struct DeleteArgAction {
+  template <typename... Args>
+  void operator()(const Args&... args) const {
+    delete std::get<k>(std::tie(args...));
+  }
+};
+
+template <typename Ptr>
+struct ReturnPointeeAction {
+  Ptr pointer;
+  template <typename... Args>
+  auto operator()(const Args&...) const -> decltype(*pointer) {
+    return *pointer;
+  }
+};
+
+#if GTEST_HAS_EXCEPTIONS
+template <typename T>
+struct ThrowAction {
+  T exception;
+  // We use a conversion operator to adapt to any return type.
+  template <typename R, typename... Args>
+  operator Action<R(Args...)>() const {  // NOLINT
+    T copy = exception;
+    return [copy](Args...) -> R { throw copy; };
+  }
+};
+struct RethrowAction {
+  std::exception_ptr exception;
+  template <typename R, typename... Args>
+  operator Action<R(Args...)>() const {  // NOLINT
+    return [ex = exception](Args...) -> R { std::rethrow_exception(ex); };
+  }
+};
+#endif  // GTEST_HAS_EXCEPTIONS
+
+}  // namespace internal
+
+// An Unused object can be implicitly constructed from ANY value.
+// This is handy when defining actions that ignore some or all of the
+// mock function arguments.  For example, given
+//
+//   MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+//   MOCK_METHOD3(Bar, double(int index, double x, double y));
+//
+// instead of
+//
+//   double DistanceToOriginWithLabel(const string& label, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   double DistanceToOriginWithIndex(int index, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXPECT_CALL(mock, Foo("abc", _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithLabel));
+//   EXPECT_CALL(mock, Bar(5, _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithIndex));
+//
+// you could write
+//
+//   // We can declare any uninteresting argument as Unused.
+//   double DistanceToOrigin(Unused, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXPECT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin));
+//   EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
+typedef internal::IgnoredValue Unused;
+
+// Creates an action that does actions a1, a2, ..., sequentially in
+// each invocation. All but the last action will have a readonly view of the
+// arguments.
+template <typename... Action>
+internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
+    Action&&... action) {
+  return internal::DoAllAction<typename std::decay<Action>::type...>(
+      {}, std::forward<Action>(action)...);
+}
+
+// WithArg<k>(an_action) creates an action that passes the k-th
+// (0-based) argument of the mock function to an_action and performs
+// it.  It adapts an action accepting one argument to one that accepts
+// multiple arguments.  For convenience, we also provide
+// WithArgs<k>(an_action) (defined below) as a synonym.
+template <size_t k, typename InnerAction>
+internal::WithArgsAction<typename std::decay<InnerAction>::type, k> WithArg(
+    InnerAction&& action) {
+  return {std::forward<InnerAction>(action)};
+}
+
+// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
+// the selected arguments of the mock function to an_action and
+// performs it.  It serves as an adaptor between actions with
+// different argument lists.
+template <size_t k, size_t... ks, typename InnerAction>
+internal::WithArgsAction<typename std::decay<InnerAction>::type, k, ks...>
+WithArgs(InnerAction&& action) {
+  return {std::forward<InnerAction>(action)};
+}
+
+// WithoutArgs(inner_action) can be used in a mock function with a
+// non-empty argument list to perform inner_action, which takes no
+// argument.  In other words, it adapts an action accepting no
+// argument to one that accepts (and ignores) arguments.
+template <typename InnerAction>
+internal::WithArgsAction<typename std::decay<InnerAction>::type> WithoutArgs(
+    InnerAction&& action) {
+  return {std::forward<InnerAction>(action)};
+}
+
+// Creates an action that returns a value.
+//
+// The returned type can be used with a mock function returning a non-void,
+// non-reference type U as follows:
+//
+//  *  If R is convertible to U and U is move-constructible, then the action can
+//     be used with WillOnce.
+//
+//  *  If const R& is convertible to U and U is copy-constructible, then the
+//     action can be used with both WillOnce and WillRepeatedly.
+//
+// The mock expectation contains the R value from which the U return value is
+// constructed (a move/copy of the argument to Return). This means that the R
+// value will survive at least until the mock object's expectations are cleared
+// or the mock object is destroyed, meaning that U can safely be a
+// reference-like type such as std::string_view:
+//
+//     // The mock function returns a view of a copy of the string fed to
+//     // Return. The view is valid even after the action is performed.
+//     MockFunction<std::string_view()> mock;
+//     EXPECT_CALL(mock, Call).WillOnce(Return(std::string("taco")));
+//     const std::string_view result = mock.AsStdFunction()();
+//     EXPECT_EQ("taco", result);
+//
+template <typename R>
+internal::ReturnAction<R> Return(R value) {
+  return internal::ReturnAction<R>(std::move(value));
+}
+
+// Creates an action that returns NULL.
+inline PolymorphicAction<internal::ReturnNullAction> ReturnNull() {
+  return MakePolymorphicAction(internal::ReturnNullAction());
+}
+
+// Creates an action that returns from a void function.
+inline PolymorphicAction<internal::ReturnVoidAction> Return() {
+  return MakePolymorphicAction(internal::ReturnVoidAction());
+}
+
+// Creates an action that returns the reference to a variable.
+template <typename R>
+inline internal::ReturnRefAction<R> ReturnRef(R& x) {  // NOLINT
+  return internal::ReturnRefAction<R>(x);
+}
+
+// Prevent using ReturnRef on reference to temporary.
+template <typename R, R* = nullptr>
+internal::ReturnRefAction<R> ReturnRef(R&&) = delete;
+
+// Creates an action that returns the reference to a copy of the
+// argument.  The copy is created when the action is constructed and
+// lives as long as the action.
+template <typename R>
+inline internal::ReturnRefOfCopyAction<R> ReturnRefOfCopy(const R& x) {
+  return internal::ReturnRefOfCopyAction<R>(x);
+}
+
+// DEPRECATED: use Return(x) directly with WillOnce.
+//
+// Modifies the parent action (a Return() action) to perform a move of the
+// argument instead of a copy.
+// Return(ByMove()) actions can only be executed once and will assert this
+// invariant.
+template <typename R>
+internal::ByMoveWrapper<R> ByMove(R x) {
+  return internal::ByMoveWrapper<R>(std::move(x));
+}
+
+// Creates an action that returns an element of `vals`. Calling this action will
+// repeatedly return the next value from `vals` until it reaches the end and
+// will restart from the beginning.
+template <typename T>
+internal::ReturnRoundRobinAction<T> ReturnRoundRobin(std::vector<T> vals) {
+  return internal::ReturnRoundRobinAction<T>(std::move(vals));
+}
+
+// Creates an action that returns an element of `vals`. Calling this action will
+// repeatedly return the next value from `vals` until it reaches the end and
+// will restart from the beginning.
+template <typename T>
+internal::ReturnRoundRobinAction<T> ReturnRoundRobin(
+    std::initializer_list<T> vals) {
+  return internal::ReturnRoundRobinAction<T>(std::vector<T>(vals));
+}
+
+// Creates an action that does the default action for the give mock function.
+inline internal::DoDefaultAction DoDefault() {
+  return internal::DoDefaultAction();
+}
+
+// Creates an action that sets the variable pointed by the N-th
+// (0-based) function argument to 'value'.
+template <size_t N, typename T>
+internal::SetArgumentPointeeAction<N, T> SetArgPointee(T value) {
+  return {std::move(value)};
+}
+
+// The following version is DEPRECATED.
+template <size_t N, typename T>
+internal::SetArgumentPointeeAction<N, T> SetArgumentPointee(T value) {
+  return {std::move(value)};
+}
+
+// Creates an action that sets a pointer referent to a given value.
+template <typename T1, typename T2>
+PolymorphicAction<internal::AssignAction<T1, T2>> Assign(T1* ptr, T2 val) {
+  return MakePolymorphicAction(internal::AssignAction<T1, T2>(ptr, val));
+}
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+
+// Creates an action that sets errno and returns the appropriate error.
+template <typename T>
+PolymorphicAction<internal::SetErrnoAndReturnAction<T>> SetErrnoAndReturn(
+    int errval, T result) {
+  return MakePolymorphicAction(
+      internal::SetErrnoAndReturnAction<T>(errval, result));
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Various overloads for Invoke().
+
+// Legacy function.
+// Actions can now be implicitly constructed from callables. No need to create
+// wrapper objects.
+// This function exists for backwards compatibility.
+template <typename FunctionImpl>
+typename std::decay<FunctionImpl>::type Invoke(FunctionImpl&& function_impl) {
+  return std::forward<FunctionImpl>(function_impl);
+}
+
+// Creates an action that invokes the given method on the given object
+// with the mock function's arguments.
+template <class Class, typename MethodPtr>
+internal::InvokeMethodAction<Class, MethodPtr> Invoke(Class* obj_ptr,
+                                                      MethodPtr method_ptr) {
+  return {obj_ptr, method_ptr};
+}
+
+// Creates an action that invokes 'function_impl' with no argument.
+template <typename FunctionImpl>
+internal::InvokeWithoutArgsAction<typename std::decay<FunctionImpl>::type>
+InvokeWithoutArgs(FunctionImpl function_impl) {
+  return {std::move(function_impl)};
+}
+
+// Creates an action that invokes the given method on the given object
+// with no argument.
+template <class Class, typename MethodPtr>
+internal::InvokeMethodWithoutArgsAction<Class, MethodPtr> InvokeWithoutArgs(
+    Class* obj_ptr, MethodPtr method_ptr) {
+  return {obj_ptr, method_ptr};
+}
+
+// Creates an action that performs an_action and throws away its
+// result.  In other words, it changes the return type of an_action to
+// void.  an_action MUST NOT return void, or the code won't compile.
+template <typename A>
+inline internal::IgnoreResultAction<A> IgnoreResult(const A& an_action) {
+  return internal::IgnoreResultAction<A>(an_action);
+}
+
+// Creates a reference wrapper for the given L-value.  If necessary,
+// you can explicitly specify the type of the reference.  For example,
+// suppose 'derived' is an object of type Derived, ByRef(derived)
+// would wrap a Derived&.  If you want to wrap a const Base& instead,
+// where Base is a base class of Derived, just write:
+//
+//   ByRef<const Base>(derived)
+//
+// N.B. ByRef is redundant with std::ref, std::cref and std::reference_wrapper.
+// However, it may still be used for consistency with ByMove().
+template <typename T>
+inline ::std::reference_wrapper<T> ByRef(T& l_value) {  // NOLINT
+  return ::std::reference_wrapper<T>(l_value);
+}
+
+// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
+// instance of type T, constructed on the heap with constructor arguments
+// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
+template <typename T, typename... Params>
+internal::ReturnNewAction<T, typename std::decay<Params>::type...> ReturnNew(
+    Params&&... params) {
+  return {std::forward_as_tuple(std::forward<Params>(params)...)};
+}
+
+// Action ReturnArg<k>() returns the k-th argument of the mock function.
+template <size_t k>
+internal::ReturnArgAction<k> ReturnArg() {
+  return {};
+}
+
+// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
+// mock function to *pointer.
+template <size_t k, typename Ptr>
+internal::SaveArgAction<k, Ptr> SaveArg(Ptr pointer) {
+  return {pointer};
+}
+
+// Action SaveArgPointee<k>(pointer) saves the value pointed to
+// by the k-th (0-based) argument of the mock function to *pointer.
+template <size_t k, typename Ptr>
+internal::SaveArgPointeeAction<k, Ptr> SaveArgPointee(Ptr pointer) {
+  return {pointer};
+}
+
+// Action SetArgReferee<k>(value) assigns 'value' to the variable
+// referenced by the k-th (0-based) argument of the mock function.
+template <size_t k, typename T>
+internal::SetArgRefereeAction<k, typename std::decay<T>::type> SetArgReferee(
+    T&& value) {
+  return {std::forward<T>(value)};
+}
+
+// Action SetArrayArgument<k>(first, last) copies the elements in
+// source range [first, last) to the array pointed to by the k-th
+// (0-based) argument, which can be either a pointer or an
+// iterator. The action does not take ownership of the elements in the
+// source range.
+template <size_t k, typename I1, typename I2>
+internal::SetArrayArgumentAction<k, I1, I2> SetArrayArgument(I1 first,
+                                                             I2 last) {
+  return {first, last};
+}
+
+// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
+// function.
+template <size_t k>
+internal::DeleteArgAction<k> DeleteArg() {
+  return {};
+}
+
+// This action returns the value pointed to by 'pointer'.
+template <typename Ptr>
+internal::ReturnPointeeAction<Ptr> ReturnPointee(Ptr pointer) {
+  return {pointer};
+}
+
+#if GTEST_HAS_EXCEPTIONS
+// Action Throw(exception) can be used in a mock function of any type
+// to throw the given exception.  Any copyable value can be thrown,
+// except for std::exception_ptr, which is likely a mistake if
+// thrown directly.
+template <typename T>
+typename std::enable_if<
+    !std::is_base_of<std::exception_ptr, typename std::decay<T>::type>::value,
+    internal::ThrowAction<typename std::decay<T>::type>>::type
+Throw(T&& exception) {
+  return {std::forward<T>(exception)};
+}
+// Action Rethrow(exception_ptr) can be used in a mock function of any type
+// to rethrow any exception_ptr. Note that the same object is thrown each time.
+inline internal::RethrowAction Rethrow(std::exception_ptr exception) {
+  return {std::move(exception)};
+}
+#endif  // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+
+// A macro from the ACTION* family (defined later in gmock-generated-actions.h)
+// defines an action that can be used in a mock function.  Typically,
+// these actions only care about a subset of the arguments of the mock
+// function.  For example, if such an action only uses the second
+// argument, it can be used in any mock function that takes >= 2
+// arguments where the type of the second argument is compatible.
+//
+// Therefore, the action implementation must be prepared to take more
+// arguments than it needs.  The ExcessiveArg type is used to
+// represent those excessive arguments.  In order to keep the compiler
+// error messages tractable, we define it in the testing namespace
+// instead of testing::internal.  However, this is an INTERNAL TYPE
+// and subject to change without notice, so a user MUST NOT USE THIS
+// TYPE DIRECTLY.
+struct ExcessiveArg {};
+
+// Builds an implementation of an Action<> for some particular signature, using
+// a class defined by an ACTION* macro.
+template <typename F, typename Impl>
+struct ActionImpl;
+
+template <typename Impl>
+struct ImplBase {
+  struct Holder {
+    // Allows each copy of the Action<> to get to the Impl.
+    explicit operator const Impl&() const { return *ptr; }
+    std::shared_ptr<Impl> ptr;
+  };
+  using type = typename std::conditional<std::is_constructible<Impl>::value,
+                                         Impl, Holder>::type;
+};
+
+template <typename R, typename... Args, typename Impl>
+struct ActionImpl<R(Args...), Impl> : ImplBase<Impl>::type {
+  using Base = typename ImplBase<Impl>::type;
+  using function_type = R(Args...);
+  using args_type = std::tuple<Args...>;
+
+  ActionImpl() = default;  // Only defined if appropriate for Base.
+  explicit ActionImpl(std::shared_ptr<Impl> impl) : Base{std::move(impl)} {}
+
+  R operator()(Args&&... arg) const {
+    static constexpr size_t kMaxArgs =
+        sizeof...(Args) <= 10 ? sizeof...(Args) : 10;
+    return Apply(std::make_index_sequence<kMaxArgs>{},
+                 std::make_index_sequence<10 - kMaxArgs>{},
+                 args_type{std::forward<Args>(arg)...});
+  }
+
+  template <std::size_t... arg_id, std::size_t... excess_id>
+  R Apply(std::index_sequence<arg_id...>, std::index_sequence<excess_id...>,
+          const args_type& args) const {
+    // Impl need not be specific to the signature of action being implemented;
+    // only the implementing function body needs to have all of the specific
+    // types instantiated.  Up to 10 of the args that are provided by the
+    // args_type get passed, followed by a dummy of unspecified type for the
+    // remainder up to 10 explicit args.
+    static constexpr ExcessiveArg kExcessArg{};
+    return static_cast<const Impl&>(*this)
+        .template gmock_PerformImpl<
+            /*function_type=*/function_type, /*return_type=*/R,
+            /*args_type=*/args_type,
+            /*argN_type=*/
+            typename std::tuple_element<arg_id, args_type>::type...>(
+            /*args=*/args, std::get<arg_id>(args)...,
+            ((void)excess_id, kExcessArg)...);
+  }
+};
+
+// Stores a default-constructed Impl as part of the Action<>'s
+// std::function<>. The Impl should be trivial to copy.
+template <typename F, typename Impl>
+::testing::Action<F> MakeAction() {
+  return ::testing::Action<F>(ActionImpl<F, Impl>());
+}
+
+// Stores just the one given instance of Impl.
+template <typename F, typename Impl>
+::testing::Action<F> MakeAction(std::shared_ptr<Impl> impl) {
+  return ::testing::Action<F>(ActionImpl<F, Impl>(std::move(impl)));
+}
+
+#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
+  , GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_                               \
+  GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \
+      GMOCK_INTERNAL_ARG_UNUSED, , 10)
+
+#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_ \
+  const args_type& args GMOCK_PP_REPEAT(GMOCK_INTERNAL_ARG, , 10)
+
+#define GMOCK_INTERNAL_TEMPLATE_ARG(i, data, el) , typename arg##i##_type
+#define GMOCK_ACTION_TEMPLATE_ARGS_NAMES_ \
+  GMOCK_PP_TAIL(GMOCK_PP_REPEAT(GMOCK_INTERNAL_TEMPLATE_ARG, , 10))
+
+#define GMOCK_INTERNAL_TYPENAME_PARAM(i, data, param) , typename param##_type
+#define GMOCK_ACTION_TYPENAME_PARAMS_(params) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPENAME_PARAM, , params))
+
+#define GMOCK_INTERNAL_TYPE_PARAM(i, data, param) , param##_type
+#define GMOCK_ACTION_TYPE_PARAMS_(params) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPE_PARAM, , params))
+
+#define GMOCK_INTERNAL_TYPE_GVALUE_PARAM(i, data, param) \
+  , param##_type gmock_p##i
+#define GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPE_GVALUE_PARAM, , params))
+
+#define GMOCK_INTERNAL_GVALUE_PARAM(i, data, param) \
+  , std::forward<param##_type>(gmock_p##i)
+#define GMOCK_ACTION_GVALUE_PARAMS_(params) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GVALUE_PARAM, , params))
+
+#define GMOCK_INTERNAL_INIT_PARAM(i, data, param) \
+  , param(::std::forward<param##_type>(gmock_p##i))
+#define GMOCK_ACTION_INIT_PARAMS_(params) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_INIT_PARAM, , params))
+
+#define GMOCK_INTERNAL_FIELD_PARAM(i, data, param) param##_type param;
+#define GMOCK_ACTION_FIELD_PARAMS_(params) \
+  GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_FIELD_PARAM, , params)
+
+#define GMOCK_INTERNAL_ACTION(name, full_name, params)                         \
+  template <GMOCK_ACTION_TYPENAME_PARAMS_(params)>                             \
+  class full_name {                                                            \
+   public:                                                                     \
+    explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params))               \
+        : impl_(std::make_shared<gmock_Impl>(                                  \
+              GMOCK_ACTION_GVALUE_PARAMS_(params))) {}                         \
+    full_name(const full_name&) = default;                                     \
+    full_name(full_name&&) noexcept = default;                                 \
+    template <typename F>                                                      \
+    operator ::testing::Action<F>() const {                                    \
+      return ::testing::internal::MakeAction<F>(impl_);                        \
+    }                                                                          \
+                                                                               \
+   private:                                                                    \
+    class gmock_Impl {                                                         \
+     public:                                                                   \
+      explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params))            \
+          : GMOCK_ACTION_INIT_PARAMS_(params) {}                               \
+      template <typename function_type, typename return_type,                  \
+                typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>         \
+      return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;  \
+      GMOCK_ACTION_FIELD_PARAMS_(params)                                       \
+    };                                                                         \
+    std::shared_ptr<const gmock_Impl> impl_;                                   \
+  };                                                                           \
+  template <GMOCK_ACTION_TYPENAME_PARAMS_(params)>                             \
+  inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name(                    \
+      GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_;        \
+  template <GMOCK_ACTION_TYPENAME_PARAMS_(params)>                             \
+  inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name(                    \
+      GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) {                              \
+    return full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>(                       \
+        GMOCK_ACTION_GVALUE_PARAMS_(params));                                  \
+  }                                                                            \
+  template <GMOCK_ACTION_TYPENAME_PARAMS_(params)>                             \
+  template <typename function_type, typename return_type, typename args_type,  \
+            GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>                                 \
+  return_type                                                                  \
+  full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>::gmock_Impl::gmock_PerformImpl( \
+      GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+}  // namespace internal
+
+// Similar to GMOCK_INTERNAL_ACTION, but no bound parameters are stored.
+#define ACTION(name)                                                          \
+  class name##Action {                                                        \
+   public:                                                                    \
+    explicit name##Action() noexcept {}                                       \
+    name##Action(const name##Action&) noexcept {}                             \
+    template <typename F>                                                     \
+    operator ::testing::Action<F>() const {                                   \
+      return ::testing::internal::MakeAction<F, gmock_Impl>();                \
+    }                                                                         \
+                                                                              \
+   private:                                                                   \
+    class gmock_Impl {                                                        \
+     public:                                                                  \
+      template <typename function_type, typename return_type,                 \
+                typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>        \
+      return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
+    };                                                                        \
+  };                                                                          \
+  inline name##Action name() GTEST_MUST_USE_RESULT_;                          \
+  inline name##Action name() { return name##Action(); }                       \
+  template <typename function_type, typename return_type, typename args_type, \
+            GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>                                \
+  return_type name##Action::gmock_Impl::gmock_PerformImpl(                    \
+      GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP, (__VA_ARGS__))
+
+#define ACTION_P2(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP2, (__VA_ARGS__))
+
+#define ACTION_P3(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP3, (__VA_ARGS__))
+
+#define ACTION_P4(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP4, (__VA_ARGS__))
+
+#define ACTION_P5(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP5, (__VA_ARGS__))
+
+#define ACTION_P6(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP6, (__VA_ARGS__))
+
+#define ACTION_P7(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP7, (__VA_ARGS__))
+
+#define ACTION_P8(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP8, (__VA_ARGS__))
+
+#define ACTION_P9(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP9, (__VA_ARGS__))
+
+#define ACTION_P10(name, ...) \
+  GMOCK_INTERNAL_ACTION(name, name##ActionP10, (__VA_ARGS__))
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-cardinalities.h b/3rd-party/googletest/googlemock/include/gmock/gmock-cardinalities.h
new file mode 100644
index 0000000..533e604
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-cardinalities.h
@@ -0,0 +1,159 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used cardinalities.  More
+// cardinalities can be defined by the user implementing the
+// CardinalityInterface interface if necessary.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+
+#include <limits.h>
+
+#include <memory>
+#include <ostream>  // NOLINT
+
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// To implement a cardinality Foo, define:
+//   1. a class FooCardinality that implements the
+//      CardinalityInterface interface, and
+//   2. a factory function that creates a Cardinality object from a
+//      const FooCardinality*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Cardinality objects can now be copied like plain values.
+
+// The implementation of a cardinality.
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface() = default;
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return 0; }
+  virtual int ConservativeUpperBound() const { return INT_MAX; }
+
+  // Returns true if and only if call_count calls will satisfy this
+  // cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true if and only if call_count calls will saturate this
+  // cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+
+// A Cardinality is a copyable and IMMUTABLE (except by assignment)
+// object that specifies how many times a mock function is expected to
+// be called.  The implementation of Cardinality is just a std::shared_ptr
+// to const CardinalityInterface. Don't inherit from Cardinality!
+class GTEST_API_ Cardinality {
+ public:
+  // Constructs a null cardinality.  Needed for storing Cardinality
+  // objects in STL containers.
+  Cardinality() = default;
+
+  // Constructs a Cardinality from its implementation.
+  explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
+  int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
+
+  // Returns true if and only if call_count calls will satisfy this
+  // cardinality.
+  bool IsSatisfiedByCallCount(int call_count) const {
+    return impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Returns true if and only if call_count calls will saturate this
+  // cardinality.
+  bool IsSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count);
+  }
+
+  // Returns true if and only if call_count calls will over-saturate this
+  // cardinality, i.e. exceed the maximum number of allowed calls.
+  bool IsOverSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count) &&
+           !impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Describes self to an ostream
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the given actual call count to an ostream.
+  static void DescribeActualCallCountTo(int actual_call_count,
+                                        ::std::ostream* os);
+
+ private:
+  std::shared_ptr<const CardinalityInterface> impl_;
+};
+
+// Creates a cardinality that allows at least n calls.
+GTEST_API_ Cardinality AtLeast(int n);
+
+// Creates a cardinality that allows at most n calls.
+GTEST_API_ Cardinality AtMost(int n);
+
+// Creates a cardinality that allows any number of calls.
+GTEST_API_ Cardinality AnyNumber();
+
+// Creates a cardinality that allows between min and max calls.
+GTEST_API_ Cardinality Between(int min, int max);
+
+// Creates a cardinality that allows exactly n calls.
+GTEST_API_ Cardinality Exactly(int n);
+
+// Creates a cardinality from its implementation.
+inline Cardinality MakeCardinality(const CardinalityInterface* c) {
+  return Cardinality(c);
+}
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-function-mocker.h b/3rd-party/googletest/googlemock/include/gmock/gmock-function-mocker.h
new file mode 100644
index 0000000..d2cb13c
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-function-mocker.h
@@ -0,0 +1,519 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements MOCK_METHOD.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
+
+#include <cstddef>
+#include <type_traits>  // IWYU pragma: keep
+#include <utility>      // IWYU pragma: keep
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-pp.h"
+
+namespace testing {
+namespace internal {
+template <typename T>
+using identity_t = T;
+
+template <typename Pattern>
+struct ThisRefAdjuster {
+  template <typename T>
+  using AdjustT = typename std::conditional<
+      std::is_const<typename std::remove_reference<Pattern>::type>::value,
+      typename std::conditional<std::is_lvalue_reference<Pattern>::value,
+                                const T&, const T&&>::type,
+      typename std::conditional<std::is_lvalue_reference<Pattern>::value, T&,
+                                T&&>::type>::type;
+
+  template <typename MockType>
+  static AdjustT<MockType> Adjust(const MockType& mock) {
+    return static_cast<AdjustT<MockType>>(const_cast<MockType&>(mock));
+  }
+};
+
+constexpr bool PrefixOf(const char* a, const char* b) {
+  return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1));
+}
+
+template <size_t N, size_t M>
+constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) {
+  return N <= M && internal::PrefixOf(prefix, str);
+}
+
+template <size_t N, size_t M>
+constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) {
+  return N <= M && internal::PrefixOf(suffix, str + M - N);
+}
+
+template <size_t N, size_t M>
+constexpr bool Equals(const char (&a)[N], const char (&b)[M]) {
+  return N == M && internal::PrefixOf(a, b);
+}
+
+template <size_t N>
+constexpr bool ValidateSpec(const char (&spec)[N]) {
+  return internal::Equals("const", spec) ||
+         internal::Equals("override", spec) ||
+         internal::Equals("final", spec) ||
+         internal::Equals("noexcept", spec) ||
+         (internal::StartsWith("noexcept(", spec) &&
+          internal::EndsWith(")", spec)) ||
+         internal::Equals("ref(&)", spec) ||
+         internal::Equals("ref(&&)", spec) ||
+         (internal::StartsWith("Calltype(", spec) &&
+          internal::EndsWith(")", spec));
+}
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the FunctionMocker class template
+// is meant to be defined in the ::testing namespace.  The following
+// line is just a trick for working around a bug in MSVC 8.0, which
+// cannot handle it if we define FunctionMocker in ::testing.
+using internal::FunctionMocker;
+}  // namespace testing
+
+#define MOCK_METHOD(...)                                               \
+  GMOCK_INTERNAL_WARNING_PUSH()                                        \
+  GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function")    \
+  GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) \
+  GMOCK_INTERNAL_WARNING_POP()
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \
+  GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \
+  GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \
+  GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ())
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec)  \
+  GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args);                                \
+  GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec);                                \
+  GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(                                   \
+      GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args));        \
+  GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec)                                  \
+  GMOCK_INTERNAL_MOCK_METHOD_IMPL(                                         \
+      GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec),  \
+      GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \
+      GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec),                             \
+      GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Spec),                             \
+      GMOCK_INTERNAL_GET_REF_SPEC(_Spec),                                  \
+      (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)))
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \
+  GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \
+  GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
+
+#define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \
+  GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
+
+#define GMOCK_INTERNAL_WRONG_ARITY(...)                                      \
+  static_assert(                                                             \
+      false,                                                                 \
+      "MOCK_METHOD must be called with 3 or 4 arguments. _Ret, "             \
+      "_MethodName, _Args and optionally _Spec. _Args and _Spec must be "    \
+      "enclosed in parentheses. If _Ret is a type with unprotected commas, " \
+      "it must also be enclosed in parentheses.")
+
+#define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \
+  static_assert(                                  \
+      GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple),        \
+      GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.")
+
+#define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...)                 \
+  static_assert(                                                       \
+      std::is_function<__VA_ARGS__>::value,                            \
+      "Signature must be a function type, maybe return type contains " \
+      "unprotected comma.");                                           \
+  static_assert(                                                       \
+      ::testing::tuple_size<typename ::testing::internal::Function<    \
+              __VA_ARGS__>::ArgumentTuple>::value == _N,               \
+      "This method does not take " GMOCK_PP_STRINGIZE(                 \
+          _N) " arguments. Parenthesize all types with unprotected commas.")
+
+#define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \
+  GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec)
+
+#define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness,           \
+                                        _Override, _Final, _NoexceptSpec,      \
+                                        _CallType, _RefSpec, _Signature)       \
+  typename ::testing::internal::Function<GMOCK_PP_REMOVE_PARENS(               \
+      _Signature)>::Result                                                     \
+  GMOCK_INTERNAL_EXPAND(_CallType)                                             \
+      _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N))   \
+          GMOCK_PP_IF(_Constness, const, )                                     \
+              _RefSpec _NoexceptSpec GMOCK_PP_IF(_Override, override, )        \
+                  GMOCK_PP_IF(_Final, final, ) {                               \
+    GMOCK_MOCKER_(_N, _Constness, _MethodName)                                 \
+        .SetOwnerAndName(this, #_MethodName);                                  \
+    return GMOCK_MOCKER_(_N, _Constness, _MethodName)                          \
+        .Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N));  \
+  }                                                                            \
+  ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \
+      GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N))       \
+      GMOCK_PP_IF(_Constness, const, ) _RefSpec {                              \
+    GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this);            \
+    return GMOCK_MOCKER_(_N, _Constness, _MethodName)                          \
+        .With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N));         \
+  }                                                                            \
+  ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \
+      const ::testing::internal::WithoutMatchers&,                             \
+      GMOCK_PP_IF(_Constness, const, )::testing::internal::Function<           \
+          GMOCK_PP_REMOVE_PARENS(_Signature)>*) const _RefSpec _NoexceptSpec { \
+    return ::testing::internal::ThisRefAdjuster<GMOCK_PP_IF(                   \
+        _Constness, const, ) int _RefSpec>::Adjust(*this)                      \
+        .gmock_##_MethodName(GMOCK_PP_REPEAT(                                  \
+            GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N));               \
+  }                                                                            \
+  mutable ::testing::FunctionMocker<GMOCK_PP_REMOVE_PARENS(_Signature)>        \
+  GMOCK_MOCKER_(_N, _Constness, _MethodName)
+
+#define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__
+
+// Valid modifiers.
+#define GMOCK_INTERNAL_HAS_CONST(_Tuple) \
+  GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple))
+
+#define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \
+  GMOCK_PP_HAS_COMMA(                       \
+      GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple))
+
+#define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \
+  GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple))
+
+#define GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Tuple) \
+  GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT, ~, _Tuple)
+
+#define GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT(_i, _, _elem)          \
+  GMOCK_PP_IF(                                                          \
+      GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)), \
+      _elem, )
+
+#define GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Tuple) \
+  GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE, ~, _Tuple)
+
+#define GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE(_i, _, _elem)          \
+  GMOCK_PP_IF(                                                          \
+      GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem)), \
+      GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), )
+
+#define GMOCK_INTERNAL_GET_REF_SPEC(_Tuple) \
+  GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_REF_SPEC_IF_REF, ~, _Tuple)
+
+#define GMOCK_INTERNAL_REF_SPEC_IF_REF(_i, _, _elem)                       \
+  GMOCK_PP_IF(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)), \
+              GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), )
+
+#ifdef GMOCK_INTERNAL_STRICT_SPEC_ASSERT
+#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \
+  static_assert(                                                     \
+      ::testing::internal::ValidateSpec(GMOCK_PP_STRINGIZE(_elem)),  \
+      "Token \'" GMOCK_PP_STRINGIZE(                                 \
+          _elem) "\' cannot be recognized as a valid specification " \
+                 "modifier. Is a ',' missing?");
+#else
+#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem)                 \
+  static_assert(                                                               \
+      (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) +         \
+       GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) +      \
+       GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) +         \
+       GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) +      \
+       GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) +           \
+       GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem))) == 1, \
+      GMOCK_PP_STRINGIZE(                                                      \
+          _elem) " cannot be recognized as a valid specification modifier.");
+#endif  // GMOCK_INTERNAL_STRICT_SPEC_ASSERT
+
+// Modifiers implementation.
+#define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \
+  GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem)
+
+#define GMOCK_INTERNAL_DETECT_CONST_I_const ,
+
+#define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \
+  GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem)
+
+#define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override ,
+
+#define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \
+  GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem)
+
+#define GMOCK_INTERNAL_DETECT_FINAL_I_final ,
+
+#define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \
+  GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem)
+
+#define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept ,
+
+#define GMOCK_INTERNAL_DETECT_REF(_i, _, _elem) \
+  GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_REF_I_, _elem)
+
+#define GMOCK_INTERNAL_DETECT_REF_I_ref ,
+
+#define GMOCK_INTERNAL_UNPACK_ref(x) x
+
+#define GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem) \
+  GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CALLTYPE_I_, _elem)
+
+#define GMOCK_INTERNAL_DETECT_CALLTYPE_I_Calltype ,
+
+#define GMOCK_INTERNAL_UNPACK_Calltype(...) __VA_ARGS__
+
+// Note: The use of `identity_t` here allows _Ret to represent return types that
+// would normally need to be specified in a different way. For example, a method
+// returning a function pointer must be written as
+//
+// fn_ptr_return_t (*method(method_args_t...))(fn_ptr_args_t...)
+//
+// But we only support placing the return type at the beginning. To handle this,
+// we wrap all calls in identity_t, so that a declaration will be expanded to
+//
+// identity_t<fn_ptr_return_t (*)(fn_ptr_args_t...)> method(method_args_t...)
+//
+// This allows us to work around the syntactic oddities of function/method
+// types.
+#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)                                 \
+  ::testing::internal::identity_t<GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), \
+                                              GMOCK_PP_REMOVE_PARENS,         \
+                                              GMOCK_PP_IDENTITY)(_Ret)>(      \
+      GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args))
+
+#define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem)                          \
+  GMOCK_PP_COMMA_IF(_i)                                                \
+  GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \
+              GMOCK_PP_IDENTITY)                                       \
+  (_elem)
+
+#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _)            \
+  GMOCK_PP_COMMA_IF(_i)                                        \
+  GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \
+  gmock_a##_i
+
+#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \
+  GMOCK_PP_COMMA_IF(_i)                               \
+  ::std::forward<GMOCK_INTERNAL_ARG_O(                \
+      _i, GMOCK_PP_REMOVE_PARENS(_Signature))>(gmock_a##_i)
+
+#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _)        \
+  GMOCK_PP_COMMA_IF(_i)                                            \
+  GMOCK_INTERNAL_MATCHER_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \
+  gmock_a##_i
+
+#define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \
+  GMOCK_PP_COMMA_IF(_i)                             \
+  gmock_a##_i
+
+#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \
+  GMOCK_PP_COMMA_IF(_i)                                      \
+  ::testing::A<GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature))>()
+
+#define GMOCK_INTERNAL_ARG_O(_i, ...) \
+  typename ::testing::internal::Function<__VA_ARGS__>::template Arg<_i>::type
+
+#define GMOCK_INTERNAL_MATCHER_O(_i, ...)                          \
+  const ::testing::Matcher<typename ::testing::internal::Function< \
+      __VA_ARGS__>::template Arg<_i>::type>&
+
+#define MOCK_METHOD0(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 0, __VA_ARGS__)
+#define MOCK_METHOD1(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 1, __VA_ARGS__)
+#define MOCK_METHOD2(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 2, __VA_ARGS__)
+#define MOCK_METHOD3(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 3, __VA_ARGS__)
+#define MOCK_METHOD4(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 4, __VA_ARGS__)
+#define MOCK_METHOD5(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 5, __VA_ARGS__)
+#define MOCK_METHOD6(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 6, __VA_ARGS__)
+#define MOCK_METHOD7(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 7, __VA_ARGS__)
+#define MOCK_METHOD8(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 8, __VA_ARGS__)
+#define MOCK_METHOD9(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 9, __VA_ARGS__)
+#define MOCK_METHOD10(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, , m, 10, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 0, __VA_ARGS__)
+#define MOCK_CONST_METHOD1(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 1, __VA_ARGS__)
+#define MOCK_CONST_METHOD2(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 2, __VA_ARGS__)
+#define MOCK_CONST_METHOD3(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 3, __VA_ARGS__)
+#define MOCK_CONST_METHOD4(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 4, __VA_ARGS__)
+#define MOCK_CONST_METHOD5(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 5, __VA_ARGS__)
+#define MOCK_CONST_METHOD6(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 6, __VA_ARGS__)
+#define MOCK_CONST_METHOD7(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 7, __VA_ARGS__)
+#define MOCK_CONST_METHOD8(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 8, __VA_ARGS__)
+#define MOCK_CONST_METHOD9(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 9, __VA_ARGS__)
+#define MOCK_CONST_METHOD10(m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, , m, 10, __VA_ARGS__)
+
+#define MOCK_METHOD0_T(m, ...) MOCK_METHOD0(m, __VA_ARGS__)
+#define MOCK_METHOD1_T(m, ...) MOCK_METHOD1(m, __VA_ARGS__)
+#define MOCK_METHOD2_T(m, ...) MOCK_METHOD2(m, __VA_ARGS__)
+#define MOCK_METHOD3_T(m, ...) MOCK_METHOD3(m, __VA_ARGS__)
+#define MOCK_METHOD4_T(m, ...) MOCK_METHOD4(m, __VA_ARGS__)
+#define MOCK_METHOD5_T(m, ...) MOCK_METHOD5(m, __VA_ARGS__)
+#define MOCK_METHOD6_T(m, ...) MOCK_METHOD6(m, __VA_ARGS__)
+#define MOCK_METHOD7_T(m, ...) MOCK_METHOD7(m, __VA_ARGS__)
+#define MOCK_METHOD8_T(m, ...) MOCK_METHOD8(m, __VA_ARGS__)
+#define MOCK_METHOD9_T(m, ...) MOCK_METHOD9(m, __VA_ARGS__)
+#define MOCK_METHOD10_T(m, ...) MOCK_METHOD10(m, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0_T(m, ...) MOCK_CONST_METHOD0(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD1_T(m, ...) MOCK_CONST_METHOD1(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2_T(m, ...) MOCK_CONST_METHOD2(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD3_T(m, ...) MOCK_CONST_METHOD3(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD4_T(m, ...) MOCK_CONST_METHOD4(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD5_T(m, ...) MOCK_CONST_METHOD5(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD6_T(m, ...) MOCK_CONST_METHOD6(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD7_T(m, ...) MOCK_CONST_METHOD7(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD8_T(m, ...) MOCK_CONST_METHOD8(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD9_T(m, ...) MOCK_CONST_METHOD9(m, __VA_ARGS__)
+#define MOCK_CONST_METHOD10_T(m, ...) MOCK_CONST_METHOD10(m, __VA_ARGS__)
+
+#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 0, __VA_ARGS__)
+#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 1, __VA_ARGS__)
+#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 2, __VA_ARGS__)
+#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 3, __VA_ARGS__)
+#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 4, __VA_ARGS__)
+#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 5, __VA_ARGS__)
+#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 6, __VA_ARGS__)
+#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 7, __VA_ARGS__)
+#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 8, __VA_ARGS__)
+#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 9, __VA_ARGS__)
+#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 10, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 0, __VA_ARGS__)
+#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 1, __VA_ARGS__)
+#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 2, __VA_ARGS__)
+#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 3, __VA_ARGS__)
+#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 4, __VA_ARGS__)
+#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 5, __VA_ARGS__)
+#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 6, __VA_ARGS__)
+#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 7, __VA_ARGS__)
+#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 8, __VA_ARGS__)
+#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 9, __VA_ARGS__)
+#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
+  GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 10, __VA_ARGS__)
+
+#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
+  MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__)
+
+#define GMOCK_INTERNAL_MOCK_METHODN(constness, ct, Method, args_num, ...) \
+  GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(                                  \
+      args_num, ::testing::internal::identity_t<__VA_ARGS__>);            \
+  GMOCK_INTERNAL_MOCK_METHOD_IMPL(                                        \
+      args_num, Method, GMOCK_PP_NARG0(constness), 0, 0, , ct, ,          \
+      (::testing::internal::identity_t<__VA_ARGS__>))
+
+#define GMOCK_MOCKER_(arity, constness, Method) \
+  GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-matchers.h b/3rd-party/googletest/googlemock/include/gmock/gmock-matchers.h
new file mode 100644
index 0000000..3daf617
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-matchers.h
@@ -0,0 +1,5638 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// The MATCHER* family of macros can be used in a namespace scope to
+// define custom matchers easily.
+//
+// Basic Usage
+// ===========
+//
+// The syntax
+//
+//   MATCHER(name, description_string) { statements; }
+//
+// defines a matcher with the given name that executes the statements,
+// which must return a bool to indicate if the match succeeds.  Inside
+// the statements, you can refer to the value being matched by 'arg',
+// and refer to its type by 'arg_type'.
+//
+// The description string documents what the matcher does, and is used
+// to generate the failure message when the match fails.  Since a
+// MATCHER() is usually defined in a header file shared by multiple
+// C++ source files, we require the description to be a C-string
+// literal to avoid possible side effects.  It can be empty, in which
+// case we'll use the sequence of words in the matcher name as the
+// description.
+//
+// For example:
+//
+//   MATCHER(IsEven, "") { return (arg % 2) == 0; }
+//
+// allows you to write
+//
+//   // Expects mock_foo.Bar(n) to be called where n is even.
+//   EXPECT_CALL(mock_foo, Bar(IsEven()));
+//
+// or,
+//
+//   // Verifies that the value of some_expression is even.
+//   EXPECT_THAT(some_expression, IsEven());
+//
+// If the above assertion fails, it will print something like:
+//
+//   Value of: some_expression
+//   Expected: is even
+//     Actual: 7
+//
+// where the description "is even" is automatically calculated from the
+// matcher name IsEven.
+//
+// Argument Type
+// =============
+//
+// Note that the type of the value being matched (arg_type) is
+// determined by the context in which you use the matcher and is
+// supplied to you by the compiler, so you don't need to worry about
+// declaring it (nor can you).  This allows the matcher to be
+// polymorphic.  For example, IsEven() can be used to match any type
+// where the value of "(arg % 2) == 0" can be implicitly converted to
+// a bool.  In the "Bar(IsEven())" example above, if method Bar()
+// takes an int, 'arg_type' will be int; if it takes an unsigned long,
+// 'arg_type' will be unsigned long; and so on.
+//
+// Parameterizing Matchers
+// =======================
+//
+// Sometimes you'll want to parameterize the matcher.  For that you
+// can use another macro:
+//
+//   MATCHER_P(name, param_name, description_string) { statements; }
+//
+// For example:
+//
+//   MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+//
+// will allow you to write:
+//
+//   EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+//
+// which may lead to this message (assuming n is 10):
+//
+//   Value of: Blah("a")
+//   Expected: has absolute value 10
+//     Actual: -9
+//
+// Note that both the matcher description and its parameter are
+// printed, making the message human-friendly.
+//
+// In the matcher definition body, you can write 'foo_type' to
+// reference the type of a parameter named 'foo'.  For example, in the
+// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
+// 'value_type' to refer to the type of 'value'.
+//
+// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
+// support multi-parameter matchers.
+//
+// Describing Parameterized Matchers
+// =================================
+//
+// The last argument to MATCHER*() is a string-typed expression.  The
+// expression can reference all of the matcher's parameters and a
+// special bool-typed variable named 'negation'.  When 'negation' is
+// false, the expression should evaluate to the matcher's description;
+// otherwise it should evaluate to the description of the negation of
+// the matcher.  For example,
+//
+//   using testing::PrintToString;
+//
+//   MATCHER_P2(InClosedRange, low, hi,
+//       std::string(negation ? "is not" : "is") + " in range [" +
+//       PrintToString(low) + ", " + PrintToString(hi) + "]") {
+//     return low <= arg && arg <= hi;
+//   }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: is in range [4, 6]
+//   ...
+//   Expected: is not in range [2, 4]
+//
+// If you specify "" as the description, the failure message will
+// contain the sequence of words in the matcher name followed by the
+// parameter values printed as a tuple.  For example,
+//
+//   MATCHER_P2(InClosedRange, low, hi, "") { ... }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: in closed range (4, 6)
+//   ...
+//   Expected: not (in closed range (2, 4))
+//
+// Types of Matcher Parameters
+// ===========================
+//
+// For the purpose of typing, you can view
+//
+//   MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooMatcherPk<p1_type, ..., pk_type>
+//   Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// When you write Foo(v1, ..., vk), the compiler infers the types of
+// the parameters v1, ..., and vk for you.  If you are not happy with
+// the result of the type inference, you can specify the types by
+// explicitly instantiating the template, as in Foo<long, bool>(5,
+// false).  As said earlier, you don't get to (or need to) specify
+// 'arg_type' as that's determined by the context in which the matcher
+// is used.  You can assign the result of expression Foo(p1, ..., pk)
+// to a variable of type FooMatcherPk<p1_type, ..., pk_type>.  This
+// can be useful when composing matchers.
+//
+// While you can instantiate a matcher template with reference types,
+// passing the parameters by pointer usually makes your code more
+// readable.  If, however, you still want to pass a parameter by
+// reference, be aware that in the failure message generated by the
+// matcher you will see the value of the referenced object but not its
+// address.
+//
+// Explaining Match Results
+// ========================
+//
+// Sometimes the matcher description alone isn't enough to explain why
+// the match has failed or succeeded.  For example, when expecting a
+// long string, it can be very helpful to also print the diff between
+// the expected string and the actual one.  To achieve that, you can
+// optionally stream additional information to a special variable
+// named result_listener, whose type is a pointer to class
+// MatchResultListener:
+//
+//   MATCHER_P(EqualsLongString, str, "") {
+//     if (arg == str) return true;
+//
+//     *result_listener << "the difference: "
+///                     << DiffStrings(str, arg);
+//     return false;
+//   }
+//
+// Overloading Matchers
+// ====================
+//
+// You can overload matchers with different numbers of parameters:
+//
+//   MATCHER_P(Blah, a, description_string1) { ... }
+//   MATCHER_P2(Blah, a, b, description_string2) { ... }
+//
+// Caveats
+// =======
+//
+// When defining a new matcher, you should also consider implementing
+// MatcherInterface or using MakePolymorphicMatcher().  These
+// approaches require more work than the MATCHER* macros, but also
+// give you more control on the types of the value being matched and
+// the matcher parameters, which may leads to better compiler error
+// messages when the matcher is used wrong.  They also allow
+// overloading matchers based on parameter types (as opposed to just
+// based on the number of parameters).
+//
+// MATCHER*() can only be used in a namespace scope as templates cannot be
+// declared inside of a local class.
+//
+// More Information
+// ================
+//
+// To learn more about using these macros, please search for 'MATCHER'
+// on
+// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md
+//
+// This file also implements some commonly used argument matchers.  More
+// matchers can be defined by the user implementing the
+// MatcherInterface<T> interface if necessary.
+//
+// See googletest/include/gtest/gtest-matchers.h for the definition of class
+// Matcher, class MatcherInterface, and others.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+
+#include <algorithm>
+#include <cmath>
+#include <exception>
+#include <functional>
+#include <initializer_list>
+#include <ios>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gmock/internal/gmock-pp.h"
+#include "gtest/gtest.h"
+
+// MSVC warning C5046 is new as of VS2017 version 15.8.
+#if defined(_MSC_VER) && _MSC_VER >= 1915
+#define GMOCK_MAYBE_5046_ 5046
+#else
+#define GMOCK_MAYBE_5046_
+#endif
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(
+    4251 GMOCK_MAYBE_5046_ /* class A needs to have dll-interface to be used by
+                              clients of class B */
+    /* Symbol involving type with internal linkage not defined */)
+
+namespace testing {
+
+// To implement a matcher Foo for type T, define:
+//   1. a class FooMatcherImpl that implements the
+//      MatcherInterface<T> interface, and
+//   2. a factory function that creates a Matcher<T> object from a
+//      FooMatcherImpl*.
+//
+// The two-level delegation design makes it possible to allow a user
+// to write "v" instead of "Eq(v)" where a Matcher is expected, which
+// is impossible if we pass matchers by pointers.  It also eases
+// ownership management as Matcher objects can now be copied like
+// plain values.
+
+// A match result listener that stores the explanation in a string.
+class StringMatchResultListener : public MatchResultListener {
+ public:
+  StringMatchResultListener() : MatchResultListener(&ss_) {}
+
+  // Returns the explanation accumulated so far.
+  std::string str() const { return ss_.str(); }
+
+  // Clears the explanation accumulated so far.
+  void Clear() { ss_.str(""); }
+
+ private:
+  ::std::stringstream ss_;
+
+  StringMatchResultListener(const StringMatchResultListener&) = delete;
+  StringMatchResultListener& operator=(const StringMatchResultListener&) =
+      delete;
+};
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// The MatcherCastImpl class template is a helper for implementing
+// MatcherCast().  We need this helper in order to partially
+// specialize the implementation of MatcherCast() (C++ allows
+// class/struct templates to be partially specialized, but not
+// function templates.).
+
+// This general version is used when MatcherCast()'s argument is a
+// polymorphic matcher (i.e. something that can be converted to a
+// Matcher but is not one yet; for example, Eq(value)) or a value (for
+// example, "hello").
+template <typename T, typename M>
+class MatcherCastImpl {
+ public:
+  static Matcher<T> Cast(const M& polymorphic_matcher_or_value) {
+    // M can be a polymorphic matcher, in which case we want to use
+    // its conversion operator to create Matcher<T>.  Or it can be a value
+    // that should be passed to the Matcher<T>'s constructor.
+    //
+    // We can't call Matcher<T>(polymorphic_matcher_or_value) when M is a
+    // polymorphic matcher because it'll be ambiguous if T has an implicit
+    // constructor from M (this usually happens when T has an implicit
+    // constructor from any type).
+    //
+    // It won't work to unconditionally implicit_cast
+    // polymorphic_matcher_or_value to Matcher<T> because it won't trigger
+    // a user-defined conversion from M to T if one exists (assuming M is
+    // a value).
+    return CastImpl(polymorphic_matcher_or_value,
+                    std::is_convertible<M, Matcher<T>>{},
+                    std::is_convertible<M, T>{});
+  }
+
+ private:
+  template <bool Ignore>
+  static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value,
+                             std::true_type /* convertible_to_matcher */,
+                             std::integral_constant<bool, Ignore>) {
+    // M is implicitly convertible to Matcher<T>, which means that either
+    // M is a polymorphic matcher or Matcher<T> has an implicit constructor
+    // from M.  In both cases using the implicit conversion will produce a
+    // matcher.
+    //
+    // Even if T has an implicit constructor from M, it won't be called because
+    // creating Matcher<T> would require a chain of two user-defined conversions
+    // (first to create T from M and then to create Matcher<T> from T).
+    return polymorphic_matcher_or_value;
+  }
+
+  // M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
+  // matcher. It's a value of a type implicitly convertible to T. Use direct
+  // initialization to create a matcher.
+  static Matcher<T> CastImpl(const M& value,
+                             std::false_type /* convertible_to_matcher */,
+                             std::true_type /* convertible_to_T */) {
+    return Matcher<T>(ImplicitCast_<T>(value));
+  }
+
+  // M can't be implicitly converted to either Matcher<T> or T. Attempt to use
+  // polymorphic matcher Eq(value) in this case.
+  //
+  // Note that we first attempt to perform an implicit cast on the value and
+  // only fall back to the polymorphic Eq() matcher afterwards because the
+  // latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end
+  // which might be undefined even when Rhs is implicitly convertible to Lhs
+  // (e.g. std::pair<const int, int> vs. std::pair<int, int>).
+  //
+  // We don't define this method inline as we need the declaration of Eq().
+  static Matcher<T> CastImpl(const M& value,
+                             std::false_type /* convertible_to_matcher */,
+                             std::false_type /* convertible_to_T */);
+};
+
+// This more specialized version is used when MatcherCast()'s argument
+// is already a Matcher.  This only compiles when type T can be
+// statically converted to type U.
+template <typename T, typename U>
+class MatcherCastImpl<T, Matcher<U>> {
+ public:
+  static Matcher<T> Cast(const Matcher<U>& source_matcher) {
+    return Matcher<T>(new Impl(source_matcher));
+  }
+
+ private:
+  class Impl : public MatcherInterface<T> {
+   public:
+    explicit Impl(const Matcher<U>& source_matcher)
+        : source_matcher_(source_matcher) {}
+
+    // We delegate the matching logic to the source matcher.
+    bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+      using FromType = typename std::remove_cv<typename std::remove_pointer<
+          typename std::remove_reference<T>::type>::type>::type;
+      using ToType = typename std::remove_cv<typename std::remove_pointer<
+          typename std::remove_reference<U>::type>::type>::type;
+      // Do not allow implicitly converting base*/& to derived*/&.
+      static_assert(
+          // Do not trigger if only one of them is a pointer. That implies a
+          // regular conversion and not a down_cast.
+          (std::is_pointer<typename std::remove_reference<T>::type>::value !=
+           std::is_pointer<typename std::remove_reference<U>::type>::value) ||
+              std::is_same<FromType, ToType>::value ||
+              !std::is_base_of<FromType, ToType>::value,
+          "Can't implicitly convert from <base> to <derived>");
+
+      // Do the cast to `U` explicitly if necessary.
+      // Otherwise, let implicit conversions do the trick.
+      using CastType =
+          typename std::conditional<std::is_convertible<T&, const U&>::value,
+                                    T&, U>::type;
+
+      return source_matcher_.MatchAndExplain(static_cast<CastType>(x),
+                                             listener);
+    }
+
+    void DescribeTo(::std::ostream* os) const override {
+      source_matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      source_matcher_.DescribeNegationTo(os);
+    }
+
+   private:
+    const Matcher<U> source_matcher_;
+  };
+};
+
+// This even more specialized version is used for efficiently casting
+// a matcher to its own type.
+template <typename T>
+class MatcherCastImpl<T, Matcher<T>> {
+ public:
+  static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
+};
+
+// Template specialization for parameterless Matcher.
+template <typename Derived>
+class MatcherBaseImpl {
+ public:
+  MatcherBaseImpl() = default;
+
+  template <typename T>
+  operator ::testing::Matcher<T>() const {  // NOLINT(runtime/explicit)
+    return ::testing::Matcher<T>(new
+                                 typename Derived::template gmock_Impl<T>());
+  }
+};
+
+// Template specialization for Matcher with parameters.
+template <template <typename...> class Derived, typename... Ts>
+class MatcherBaseImpl<Derived<Ts...>> {
+ public:
+  // Mark the constructor explicit for single argument T to avoid implicit
+  // conversions.
+  template <typename E = std::enable_if<sizeof...(Ts) == 1>,
+            typename E::type* = nullptr>
+  explicit MatcherBaseImpl(Ts... params)
+      : params_(std::forward<Ts>(params)...) {}
+  template <typename E = std::enable_if<sizeof...(Ts) != 1>,
+            typename = typename E::type>
+  MatcherBaseImpl(Ts... params)  // NOLINT
+      : params_(std::forward<Ts>(params)...) {}
+
+  template <typename F>
+  operator ::testing::Matcher<F>() const {  // NOLINT(runtime/explicit)
+    return Apply<F>(std::make_index_sequence<sizeof...(Ts)>{});
+  }
+
+ private:
+  template <typename F, std::size_t... tuple_ids>
+  ::testing::Matcher<F> Apply(std::index_sequence<tuple_ids...>) const {
+    return ::testing::Matcher<F>(
+        new typename Derived<Ts...>::template gmock_Impl<F>(
+            std::get<tuple_ids>(params_)...));
+  }
+
+  const std::tuple<Ts...> params_;
+};
+
+}  // namespace internal
+
+// In order to be safe and clear, casting between different matcher
+// types is done explicitly via MatcherCast<T>(m), which takes a
+// matcher m and returns a Matcher<T>.  It compiles only when T can be
+// statically converted to the argument type of m.
+template <typename T, typename M>
+inline Matcher<T> MatcherCast(const M& matcher) {
+  return internal::MatcherCastImpl<T, M>::Cast(matcher);
+}
+
+// This overload handles polymorphic matchers and values only since
+// monomorphic matchers are handled by the next one.
+template <typename T, typename M>
+inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher_or_value) {
+  return MatcherCast<T>(polymorphic_matcher_or_value);
+}
+
+// This overload handles monomorphic matchers.
+//
+// In general, if type T can be implicitly converted to type U, we can
+// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
+// contravariant): just keep a copy of the original Matcher<U>, convert the
+// argument from type T to U, and then pass it to the underlying Matcher<U>.
+// The only exception is when U is a reference and T is not, as the
+// underlying Matcher<U> may be interested in the argument's address, which
+// is not preserved in the conversion from T to U.
+template <typename T, typename U>
+inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
+  // Enforce that T can be implicitly converted to U.
+  static_assert(std::is_convertible<const T&, const U&>::value,
+                "T must be implicitly convertible to U");
+  // Enforce that we are not converting a non-reference type T to a reference
+  // type U.
+  static_assert(std::is_reference<T>::value || !std::is_reference<U>::value,
+                "cannot convert non reference arg to reference");
+  // In case both T and U are arithmetic types, enforce that the
+  // conversion is not lossy.
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU;
+  constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
+  constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
+  static_assert(
+      kTIsOther || kUIsOther ||
+          (internal::LosslessArithmeticConvertible<RawT, RawU>::value),
+      "conversion of arithmetic types must be lossless");
+  return MatcherCast<T>(matcher);
+}
+
+// A<T>() returns a matcher that matches any value of type T.
+template <typename T>
+Matcher<T> A();
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// If the explanation is not empty, prints it to the ostream.
+inline void PrintIfNotEmpty(const std::string& explanation,
+                            ::std::ostream* os) {
+  if (!explanation.empty() && os != nullptr) {
+    *os << ", " << explanation;
+  }
+}
+
+// Returns true if the given type name is easy to read by a human.
+// This is used to decide whether printing the type of a value might
+// be helpful.
+inline bool IsReadableTypeName(const std::string& type_name) {
+  // We consider a type name readable if it's short or doesn't contain
+  // a template or function type.
+  return (type_name.length() <= 20 ||
+          type_name.find_first_of("<(") == std::string::npos);
+}
+
+// Matches the value against the given matcher, prints the value and explains
+// the match result to the listener. Returns the match result.
+// 'listener' must not be NULL.
+// Value cannot be passed by const reference, because some matchers take a
+// non-const argument.
+template <typename Value, typename T>
+bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher,
+                          MatchResultListener* listener) {
+  if (!listener->IsInterested()) {
+    // If the listener is not interested, we do not need to construct the
+    // inner explanation.
+    return matcher.Matches(value);
+  }
+
+  StringMatchResultListener inner_listener;
+  const bool match = matcher.MatchAndExplain(value, &inner_listener);
+
+  UniversalPrint(value, listener->stream());
+#if GTEST_HAS_RTTI
+  const std::string& type_name = GetTypeName<Value>();
+  if (IsReadableTypeName(type_name))
+    *listener->stream() << " (of type " << type_name << ")";
+#endif
+  PrintIfNotEmpty(inner_listener.str(), listener->stream());
+
+  return match;
+}
+
+// An internal helper class for doing compile-time loop on a tuple's
+// fields.
+template <size_t N>
+class TuplePrefix {
+ public:
+  // TuplePrefix<N>::Matches(matcher_tuple, value_tuple) returns true
+  // if and only if the first N fields of matcher_tuple matches
+  // the first N fields of value_tuple, respectively.
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& matcher_tuple,
+                      const ValueTuple& value_tuple) {
+    return TuplePrefix<N - 1>::Matches(matcher_tuple, value_tuple) &&
+           std::get<N - 1>(matcher_tuple).Matches(std::get<N - 1>(value_tuple));
+  }
+
+  // TuplePrefix<N>::ExplainMatchFailuresTo(matchers, values, os)
+  // describes failures in matching the first N fields of matchers
+  // against the first N fields of values.  If there is no failure,
+  // nothing will be streamed to os.
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& matchers,
+                                     const ValueTuple& values,
+                                     ::std::ostream* os) {
+    // First, describes failures in the first N - 1 fields.
+    TuplePrefix<N - 1>::ExplainMatchFailuresTo(matchers, values, os);
+
+    // Then describes the failure (if any) in the (N - 1)-th (0-based)
+    // field.
+    typename std::tuple_element<N - 1, MatcherTuple>::type matcher =
+        std::get<N - 1>(matchers);
+    typedef typename std::tuple_element<N - 1, ValueTuple>::type Value;
+    const Value& value = std::get<N - 1>(values);
+    StringMatchResultListener listener;
+    if (!matcher.MatchAndExplain(value, &listener)) {
+      *os << "  Expected arg #" << N - 1 << ": ";
+      std::get<N - 1>(matchers).DescribeTo(os);
+      *os << "\n           Actual: ";
+      // We remove the reference in type Value to prevent the
+      // universal printer from printing the address of value, which
+      // isn't interesting to the user most of the time.  The
+      // matcher's MatchAndExplain() method handles the case when
+      // the address is interesting.
+      internal::UniversalPrint(value, os);
+      PrintIfNotEmpty(listener.str(), os);
+      *os << "\n";
+    }
+  }
+};
+
+// The base case.
+template <>
+class TuplePrefix<0> {
+ public:
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& /* matcher_tuple */,
+                      const ValueTuple& /* value_tuple */) {
+    return true;
+  }
+
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */,
+                                     const ValueTuple& /* values */,
+                                     ::std::ostream* /* os */) {}
+};
+
+// TupleMatches(matcher_tuple, value_tuple) returns true if and only if
+// all matchers in matcher_tuple match the corresponding fields in
+// value_tuple.  It is a compiler error if matcher_tuple and
+// value_tuple have different number of fields or incompatible field
+// types.
+template <typename MatcherTuple, typename ValueTuple>
+bool TupleMatches(const MatcherTuple& matcher_tuple,
+                  const ValueTuple& value_tuple) {
+  // Makes sure that matcher_tuple and value_tuple have the same
+  // number of fields.
+  static_assert(std::tuple_size<MatcherTuple>::value ==
+                    std::tuple_size<ValueTuple>::value,
+                "matcher and value have different numbers of fields");
+  return TuplePrefix<std::tuple_size<ValueTuple>::value>::Matches(matcher_tuple,
+                                                                  value_tuple);
+}
+
+// Describes failures in matching matchers against values.  If there
+// is no failure, nothing will be streamed to os.
+template <typename MatcherTuple, typename ValueTuple>
+void ExplainMatchFailureTupleTo(const MatcherTuple& matchers,
+                                const ValueTuple& values, ::std::ostream* os) {
+  TuplePrefix<std::tuple_size<MatcherTuple>::value>::ExplainMatchFailuresTo(
+      matchers, values, os);
+}
+
+// TransformTupleValues and its helper.
+//
+// TransformTupleValuesHelper hides the internal machinery that
+// TransformTupleValues uses to implement a tuple traversal.
+template <typename Tuple, typename Func, typename OutIter>
+class TransformTupleValuesHelper {
+ private:
+  typedef ::std::tuple_size<Tuple> TupleSize;
+
+ public:
+  // For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'.
+  // Returns the final value of 'out' in case the caller needs it.
+  static OutIter Run(Func f, const Tuple& t, OutIter out) {
+    return IterateOverTuple<Tuple, TupleSize::value>()(f, t, out);
+  }
+
+ private:
+  template <typename Tup, size_t kRemainingSize>
+  struct IterateOverTuple {
+    OutIter operator()(Func f, const Tup& t, OutIter out) const {
+      *out++ = f(::std::get<TupleSize::value - kRemainingSize>(t));
+      return IterateOverTuple<Tup, kRemainingSize - 1>()(f, t, out);
+    }
+  };
+  template <typename Tup>
+  struct IterateOverTuple<Tup, 0> {
+    OutIter operator()(Func /* f */, const Tup& /* t */, OutIter out) const {
+      return out;
+    }
+  };
+};
+
+// Successively invokes 'f(element)' on each element of the tuple 't',
+// appending each result to the 'out' iterator. Returns the final value
+// of 'out'.
+template <typename Tuple, typename Func, typename OutIter>
+OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) {
+  return TransformTupleValuesHelper<Tuple, Func, OutIter>::Run(f, t, out);
+}
+
+// Implements _, a matcher that matches any value of any
+// type.  This is a polymorphic matcher, so we need a template type
+// conversion operator to make it appearing as a Matcher<T> for any
+// type T.
+class AnythingMatcher {
+ public:
+  using is_gtest_matcher = void;
+
+  template <typename T>
+  bool MatchAndExplain(const T& /* x */, std::ostream* /* listener */) const {
+    return true;
+  }
+  void DescribeTo(std::ostream* os) const { *os << "is anything"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    // This is mostly for completeness' sake, as it's not very useful
+    // to write Not(A<bool>()).  However we cannot completely rule out
+    // such a possibility, and it doesn't hurt to be prepared.
+    *os << "never matches";
+  }
+};
+
+// Implements the polymorphic IsNull() matcher, which matches any raw or smart
+// pointer that is NULL.
+class IsNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+    return p == nullptr;
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "is NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const { *os << "isn't NULL"; }
+};
+
+// Implements the polymorphic NotNull() matcher, which matches any raw or smart
+// pointer that is not NULL.
+class NotNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+    return p != nullptr;
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; }
+};
+
+// Ref(variable) matches any argument that is a reference to
+// 'variable'.  This matcher is polymorphic as it can match any
+// super type of the type of 'variable'.
+//
+// The RefMatcher template class implements Ref(variable).  It can
+// only be instantiated with a reference type.  This prevents a user
+// from mistakenly using Ref(x) to match a non-reference function
+// argument.  For example, the following will righteously cause a
+// compiler error:
+//
+//   int n;
+//   Matcher<int> m1 = Ref(n);   // This won't compile.
+//   Matcher<int&> m2 = Ref(n);  // This will compile.
+template <typename T>
+class RefMatcher;
+
+template <typename T>
+class RefMatcher<T&> {
+  // Google Mock is a generic framework and thus needs to support
+  // mocking any function types, including those that take non-const
+  // reference arguments.  Therefore the template parameter T (and
+  // Super below) can be instantiated to either a const type or a
+  // non-const type.
+ public:
+  // RefMatcher() takes a T& instead of const T&, as we want the
+  // compiler to catch using Ref(const_value) as a matcher for a
+  // non-const reference.
+  explicit RefMatcher(T& x) : object_(x) {}  // NOLINT
+
+  template <typename Super>
+  operator Matcher<Super&>() const {
+    // By passing object_ (type T&) to Impl(), which expects a Super&,
+    // we make sure that Super is a super type of T.  In particular,
+    // this catches using Ref(const_value) as a matcher for a
+    // non-const reference, as you cannot implicitly convert a const
+    // reference to a non-const reference.
+    return MakeMatcher(new Impl<Super>(object_));
+  }
+
+ private:
+  template <typename Super>
+  class Impl : public MatcherInterface<Super&> {
+   public:
+    explicit Impl(Super& x) : object_(x) {}  // NOLINT
+
+    // MatchAndExplain() takes a Super& (as opposed to const Super&)
+    // in order to match the interface MatcherInterface<Super&>.
+    bool MatchAndExplain(Super& x,
+                         MatchResultListener* listener) const override {
+      *listener << "which is located @" << static_cast<const void*>(&x);
+      return &x == &object_;
+    }
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "references the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "does not reference the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+   private:
+    const Super& object_;
+  };
+
+  T& object_;
+};
+
+// Polymorphic helper functions for narrow and wide string matchers.
+inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) {
+  return String::CaseInsensitiveCStringEquals(lhs, rhs);
+}
+
+inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs,
+                                         const wchar_t* rhs) {
+  return String::CaseInsensitiveWideCStringEquals(lhs, rhs);
+}
+
+// String comparison for narrow or wide strings that can have embedded NUL
+// characters.
+template <typename StringType>
+bool CaseInsensitiveStringEquals(const StringType& s1, const StringType& s2) {
+  // Are the heads equal?
+  if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) {
+    return false;
+  }
+
+  // Skip the equal heads.
+  const typename StringType::value_type nul = 0;
+  const size_t i1 = s1.find(nul), i2 = s2.find(nul);
+
+  // Are we at the end of either s1 or s2?
+  if (i1 == StringType::npos || i2 == StringType::npos) {
+    return i1 == i2;
+  }
+
+  // Are the tails equal?
+  return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1));
+}
+
+// String matchers.
+
+// Implements equality-based string matchers like StrEq, StrCaseNe, and etc.
+template <typename StringType>
+class StrEqualityMatcher {
+ public:
+  StrEqualityMatcher(StringType str, bool expect_eq, bool case_sensitive)
+      : string_(std::move(str)),
+        expect_eq_(expect_eq),
+        case_sensitive_(case_sensitive) {}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  bool MatchAndExplain(const internal::StringView& s,
+                       MatchResultListener* listener) const {
+    // This should fail to compile if StringView is used with wide
+    // strings.
+    const StringType& str = std::string(s);
+    return MatchAndExplain(str, listener);
+  }
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    if (s == nullptr) {
+      return !expect_eq_;
+    }
+    return MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringView has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType s2(s);
+    const bool eq = case_sensitive_ ? s2 == string_
+                                    : CaseInsensitiveStringEquals(s2, string_);
+    return expect_eq_ == eq;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    DescribeToHelper(expect_eq_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    DescribeToHelper(!expect_eq_, os);
+  }
+
+ private:
+  void DescribeToHelper(bool expect_eq, ::std::ostream* os) const {
+    *os << (expect_eq ? "is " : "isn't ");
+    *os << "equal to ";
+    if (!case_sensitive_) {
+      *os << "(ignoring case) ";
+    }
+    UniversalPrint(string_, os);
+  }
+
+  const StringType string_;
+  const bool expect_eq_;
+  const bool case_sensitive_;
+};
+
+// Implements the polymorphic HasSubstr(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class HasSubstrMatcher {
+ public:
+  explicit HasSubstrMatcher(const StringType& substring)
+      : substring_(substring) {}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  bool MatchAndExplain(const internal::StringView& s,
+                       MatchResultListener* listener) const {
+    // This should fail to compile if StringView is used with wide
+    // strings.
+    const StringType& str = std::string(s);
+    return MatchAndExplain(str, listener);
+  }
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != nullptr && MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringView has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    return StringType(s).find(substring_) != StringType::npos;
+  }
+
+  // Describes what this matcher matches.
+  void DescribeTo(::std::ostream* os) const {
+    *os << "has substring ";
+    UniversalPrint(substring_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has no substring ";
+    UniversalPrint(substring_, os);
+  }
+
+ private:
+  const StringType substring_;
+};
+
+// Implements the polymorphic StartsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class StartsWithMatcher {
+ public:
+  explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  bool MatchAndExplain(const internal::StringView& s,
+                       MatchResultListener* listener) const {
+    // This should fail to compile if StringView is used with wide
+    // strings.
+    const StringType& str = std::string(s);
+    return MatchAndExplain(str, listener);
+  }
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != nullptr && MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringView has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType s2(s);
+    return s2.length() >= prefix_.length() &&
+           s2.substr(0, prefix_.length()) == prefix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "starts with ";
+    UniversalPrint(prefix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't start with ";
+    UniversalPrint(prefix_, os);
+  }
+
+ private:
+  const StringType prefix_;
+};
+
+// Implements the polymorphic EndsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class EndsWithMatcher {
+ public:
+  explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  bool MatchAndExplain(const internal::StringView& s,
+                       MatchResultListener* listener) const {
+    // This should fail to compile if StringView is used with wide
+    // strings.
+    const StringType& str = std::string(s);
+    return MatchAndExplain(str, listener);
+  }
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != nullptr && MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringView has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType s2(s);
+    return s2.length() >= suffix_.length() &&
+           s2.substr(s2.length() - suffix_.length()) == suffix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "ends with ";
+    UniversalPrint(suffix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't end with ";
+    UniversalPrint(suffix_, os);
+  }
+
+ private:
+  const StringType suffix_;
+};
+
+// Implements the polymorphic WhenBase64Unescaped(matcher) matcher, which can be
+// used as a Matcher<T> as long as T can be converted to a string.
+class WhenBase64UnescapedMatcher {
+ public:
+  using is_gtest_matcher = void;
+
+  explicit WhenBase64UnescapedMatcher(
+      const Matcher<const std::string&>& internal_matcher)
+      : internal_matcher_(internal_matcher) {}
+
+  // Matches anything that can convert to std::string.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* listener) const {
+    const std::string s2(s);  // NOLINT (needed for working with string_view).
+    std::string unescaped;
+    if (!internal::Base64Unescape(s2, &unescaped)) {
+      if (listener != nullptr) {
+        *listener << "is not a valid base64 escaped string";
+      }
+      return false;
+    }
+    return MatchPrintAndExplain(unescaped, internal_matcher_, listener);
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "matches after Base64Unescape ";
+    internal_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "does not match after Base64Unescape ";
+    internal_matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<const std::string&> internal_matcher_;
+};
+
+// Implements a matcher that compares the two fields of a 2-tuple
+// using one of the ==, <=, <, etc, operators.  The two fields being
+// compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq() can be
+// used to match a std::tuple<int, short>, a std::tuple<const long&, double>,
+// etc).  Therefore we use a template type conversion operator in the
+// implementation.
+template <typename D, typename Op>
+class PairMatchBase {
+ public:
+  template <typename T1, typename T2>
+  operator Matcher<::std::tuple<T1, T2>>() const {
+    return Matcher<::std::tuple<T1, T2>>(new Impl<const ::std::tuple<T1, T2>&>);
+  }
+  template <typename T1, typename T2>
+  operator Matcher<const ::std::tuple<T1, T2>&>() const {
+    return MakeMatcher(new Impl<const ::std::tuple<T1, T2>&>);
+  }
+
+ private:
+  static ::std::ostream& GetDesc(::std::ostream& os) {  // NOLINT
+    return os << D::Desc();
+  }
+
+  template <typename Tuple>
+  class Impl : public MatcherInterface<Tuple> {
+   public:
+    bool MatchAndExplain(Tuple args,
+                         MatchResultListener* /* listener */) const override {
+      return Op()(::std::get<0>(args), ::std::get<1>(args));
+    }
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "are " << GetDesc;
+    }
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "aren't " << GetDesc;
+    }
+  };
+};
+
+class Eq2Matcher : public PairMatchBase<Eq2Matcher, std::equal_to<>> {
+ public:
+  static const char* Desc() { return "an equal pair"; }
+};
+class Ne2Matcher : public PairMatchBase<Ne2Matcher, std::not_equal_to<>> {
+ public:
+  static const char* Desc() { return "an unequal pair"; }
+};
+class Lt2Matcher : public PairMatchBase<Lt2Matcher, std::less<>> {
+ public:
+  static const char* Desc() { return "a pair where the first < the second"; }
+};
+class Gt2Matcher : public PairMatchBase<Gt2Matcher, std::greater<>> {
+ public:
+  static const char* Desc() { return "a pair where the first > the second"; }
+};
+class Le2Matcher : public PairMatchBase<Le2Matcher, std::less_equal<>> {
+ public:
+  static const char* Desc() { return "a pair where the first <= the second"; }
+};
+class Ge2Matcher : public PairMatchBase<Ge2Matcher, std::greater_equal<>> {
+ public:
+  static const char* Desc() { return "a pair where the first >= the second"; }
+};
+
+// Implements the Not(...) matcher for a particular argument type T.
+// We do not nest it inside the NotMatcher class template, as that
+// will prevent different instantiations of NotMatcher from sharing
+// the same NotMatcherImpl<T> class.
+template <typename T>
+class NotMatcherImpl : public MatcherInterface<const T&> {
+ public:
+  explicit NotMatcherImpl(const Matcher<T>& matcher) : matcher_(matcher) {}
+
+  bool MatchAndExplain(const T& x,
+                       MatchResultListener* listener) const override {
+    return !matcher_.MatchAndExplain(x, listener);
+  }
+
+  void DescribeTo(::std::ostream* os) const override {
+    matcher_.DescribeNegationTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<T> matcher_;
+};
+
+// Implements the Not(m) matcher, which matches a value that doesn't
+// match matcher m.
+template <typename InnerMatcher>
+class NotMatcher {
+ public:
+  explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {}
+
+  // This template type conversion operator allows Not(m) to be used
+  // to match any type m can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_)));
+  }
+
+ private:
+  InnerMatcher matcher_;
+};
+
+// Implements the AllOf(m1, m2) matcher for a particular argument type
+// T. We do not nest it inside the BothOfMatcher class template, as
+// that will prevent different instantiations of BothOfMatcher from
+// sharing the same BothOfMatcherImpl<T> class.
+template <typename T>
+class AllOfMatcherImpl : public MatcherInterface<const T&> {
+ public:
+  explicit AllOfMatcherImpl(std::vector<Matcher<T>> matchers)
+      : matchers_(std::move(matchers)) {}
+
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "(";
+    for (size_t i = 0; i < matchers_.size(); ++i) {
+      if (i != 0) *os << ") and (";
+      matchers_[i].DescribeTo(os);
+    }
+    *os << ")";
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "(";
+    for (size_t i = 0; i < matchers_.size(); ++i) {
+      if (i != 0) *os << ") or (";
+      matchers_[i].DescribeNegationTo(os);
+    }
+    *os << ")";
+  }
+
+  bool MatchAndExplain(const T& x,
+                       MatchResultListener* listener) const override {
+    // This method uses matcher's explanation when explaining the result.
+    // However, if matcher doesn't provide one, this method uses matcher's
+    // description.
+    std::string all_match_result;
+    for (const Matcher<T>& matcher : matchers_) {
+      StringMatchResultListener slistener;
+      // Return explanation for first failed matcher.
+      if (!matcher.MatchAndExplain(x, &slistener)) {
+        const std::string explanation = slistener.str();
+        if (!explanation.empty()) {
+          *listener << explanation;
+        } else {
+          *listener << "which doesn't match (" << Describe(matcher) << ")";
+        }
+        return false;
+      }
+      // Keep track of explanations in case all matchers succeed.
+      std::string explanation = slistener.str();
+      if (explanation.empty()) {
+        explanation = Describe(matcher);
+      }
+      if (all_match_result.empty()) {
+        all_match_result = explanation;
+      } else {
+        if (!explanation.empty()) {
+          all_match_result += ", and ";
+          all_match_result += explanation;
+        }
+      }
+    }
+
+    *listener << all_match_result;
+    return true;
+  }
+
+ private:
+  // Returns matcher description as a string.
+  std::string Describe(const Matcher<T>& matcher) const {
+    StringMatchResultListener listener;
+    matcher.DescribeTo(listener.stream());
+    return listener.str();
+  }
+  const std::vector<Matcher<T>> matchers_;
+};
+
+// VariadicMatcher is used for the variadic implementation of
+// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...).
+// CombiningMatcher<T> is used to recursively combine the provided matchers
+// (of type Args...).
+template <template <typename T> class CombiningMatcher, typename... Args>
+class VariadicMatcher {
+ public:
+  VariadicMatcher(const Args&... matchers)  // NOLINT
+      : matchers_(matchers...) {
+    static_assert(sizeof...(Args) > 0, "Must have at least one matcher.");
+  }
+
+  VariadicMatcher(const VariadicMatcher&) = default;
+  VariadicMatcher& operator=(const VariadicMatcher&) = delete;
+
+  // This template type conversion operator allows an
+  // VariadicMatcher<Matcher1, Matcher2...> object to match any type that
+  // all of the provided matchers (Matcher1, Matcher2, ...) can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    std::vector<Matcher<T>> values;
+    CreateVariadicMatcher<T>(&values, std::integral_constant<size_t, 0>());
+    return Matcher<T>(new CombiningMatcher<T>(std::move(values)));
+  }
+
+ private:
+  template <typename T, size_t I>
+  void CreateVariadicMatcher(std::vector<Matcher<T>>* values,
+                             std::integral_constant<size_t, I>) const {
+    values->push_back(SafeMatcherCast<T>(std::get<I>(matchers_)));
+    CreateVariadicMatcher<T>(values, std::integral_constant<size_t, I + 1>());
+  }
+
+  template <typename T>
+  void CreateVariadicMatcher(
+      std::vector<Matcher<T>>*,
+      std::integral_constant<size_t, sizeof...(Args)>) const {}
+
+  std::tuple<Args...> matchers_;
+};
+
+template <typename... Args>
+using AllOfMatcher = VariadicMatcher<AllOfMatcherImpl, Args...>;
+
+// Implements the AnyOf(m1, m2) matcher for a particular argument type
+// T.  We do not nest it inside the AnyOfMatcher class template, as
+// that will prevent different instantiations of AnyOfMatcher from
+// sharing the same EitherOfMatcherImpl<T> class.
+template <typename T>
+class AnyOfMatcherImpl : public MatcherInterface<const T&> {
+ public:
+  explicit AnyOfMatcherImpl(std::vector<Matcher<T>> matchers)
+      : matchers_(std::move(matchers)) {}
+
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "(";
+    for (size_t i = 0; i < matchers_.size(); ++i) {
+      if (i != 0) *os << ") or (";
+      matchers_[i].DescribeTo(os);
+    }
+    *os << ")";
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "(";
+    for (size_t i = 0; i < matchers_.size(); ++i) {
+      if (i != 0) *os << ") and (";
+      matchers_[i].DescribeNegationTo(os);
+    }
+    *os << ")";
+  }
+
+  bool MatchAndExplain(const T& x,
+                       MatchResultListener* listener) const override {
+    std::string no_match_result;
+
+    // If either matcher1_ or matcher2_ matches x, we just need to
+    // explain why *one* of them matches.
+    for (size_t i = 0; i < matchers_.size(); ++i) {
+      StringMatchResultListener slistener;
+      if (matchers_[i].MatchAndExplain(x, &slistener)) {
+        *listener << slistener.str();
+        return true;
+      } else {
+        if (no_match_result.empty()) {
+          no_match_result = slistener.str();
+        } else {
+          std::string result = slistener.str();
+          if (!result.empty()) {
+            no_match_result += ", and ";
+            no_match_result += result;
+          }
+        }
+      }
+    }
+
+    // Otherwise we need to explain why *both* of them fail.
+    *listener << no_match_result;
+    return false;
+  }
+
+ private:
+  const std::vector<Matcher<T>> matchers_;
+};
+
+// AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...).
+template <typename... Args>
+using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>;
+
+// ConditionalMatcher is the implementation of Conditional(cond, m1, m2)
+template <typename MatcherTrue, typename MatcherFalse>
+class ConditionalMatcher {
+ public:
+  ConditionalMatcher(bool condition, MatcherTrue matcher_true,
+                     MatcherFalse matcher_false)
+      : condition_(condition),
+        matcher_true_(std::move(matcher_true)),
+        matcher_false_(std::move(matcher_false)) {}
+
+  template <typename T>
+  operator Matcher<T>() const {  // NOLINT(runtime/explicit)
+    return condition_ ? SafeMatcherCast<T>(matcher_true_)
+                      : SafeMatcherCast<T>(matcher_false_);
+  }
+
+ private:
+  bool condition_;
+  MatcherTrue matcher_true_;
+  MatcherFalse matcher_false_;
+};
+
+// Wrapper for implementation of Any/AllOfArray().
+template <template <class> class MatcherImpl, typename T>
+class SomeOfArrayMatcher {
+ public:
+  // Constructs the matcher from a sequence of element values or
+  // element matchers.
+  template <typename Iter>
+  SomeOfArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
+
+  template <typename U>
+  operator Matcher<U>() const {  // NOLINT
+    using RawU = typename std::decay<U>::type;
+    std::vector<Matcher<RawU>> matchers;
+    matchers.reserve(matchers_.size());
+    for (const auto& matcher : matchers_) {
+      matchers.push_back(MatcherCast<RawU>(matcher));
+    }
+    return Matcher<U>(new MatcherImpl<RawU>(std::move(matchers)));
+  }
+
+ private:
+  const ::std::vector<T> matchers_;
+};
+
+template <typename T>
+using AllOfArrayMatcher = SomeOfArrayMatcher<AllOfMatcherImpl, T>;
+
+template <typename T>
+using AnyOfArrayMatcher = SomeOfArrayMatcher<AnyOfMatcherImpl, T>;
+
+// Used for implementing Truly(pred), which turns a predicate into a
+// matcher.
+template <typename Predicate>
+class TrulyMatcher {
+ public:
+  explicit TrulyMatcher(Predicate pred) : predicate_(pred) {}
+
+  // This method template allows Truly(pred) to be used as a matcher
+  // for type T where T is the argument type of predicate 'pred'.  The
+  // argument is passed by reference as the predicate may be
+  // interested in the address of the argument.
+  template <typename T>
+  bool MatchAndExplain(T& x,  // NOLINT
+                       MatchResultListener* listener) const {
+    // Without the if-statement, MSVC sometimes warns about converting
+    // a value to bool (warning 4800).
+    //
+    // We cannot write 'return !!predicate_(x);' as that doesn't work
+    // when predicate_(x) returns a class convertible to bool but
+    // having no operator!().
+    if (predicate_(x)) return true;
+    *listener << "didn't satisfy the given predicate";
+    return false;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "satisfies the given predicate";
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't satisfy the given predicate";
+  }
+
+ private:
+  Predicate predicate_;
+};
+
+// Used for implementing Matches(matcher), which turns a matcher into
+// a predicate.
+template <typename M>
+class MatcherAsPredicate {
+ public:
+  explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {}
+
+  // This template operator() allows Matches(m) to be used as a
+  // predicate on type T where m is a matcher on type T.
+  //
+  // The argument x is passed by reference instead of by value, as
+  // some matcher may be interested in its address (e.g. as in
+  // Matches(Ref(n))(x)).
+  template <typename T>
+  bool operator()(const T& x) const {
+    // We let matcher_ commit to a particular type here instead of
+    // when the MatcherAsPredicate object was constructed.  This
+    // allows us to write Matches(m) where m is a polymorphic matcher
+    // (e.g. Eq(5)).
+    //
+    // If we write Matcher<T>(matcher_).Matches(x) here, it won't
+    // compile when matcher_ has type Matcher<const T&>; if we write
+    // Matcher<const T&>(matcher_).Matches(x) here, it won't compile
+    // when matcher_ has type Matcher<T>; if we just write
+    // matcher_.Matches(x), it won't compile when matcher_ is
+    // polymorphic, e.g. Eq(5).
+    //
+    // MatcherCast<const T&>() is necessary for making the code work
+    // in all of the above situations.
+    return MatcherCast<const T&>(matcher_).Matches(x);
+  }
+
+ private:
+  M matcher_;
+};
+
+// For implementing ASSERT_THAT() and EXPECT_THAT().  The template
+// argument M must be a type that can be converted to a matcher.
+template <typename M>
+class PredicateFormatterFromMatcher {
+ public:
+  explicit PredicateFormatterFromMatcher(M m) : matcher_(std::move(m)) {}
+
+  // This template () operator allows a PredicateFormatterFromMatcher
+  // object to act as a predicate-formatter suitable for using with
+  // Google Test's EXPECT_PRED_FORMAT1() macro.
+  template <typename T>
+  AssertionResult operator()(const char* value_text, const T& x) const {
+    // We convert matcher_ to a Matcher<const T&> *now* instead of
+    // when the PredicateFormatterFromMatcher object was constructed,
+    // as matcher_ may be polymorphic (e.g. NotNull()) and we won't
+    // know which type to instantiate it to until we actually see the
+    // type of x here.
+    //
+    // We write SafeMatcherCast<const T&>(matcher_) instead of
+    // Matcher<const T&>(matcher_), as the latter won't compile when
+    // matcher_ has type Matcher<T> (e.g. An<int>()).
+    // We don't write MatcherCast<const T&> either, as that allows
+    // potentially unsafe downcasting of the matcher argument.
+    const Matcher<const T&> matcher = SafeMatcherCast<const T&>(matcher_);
+
+    // The expected path here is that the matcher should match (i.e. that most
+    // tests pass) so optimize for this case.
+    if (matcher.Matches(x)) {
+      return AssertionSuccess();
+    }
+
+    ::std::stringstream ss;
+    ss << "Value of: " << value_text << "\n"
+       << "Expected: ";
+    matcher.DescribeTo(&ss);
+
+    // Rerun the matcher to "PrintAndExplain" the failure.
+    StringMatchResultListener listener;
+    if (MatchPrintAndExplain(x, matcher, &listener)) {
+      ss << "\n  The matcher failed on the initial attempt; but passed when "
+            "rerun to generate the explanation.";
+    }
+    ss << "\n  Actual: " << listener.str();
+    return AssertionFailure() << ss.str();
+  }
+
+ private:
+  const M matcher_;
+};
+
+// A helper function for converting a matcher to a predicate-formatter
+// without the user needing to explicitly write the type.  This is
+// used for implementing ASSERT_THAT() and EXPECT_THAT().
+// Implementation detail: 'matcher' is received by-value to force decaying.
+template <typename M>
+inline PredicateFormatterFromMatcher<M> MakePredicateFormatterFromMatcher(
+    M matcher) {
+  return PredicateFormatterFromMatcher<M>(std::move(matcher));
+}
+
+// Implements the polymorphic IsNan() matcher, which matches any floating type
+// value that is Nan.
+class IsNanMatcher {
+ public:
+  template <typename FloatType>
+  bool MatchAndExplain(const FloatType& f,
+                       MatchResultListener* /* listener */) const {
+    return (::std::isnan)(f);
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "is NaN"; }
+  void DescribeNegationTo(::std::ostream* os) const { *os << "isn't NaN"; }
+};
+
+// Implements the polymorphic floating point equality matcher, which matches
+// two float values using ULP-based approximation or, optionally, a
+// user-specified epsilon.  The template is meant to be instantiated with
+// FloatType being either float or double.
+template <typename FloatType>
+class FloatingEqMatcher {
+ public:
+  // Constructor for FloatingEqMatcher.
+  // The matcher's input will be compared with expected.  The matcher treats two
+  // NANs as equal if nan_eq_nan is true.  Otherwise, under IEEE standards,
+  // equality comparisons between NANs will always return false.  We specify a
+  // negative max_abs_error_ term to indicate that ULP-based approximation will
+  // be used for comparison.
+  FloatingEqMatcher(FloatType expected, bool nan_eq_nan)
+      : expected_(expected), nan_eq_nan_(nan_eq_nan), max_abs_error_(-1) {}
+
+  // Constructor that supports a user-specified max_abs_error that will be used
+  // for comparison instead of ULP-based approximation.  The max absolute
+  // should be non-negative.
+  FloatingEqMatcher(FloatType expected, bool nan_eq_nan,
+                    FloatType max_abs_error)
+      : expected_(expected),
+        nan_eq_nan_(nan_eq_nan),
+        max_abs_error_(max_abs_error) {
+    GTEST_CHECK_(max_abs_error >= 0)
+        << ", where max_abs_error is" << max_abs_error;
+  }
+
+  // Implements floating point equality matcher as a Matcher<T>.
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(FloatType expected, bool nan_eq_nan, FloatType max_abs_error)
+        : expected_(expected),
+          nan_eq_nan_(nan_eq_nan),
+          max_abs_error_(max_abs_error) {}
+
+    bool MatchAndExplain(T value,
+                         MatchResultListener* listener) const override {
+      const FloatingPoint<FloatType> actual(value), expected(expected_);
+
+      // Compares NaNs first, if nan_eq_nan_ is true.
+      if (actual.is_nan() || expected.is_nan()) {
+        if (actual.is_nan() && expected.is_nan()) {
+          return nan_eq_nan_;
+        }
+        // One is nan; the other is not nan.
+        return false;
+      }
+      if (HasMaxAbsError()) {
+        // We perform an equality check so that inf will match inf, regardless
+        // of error bounds.  If the result of value - expected_ would result in
+        // overflow or if either value is inf, the default result is infinity,
+        // which should only match if max_abs_error_ is also infinity.
+        if (value == expected_) {
+          return true;
+        }
+
+        const FloatType diff = value - expected_;
+        if (::std::fabs(diff) <= max_abs_error_) {
+          return true;
+        }
+
+        if (listener->IsInterested()) {
+          *listener << "which is " << diff << " from " << expected_;
+        }
+        return false;
+      } else {
+        return actual.AlmostEquals(expected);
+      }
+    }
+
+    void DescribeTo(::std::ostream* os) const override {
+      // os->precision() returns the previously set precision, which we
+      // store to restore the ostream to its original configuration
+      // after outputting.
+      const ::std::streamsize old_precision =
+          os->precision(::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(expected_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "is NaN";
+        } else {
+          *os << "never matches";
+        }
+      } else {
+        *os << "is approximately " << expected_;
+        if (HasMaxAbsError()) {
+          *os << " (absolute error <= " << max_abs_error_ << ")";
+        }
+      }
+      os->precision(old_precision);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      // As before, get original precision.
+      const ::std::streamsize old_precision =
+          os->precision(::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(expected_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "isn't NaN";
+        } else {
+          *os << "is anything";
+        }
+      } else {
+        *os << "isn't approximately " << expected_;
+        if (HasMaxAbsError()) {
+          *os << " (absolute error > " << max_abs_error_ << ")";
+        }
+      }
+      // Restore original precision.
+      os->precision(old_precision);
+    }
+
+   private:
+    bool HasMaxAbsError() const { return max_abs_error_ >= 0; }
+
+    const FloatType expected_;
+    const bool nan_eq_nan_;
+    // max_abs_error will be used for value comparison when >= 0.
+    const FloatType max_abs_error_;
+  };
+
+  // The following 3 type conversion operators allow FloatEq(expected) and
+  // NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a
+  // Matcher<const float&>, or a Matcher<float&>, but nothing else.
+  operator Matcher<FloatType>() const {
+    return MakeMatcher(
+        new Impl<FloatType>(expected_, nan_eq_nan_, max_abs_error_));
+  }
+
+  operator Matcher<const FloatType&>() const {
+    return MakeMatcher(
+        new Impl<const FloatType&>(expected_, nan_eq_nan_, max_abs_error_));
+  }
+
+  operator Matcher<FloatType&>() const {
+    return MakeMatcher(
+        new Impl<FloatType&>(expected_, nan_eq_nan_, max_abs_error_));
+  }
+
+ private:
+  const FloatType expected_;
+  const bool nan_eq_nan_;
+  // max_abs_error will be used for value comparison when >= 0.
+  const FloatType max_abs_error_;
+};
+
+// A 2-tuple ("binary") wrapper around FloatingEqMatcher:
+// FloatingEq2Matcher() matches (x, y) by matching FloatingEqMatcher(x, false)
+// against y, and FloatingEq2Matcher(e) matches FloatingEqMatcher(x, false, e)
+// against y. The former implements "Eq", the latter "Near". At present, there
+// is no version that compares NaNs as equal.
+template <typename FloatType>
+class FloatingEq2Matcher {
+ public:
+  FloatingEq2Matcher() { Init(-1, false); }
+
+  explicit FloatingEq2Matcher(bool nan_eq_nan) { Init(-1, nan_eq_nan); }
+
+  explicit FloatingEq2Matcher(FloatType max_abs_error) {
+    Init(max_abs_error, false);
+  }
+
+  FloatingEq2Matcher(FloatType max_abs_error, bool nan_eq_nan) {
+    Init(max_abs_error, nan_eq_nan);
+  }
+
+  template <typename T1, typename T2>
+  operator Matcher<::std::tuple<T1, T2>>() const {
+    return MakeMatcher(
+        new Impl<::std::tuple<T1, T2>>(max_abs_error_, nan_eq_nan_));
+  }
+  template <typename T1, typename T2>
+  operator Matcher<const ::std::tuple<T1, T2>&>() const {
+    return MakeMatcher(
+        new Impl<const ::std::tuple<T1, T2>&>(max_abs_error_, nan_eq_nan_));
+  }
+
+ private:
+  static ::std::ostream& GetDesc(::std::ostream& os) {  // NOLINT
+    return os << "an almost-equal pair";
+  }
+
+  template <typename Tuple>
+  class Impl : public MatcherInterface<Tuple> {
+   public:
+    Impl(FloatType max_abs_error, bool nan_eq_nan)
+        : max_abs_error_(max_abs_error), nan_eq_nan_(nan_eq_nan) {}
+
+    bool MatchAndExplain(Tuple args,
+                         MatchResultListener* listener) const override {
+      if (max_abs_error_ == -1) {
+        FloatingEqMatcher<FloatType> fm(::std::get<0>(args), nan_eq_nan_);
+        return static_cast<Matcher<FloatType>>(fm).MatchAndExplain(
+            ::std::get<1>(args), listener);
+      } else {
+        FloatingEqMatcher<FloatType> fm(::std::get<0>(args), nan_eq_nan_,
+                                        max_abs_error_);
+        return static_cast<Matcher<FloatType>>(fm).MatchAndExplain(
+            ::std::get<1>(args), listener);
+      }
+    }
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "are " << GetDesc;
+    }
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "aren't " << GetDesc;
+    }
+
+   private:
+    FloatType max_abs_error_;
+    const bool nan_eq_nan_;
+  };
+
+  void Init(FloatType max_abs_error_val, bool nan_eq_nan_val) {
+    max_abs_error_ = max_abs_error_val;
+    nan_eq_nan_ = nan_eq_nan_val;
+  }
+  FloatType max_abs_error_;
+  bool nan_eq_nan_;
+};
+
+// Implements the Pointee(m) matcher for matching a pointer whose
+// pointee matches matcher m.  The pointer can be either raw or smart.
+template <typename InnerMatcher>
+class PointeeMatcher {
+ public:
+  explicit PointeeMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
+
+  // This type conversion operator template allows Pointee(m) to be
+  // used as a matcher for any pointer type whose pointee type is
+  // compatible with the inner matcher, where type Pointer can be
+  // either a raw pointer or a smart pointer.
+  //
+  // The reason we do this instead of relying on
+  // MakePolymorphicMatcher() is that the latter is not flexible
+  // enough for implementing the DescribeTo() method of Pointee().
+  template <typename Pointer>
+  operator Matcher<Pointer>() const {
+    return Matcher<Pointer>(new Impl<const Pointer&>(matcher_));
+  }
+
+ private:
+  // The monomorphic implementation that works for a particular pointer type.
+  template <typename Pointer>
+  class Impl : public MatcherInterface<Pointer> {
+   public:
+    using Pointee =
+        typename std::pointer_traits<GTEST_REMOVE_REFERENCE_AND_CONST_(
+            Pointer)>::element_type;
+
+    explicit Impl(const InnerMatcher& matcher)
+        : matcher_(MatcherCast<const Pointee&>(matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "points to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "does not point to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    bool MatchAndExplain(Pointer pointer,
+                         MatchResultListener* listener) const override {
+      if (GetRawPointer(pointer) == nullptr) return false;
+
+      *listener << "which points to ";
+      return MatchPrintAndExplain(*pointer, matcher_, listener);
+    }
+
+   private:
+    const Matcher<const Pointee&> matcher_;
+  };
+
+  const InnerMatcher matcher_;
+};
+
+// Implements the Pointer(m) matcher
+// Implements the Pointer(m) matcher for matching a pointer that matches matcher
+// m.  The pointer can be either raw or smart, and will match `m` against the
+// raw pointer.
+template <typename InnerMatcher>
+class PointerMatcher {
+ public:
+  explicit PointerMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
+
+  // This type conversion operator template allows Pointer(m) to be
+  // used as a matcher for any pointer type whose pointer type is
+  // compatible with the inner matcher, where type PointerType can be
+  // either a raw pointer or a smart pointer.
+  //
+  // The reason we do this instead of relying on
+  // MakePolymorphicMatcher() is that the latter is not flexible
+  // enough for implementing the DescribeTo() method of Pointer().
+  template <typename PointerType>
+  operator Matcher<PointerType>() const {  // NOLINT
+    return Matcher<PointerType>(new Impl<const PointerType&>(matcher_));
+  }
+
+ private:
+  // The monomorphic implementation that works for a particular pointer type.
+  template <typename PointerType>
+  class Impl : public MatcherInterface<PointerType> {
+   public:
+    using Pointer =
+        const typename std::pointer_traits<GTEST_REMOVE_REFERENCE_AND_CONST_(
+            PointerType)>::element_type*;
+
+    explicit Impl(const InnerMatcher& matcher)
+        : matcher_(MatcherCast<Pointer>(matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "is a pointer that ";
+      matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "is not a pointer that ";
+      matcher_.DescribeTo(os);
+    }
+
+    bool MatchAndExplain(PointerType pointer,
+                         MatchResultListener* listener) const override {
+      *listener << "which is a pointer that ";
+      Pointer p = GetRawPointer(pointer);
+      return MatchPrintAndExplain(p, matcher_, listener);
+    }
+
+   private:
+    Matcher<Pointer> matcher_;
+  };
+
+  const InnerMatcher matcher_;
+};
+
+#if GTEST_HAS_RTTI
+// Implements the WhenDynamicCastTo<T>(m) matcher that matches a pointer or
+// reference that matches inner_matcher when dynamic_cast<T> is applied.
+// The result of dynamic_cast<To> is forwarded to the inner matcher.
+// If To is a pointer and the cast fails, the inner matcher will receive NULL.
+// If To is a reference and the cast fails, this matcher returns false
+// immediately.
+template <typename To>
+class WhenDynamicCastToMatcherBase {
+ public:
+  explicit WhenDynamicCastToMatcherBase(const Matcher<To>& matcher)
+      : matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    GetCastTypeDescription(os);
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    GetCastTypeDescription(os);
+    matcher_.DescribeNegationTo(os);
+  }
+
+ protected:
+  const Matcher<To> matcher_;
+
+  static std::string GetToName() { return GetTypeName<To>(); }
+
+ private:
+  static void GetCastTypeDescription(::std::ostream* os) {
+    *os << "when dynamic_cast to " << GetToName() << ", ";
+  }
+};
+
+// Primary template.
+// To is a pointer. Cast and forward the result.
+template <typename To>
+class WhenDynamicCastToMatcher : public WhenDynamicCastToMatcherBase<To> {
+ public:
+  explicit WhenDynamicCastToMatcher(const Matcher<To>& matcher)
+      : WhenDynamicCastToMatcherBase<To>(matcher) {}
+
+  template <typename From>
+  bool MatchAndExplain(From from, MatchResultListener* listener) const {
+    To to = dynamic_cast<To>(from);
+    return MatchPrintAndExplain(to, this->matcher_, listener);
+  }
+};
+
+// Specialize for references.
+// In this case we return false if the dynamic_cast fails.
+template <typename To>
+class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
+ public:
+  explicit WhenDynamicCastToMatcher(const Matcher<To&>& matcher)
+      : WhenDynamicCastToMatcherBase<To&>(matcher) {}
+
+  template <typename From>
+  bool MatchAndExplain(From& from, MatchResultListener* listener) const {
+    // We don't want an std::bad_cast here, so do the cast with pointers.
+    To* to = dynamic_cast<To*>(&from);
+    if (to == nullptr) {
+      *listener << "which cannot be dynamic_cast to " << this->GetToName();
+      return false;
+    }
+    return MatchPrintAndExplain(*to, this->matcher_, listener);
+  }
+};
+#endif  // GTEST_HAS_RTTI
+
+// Implements the Field() matcher for matching a field (i.e. member
+// variable) of an object.
+template <typename Class, typename FieldType>
+class FieldMatcher {
+ public:
+  FieldMatcher(FieldType Class::*field,
+               const Matcher<const FieldType&>& matcher)
+      : field_(field), matcher_(matcher), whose_field_("whose given field ") {}
+
+  FieldMatcher(const std::string& field_name, FieldType Class::*field,
+               const Matcher<const FieldType&>& matcher)
+      : field_(field),
+        matcher_(matcher),
+        whose_field_("whose field `" + field_name + "` ") {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object " << whose_field_;
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object " << whose_field_;
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T& value, MatchResultListener* listener) const {
+    // FIXME: The dispatch on std::is_pointer was introduced as a workaround for
+    // a compiler bug, and can now be removed.
+    return MatchAndExplainImpl(
+        typename std::is_pointer<typename std::remove_const<T>::type>::type(),
+        value, listener);
+  }
+
+ private:
+  bool MatchAndExplainImpl(std::false_type /* is_not_pointer */,
+                           const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << whose_field_ << "is ";
+    return MatchPrintAndExplain(obj.*field_, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(std::true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == nullptr) return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a field, it must be a class/struct/union type and
+    // thus cannot be a pointer.  Therefore we pass false_type() as
+    // the first argument.
+    return MatchAndExplainImpl(std::false_type(), *p, listener);
+  }
+
+  const FieldType Class::*field_;
+  const Matcher<const FieldType&> matcher_;
+
+  // Contains either "whose given field " if the name of the field is unknown
+  // or "whose field `name_of_field` " if the name is known.
+  const std::string whose_field_;
+};
+
+// Implements the Property() matcher for matching a property
+// (i.e. return value of a getter method) of an object.
+//
+// Property is a const-qualified member function of Class returning
+// PropertyType.
+template <typename Class, typename PropertyType, typename Property>
+class PropertyMatcher {
+ public:
+  typedef const PropertyType& RefToConstProperty;
+
+  PropertyMatcher(Property property, const Matcher<RefToConstProperty>& matcher)
+      : property_(property),
+        matcher_(matcher),
+        whose_property_("whose given property ") {}
+
+  PropertyMatcher(const std::string& property_name, Property property,
+                  const Matcher<RefToConstProperty>& matcher)
+      : property_(property),
+        matcher_(matcher),
+        whose_property_("whose property `" + property_name + "` ") {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object " << whose_property_;
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object " << whose_property_;
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T& value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename std::is_pointer<typename std::remove_const<T>::type>::type(),
+        value, listener);
+  }
+
+ private:
+  bool MatchAndExplainImpl(std::false_type /* is_not_pointer */,
+                           const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << whose_property_ << "is ";
+    // Cannot pass the return value (for example, int) to MatchPrintAndExplain,
+    // which takes a non-const reference as argument.
+    RefToConstProperty result = (obj.*property_)();
+    return MatchPrintAndExplain(result, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(std::true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == nullptr) return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a property method, it must be a class/struct/union
+    // type and thus cannot be a pointer.  Therefore we pass
+    // false_type() as the first argument.
+    return MatchAndExplainImpl(std::false_type(), *p, listener);
+  }
+
+  Property property_;
+  const Matcher<RefToConstProperty> matcher_;
+
+  // Contains either "whose given property " if the name of the property is
+  // unknown or "whose property `name_of_property` " if the name is known.
+  const std::string whose_property_;
+};
+
+// Type traits specifying various features of different functors for ResultOf.
+// The default template specifies features for functor objects.
+template <typename Functor>
+struct CallableTraits {
+  typedef Functor StorageType;
+
+  static void CheckIsValid(Functor /* functor */) {}
+
+  template <typename T>
+  static auto Invoke(Functor f, const T& arg) -> decltype(f(arg)) {
+    return f(arg);
+  }
+};
+
+// Specialization for function pointers.
+template <typename ArgType, typename ResType>
+struct CallableTraits<ResType (*)(ArgType)> {
+  typedef ResType ResultType;
+  typedef ResType (*StorageType)(ArgType);
+
+  static void CheckIsValid(ResType (*f)(ArgType)) {
+    GTEST_CHECK_(f != nullptr)
+        << "NULL function pointer is passed into ResultOf().";
+  }
+  template <typename T>
+  static ResType Invoke(ResType (*f)(ArgType), T arg) {
+    return (*f)(arg);
+  }
+};
+
+// Implements the ResultOf() matcher for matching a return value of a
+// unary function of an object.
+template <typename Callable, typename InnerMatcher>
+class ResultOfMatcher {
+ public:
+  ResultOfMatcher(Callable callable, InnerMatcher matcher)
+      : ResultOfMatcher(/*result_description=*/"", std::move(callable),
+                        std::move(matcher)) {}
+
+  ResultOfMatcher(const std::string& result_description, Callable callable,
+                  InnerMatcher matcher)
+      : result_description_(result_description),
+        callable_(std::move(callable)),
+        matcher_(std::move(matcher)) {
+    CallableTraits<Callable>::CheckIsValid(callable_);
+  }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(
+        new Impl<const T&>(result_description_, callable_, matcher_));
+  }
+
+ private:
+  typedef typename CallableTraits<Callable>::StorageType CallableStorageType;
+
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+    using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
+        std::declval<CallableStorageType>(), std::declval<T>()));
+
+   public:
+    template <typename M>
+    Impl(const std::string& result_description,
+         const CallableStorageType& callable, const M& matcher)
+        : result_description_(result_description),
+          callable_(callable),
+          matcher_(MatcherCast<ResultType>(matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      if (result_description_.empty()) {
+        *os << "is mapped by the given callable to a value that ";
+      } else {
+        *os << "whose " << result_description_ << " ";
+      }
+      matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      if (result_description_.empty()) {
+        *os << "is mapped by the given callable to a value that ";
+      } else {
+        *os << "whose " << result_description_ << " ";
+      }
+      matcher_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(T obj, MatchResultListener* listener) const override {
+      if (result_description_.empty()) {
+        *listener << "which is mapped by the given callable to ";
+      } else {
+        *listener << "whose " << result_description_ << " is ";
+      }
+      // Cannot pass the return value directly to MatchPrintAndExplain, which
+      // takes a non-const reference as argument.
+      // Also, specifying template argument explicitly is needed because T could
+      // be a non-const reference (e.g. Matcher<Uncopyable&>).
+      ResultType result =
+          CallableTraits<Callable>::template Invoke<T>(callable_, obj);
+      return MatchPrintAndExplain(result, matcher_, listener);
+    }
+
+   private:
+    const std::string result_description_;
+    // Functors often define operator() as non-const method even though
+    // they are actually stateless. But we need to use them even when
+    // 'this' is a const pointer. It's the user's responsibility not to
+    // use stateful callables with ResultOf(), which doesn't guarantee
+    // how many times the callable will be invoked.
+    mutable CallableStorageType callable_;
+    const Matcher<ResultType> matcher_;
+  };  // class Impl
+
+  const std::string result_description_;
+  const CallableStorageType callable_;
+  const InnerMatcher matcher_;
+};
+
+// Implements a matcher that checks the size of an STL-style container.
+template <typename SizeMatcher>
+class SizeIsMatcher {
+ public:
+  explicit SizeIsMatcher(const SizeMatcher& size_matcher)
+      : size_matcher_(size_matcher) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return Matcher<Container>(new Impl<const Container&>(size_matcher_));
+  }
+
+  template <typename Container>
+  class Impl : public MatcherInterface<Container> {
+   public:
+    using SizeType = decltype(std::declval<Container>().size());
+    explicit Impl(const SizeMatcher& size_matcher)
+        : size_matcher_(MatcherCast<SizeType>(size_matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "has a size that ";
+      size_matcher_.DescribeTo(os);
+    }
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "has a size that ";
+      size_matcher_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(Container container,
+                         MatchResultListener* listener) const override {
+      SizeType size = container.size();
+      StringMatchResultListener size_listener;
+      const bool result = size_matcher_.MatchAndExplain(size, &size_listener);
+      *listener << "whose size " << size
+                << (result ? " matches" : " doesn't match");
+      PrintIfNotEmpty(size_listener.str(), listener->stream());
+      return result;
+    }
+
+   private:
+    const Matcher<SizeType> size_matcher_;
+  };
+
+ private:
+  const SizeMatcher size_matcher_;
+};
+
+// Implements a matcher that checks the begin()..end() distance of an STL-style
+// container.
+template <typename DistanceMatcher>
+class BeginEndDistanceIsMatcher {
+ public:
+  explicit BeginEndDistanceIsMatcher(const DistanceMatcher& distance_matcher)
+      : distance_matcher_(distance_matcher) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return Matcher<Container>(new Impl<const Container&>(distance_matcher_));
+  }
+
+  template <typename Container>
+  class Impl : public MatcherInterface<Container> {
+   public:
+    typedef internal::StlContainerView<GTEST_REMOVE_REFERENCE_AND_CONST_(
+        Container)>
+        ContainerView;
+    typedef typename std::iterator_traits<
+        typename ContainerView::type::const_iterator>::difference_type
+        DistanceType;
+    explicit Impl(const DistanceMatcher& distance_matcher)
+        : distance_matcher_(MatcherCast<DistanceType>(distance_matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "distance between begin() and end() ";
+      distance_matcher_.DescribeTo(os);
+    }
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "distance between begin() and end() ";
+      distance_matcher_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(Container container,
+                         MatchResultListener* listener) const override {
+      using std::begin;
+      using std::end;
+      DistanceType distance = std::distance(begin(container), end(container));
+      StringMatchResultListener distance_listener;
+      const bool result =
+          distance_matcher_.MatchAndExplain(distance, &distance_listener);
+      *listener << "whose distance between begin() and end() " << distance
+                << (result ? " matches" : " doesn't match");
+      PrintIfNotEmpty(distance_listener.str(), listener->stream());
+      return result;
+    }
+
+   private:
+    const Matcher<DistanceType> distance_matcher_;
+  };
+
+ private:
+  const DistanceMatcher distance_matcher_;
+};
+
+// Implements an equality matcher for any STL-style container whose elements
+// support ==. This matcher is like Eq(), but its failure explanations provide
+// more detailed information that is useful when the container is used as a set.
+// The failure message reports elements that are in one of the operands but not
+// the other. The failure messages do not report duplicate or out-of-order
+// elements in the containers (which don't properly matter to sets, but can
+// occur if the containers are vectors or lists, for example).
+//
+// Uses the container's const_iterator, value_type, operator ==,
+// begin(), and end().
+template <typename Container>
+class ContainerEqMatcher {
+ public:
+  typedef internal::StlContainerView<Container> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+
+  static_assert(!std::is_const<Container>::value,
+                "Container type must not be const");
+  static_assert(!std::is_reference<Container>::value,
+                "Container type must not be a reference");
+
+  // We make a copy of expected in case the elements in it are modified
+  // after this matcher is created.
+  explicit ContainerEqMatcher(const Container& expected)
+      : expected_(View::Copy(expected)) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "equals ";
+    UniversalPrint(expected_, os);
+  }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "does not equal ";
+    UniversalPrint(expected_, os);
+  }
+
+  template <typename LhsContainer>
+  bool MatchAndExplain(const LhsContainer& lhs,
+                       MatchResultListener* listener) const {
+    typedef internal::StlContainerView<
+        typename std::remove_const<LhsContainer>::type>
+        LhsView;
+    StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+    if (lhs_stl_container == expected_) return true;
+
+    ::std::ostream* const os = listener->stream();
+    if (os != nullptr) {
+      // Something is different. Check for extra values first.
+      bool printed_header = false;
+      for (auto it = lhs_stl_container.begin(); it != lhs_stl_container.end();
+           ++it) {
+        if (internal::ArrayAwareFind(expected_.begin(), expected_.end(), *it) ==
+            expected_.end()) {
+          if (printed_header) {
+            *os << ", ";
+          } else {
+            *os << "which has these unexpected elements: ";
+            printed_header = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+
+      // Now check for missing values.
+      bool printed_header2 = false;
+      for (auto it = expected_.begin(); it != expected_.end(); ++it) {
+        if (internal::ArrayAwareFind(lhs_stl_container.begin(),
+                                     lhs_stl_container.end(),
+                                     *it) == lhs_stl_container.end()) {
+          if (printed_header2) {
+            *os << ", ";
+          } else {
+            *os << (printed_header ? ",\nand" : "which")
+                << " doesn't have these expected elements: ";
+            printed_header2 = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+    }
+
+    return false;
+  }
+
+ private:
+  const StlContainer expected_;
+};
+
+// A comparator functor that uses the < operator to compare two values.
+struct LessComparator {
+  template <typename T, typename U>
+  bool operator()(const T& lhs, const U& rhs) const {
+    return lhs < rhs;
+  }
+};
+
+// Implements WhenSortedBy(comparator, container_matcher).
+template <typename Comparator, typename ContainerMatcher>
+class WhenSortedByMatcher {
+ public:
+  WhenSortedByMatcher(const Comparator& comparator,
+                      const ContainerMatcher& matcher)
+      : comparator_(comparator), matcher_(matcher) {}
+
+  template <typename LhsContainer>
+  operator Matcher<LhsContainer>() const {
+    return MakeMatcher(new Impl<LhsContainer>(comparator_, matcher_));
+  }
+
+  template <typename LhsContainer>
+  class Impl : public MatcherInterface<LhsContainer> {
+   public:
+    typedef internal::StlContainerView<GTEST_REMOVE_REFERENCE_AND_CONST_(
+        LhsContainer)>
+        LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    typedef typename LhsView::const_reference LhsStlContainerReference;
+    // Transforms std::pair<const Key, Value> into std::pair<Key, Value>
+    // so that we can match associative containers.
+    typedef
+        typename RemoveConstFromKey<typename LhsStlContainer::value_type>::type
+            LhsValue;
+
+    Impl(const Comparator& comparator, const ContainerMatcher& matcher)
+        : comparator_(comparator), matcher_(matcher) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "(when sorted) ";
+      matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "(when sorted) ";
+      matcher_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(LhsContainer lhs,
+                         MatchResultListener* listener) const override {
+      LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+      ::std::vector<LhsValue> sorted_container(lhs_stl_container.begin(),
+                                               lhs_stl_container.end());
+      ::std::sort(sorted_container.begin(), sorted_container.end(),
+                  comparator_);
+
+      if (!listener->IsInterested()) {
+        // If the listener is not interested, we do not need to
+        // construct the inner explanation.
+        return matcher_.Matches(sorted_container);
+      }
+
+      *listener << "which is ";
+      UniversalPrint(sorted_container, listener->stream());
+      *listener << " when sorted";
+
+      StringMatchResultListener inner_listener;
+      const bool match =
+          matcher_.MatchAndExplain(sorted_container, &inner_listener);
+      PrintIfNotEmpty(inner_listener.str(), listener->stream());
+      return match;
+    }
+
+   private:
+    const Comparator comparator_;
+    const Matcher<const ::std::vector<LhsValue>&> matcher_;
+
+    Impl(const Impl&) = delete;
+    Impl& operator=(const Impl&) = delete;
+  };
+
+ private:
+  const Comparator comparator_;
+  const ContainerMatcher matcher_;
+};
+
+// Implements Pointwise(tuple_matcher, rhs_container).  tuple_matcher
+// must be able to be safely cast to Matcher<std::tuple<const T1&, const
+// T2&> >, where T1 and T2 are the types of elements in the LHS
+// container and the RHS container respectively.
+template <typename TupleMatcher, typename RhsContainer>
+class PointwiseMatcher {
+  static_assert(
+      !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value,
+      "use UnorderedPointwise with hash tables");
+
+ public:
+  typedef internal::StlContainerView<RhsContainer> RhsView;
+  typedef typename RhsView::type RhsStlContainer;
+  typedef typename RhsStlContainer::value_type RhsValue;
+
+  static_assert(!std::is_const<RhsContainer>::value,
+                "RhsContainer type must not be const");
+  static_assert(!std::is_reference<RhsContainer>::value,
+                "RhsContainer type must not be a reference");
+
+  // Like ContainerEq, we make a copy of rhs in case the elements in
+  // it are modified after this matcher is created.
+  PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs)
+      : tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) {}
+
+  template <typename LhsContainer>
+  operator Matcher<LhsContainer>() const {
+    static_assert(
+        !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)>::value,
+        "use UnorderedPointwise with hash tables");
+
+    return Matcher<LhsContainer>(
+        new Impl<const LhsContainer&>(tuple_matcher_, rhs_));
+  }
+
+  template <typename LhsContainer>
+  class Impl : public MatcherInterface<LhsContainer> {
+   public:
+    typedef internal::StlContainerView<GTEST_REMOVE_REFERENCE_AND_CONST_(
+        LhsContainer)>
+        LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    typedef typename LhsView::const_reference LhsStlContainerReference;
+    typedef typename LhsStlContainer::value_type LhsValue;
+    // We pass the LHS value and the RHS value to the inner matcher by
+    // reference, as they may be expensive to copy.  We must use tuple
+    // instead of pair here, as a pair cannot hold references (C++ 98,
+    // 20.2.2 [lib.pairs]).
+    typedef ::std::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg;
+
+    Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs)
+        // mono_tuple_matcher_ holds a monomorphic version of the tuple matcher.
+        : mono_tuple_matcher_(SafeMatcherCast<InnerMatcherArg>(tuple_matcher)),
+          rhs_(rhs) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "contains " << rhs_.size()
+          << " values, where each value and its corresponding value in ";
+      UniversalPrinter<RhsStlContainer>::Print(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeTo(os);
+    }
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "doesn't contain exactly " << rhs_.size()
+          << " values, or contains a value x at some index i"
+          << " where x and the i-th value of ";
+      UniversalPrint(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(LhsContainer lhs,
+                         MatchResultListener* listener) const override {
+      LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+      const size_t actual_size = lhs_stl_container.size();
+      if (actual_size != rhs_.size()) {
+        *listener << "which contains " << actual_size << " values";
+        return false;
+      }
+
+      auto left = lhs_stl_container.begin();
+      auto right = rhs_.begin();
+      for (size_t i = 0; i != actual_size; ++i, ++left, ++right) {
+        if (listener->IsInterested()) {
+          StringMatchResultListener inner_listener;
+          // Create InnerMatcherArg as a temporarily object to avoid it outlives
+          // *left and *right. Dereference or the conversion to `const T&` may
+          // return temp objects, e.g. for vector<bool>.
+          if (!mono_tuple_matcher_.MatchAndExplain(
+                  InnerMatcherArg(ImplicitCast_<const LhsValue&>(*left),
+                                  ImplicitCast_<const RhsValue&>(*right)),
+                  &inner_listener)) {
+            *listener << "where the value pair (";
+            UniversalPrint(*left, listener->stream());
+            *listener << ", ";
+            UniversalPrint(*right, listener->stream());
+            *listener << ") at index #" << i << " don't match";
+            PrintIfNotEmpty(inner_listener.str(), listener->stream());
+            return false;
+          }
+        } else {
+          if (!mono_tuple_matcher_.Matches(
+                  InnerMatcherArg(ImplicitCast_<const LhsValue&>(*left),
+                                  ImplicitCast_<const RhsValue&>(*right))))
+            return false;
+        }
+      }
+
+      return true;
+    }
+
+   private:
+    const Matcher<InnerMatcherArg> mono_tuple_matcher_;
+    const RhsStlContainer rhs_;
+  };
+
+ private:
+  const TupleMatcher tuple_matcher_;
+  const RhsStlContainer rhs_;
+};
+
+// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
+template <typename Container>
+class QuantifierMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  template <typename InnerMatcher>
+  explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+            testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+
+  // Checks whether:
+  // * All elements in the container match, if all_elements_should_match.
+  // * Any element in the container matches, if !all_elements_should_match.
+  bool MatchAndExplainImpl(bool all_elements_should_match, Container container,
+                           MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    size_t i = 0;
+    for (auto it = stl_container.begin(); it != stl_container.end();
+         ++it, ++i) {
+      StringMatchResultListener inner_listener;
+      const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
+
+      if (matches != all_elements_should_match) {
+        *listener << "whose element #" << i
+                  << (matches ? " matches" : " doesn't match");
+        PrintIfNotEmpty(inner_listener.str(), listener->stream());
+        return !all_elements_should_match;
+      }
+    }
+    return all_elements_should_match;
+  }
+
+  bool MatchAndExplainImpl(const Matcher<size_t>& count_matcher,
+                           Container container,
+                           MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    size_t i = 0;
+    std::vector<size_t> match_elements;
+    for (auto it = stl_container.begin(); it != stl_container.end();
+         ++it, ++i) {
+      StringMatchResultListener inner_listener;
+      const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
+      if (matches) {
+        match_elements.push_back(i);
+      }
+    }
+    if (listener->IsInterested()) {
+      if (match_elements.empty()) {
+        *listener << "has no element that matches";
+      } else if (match_elements.size() == 1) {
+        *listener << "whose element #" << match_elements[0] << " matches";
+      } else {
+        *listener << "whose elements (";
+        std::string sep = "";
+        for (size_t e : match_elements) {
+          *listener << sep << e;
+          sep = ", ";
+        }
+        *listener << ") match";
+      }
+    }
+    StringMatchResultListener count_listener;
+    if (count_matcher.MatchAndExplain(match_elements.size(), &count_listener)) {
+      *listener << " and whose match quantity of " << match_elements.size()
+                << " matches";
+      PrintIfNotEmpty(count_listener.str(), listener->stream());
+      return true;
+    } else {
+      if (match_elements.empty()) {
+        *listener << " and";
+      } else {
+        *listener << " but";
+      }
+      *listener << " whose match quantity of " << match_elements.size()
+                << " does not match";
+      PrintIfNotEmpty(count_listener.str(), listener->stream());
+      return false;
+    }
+  }
+
+ protected:
+  const Matcher<const Element&> inner_matcher_;
+};
+
+// Implements Contains(element_matcher) for the given argument type Container.
+// Symmetric to EachMatcherImpl.
+template <typename Container>
+class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "contains at least one element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "doesn't contain any element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  bool MatchAndExplain(Container container,
+                       MatchResultListener* listener) const override {
+    return this->MatchAndExplainImpl(false, container, listener);
+  }
+};
+
+// Implements Each(element_matcher) for the given argument type Container.
+// Symmetric to ContainsMatcherImpl.
+template <typename Container>
+class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit EachMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "only contains elements that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "contains some element that ";
+    this->inner_matcher_.DescribeNegationTo(os);
+  }
+
+  bool MatchAndExplain(Container container,
+                       MatchResultListener* listener) const override {
+    return this->MatchAndExplainImpl(true, container, listener);
+  }
+};
+
+// Implements Contains(element_matcher).Times(n) for the given argument type
+// Container.
+template <typename Container>
+class ContainsTimesMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit ContainsTimesMatcherImpl(InnerMatcher inner_matcher,
+                                    Matcher<size_t> count_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher),
+        count_matcher_(std::move(count_matcher)) {}
+
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "quantity of elements that match ";
+    this->inner_matcher_.DescribeTo(os);
+    *os << " ";
+    count_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "quantity of elements that match ";
+    this->inner_matcher_.DescribeTo(os);
+    *os << " ";
+    count_matcher_.DescribeNegationTo(os);
+  }
+
+  bool MatchAndExplain(Container container,
+                       MatchResultListener* listener) const override {
+    return this->MatchAndExplainImpl(count_matcher_, container, listener);
+  }
+
+ private:
+  const Matcher<size_t> count_matcher_;
+};
+
+// Implements polymorphic Contains(element_matcher).Times(n).
+template <typename M>
+class ContainsTimesMatcher {
+ public:
+  explicit ContainsTimesMatcher(M m, Matcher<size_t> count_matcher)
+      : inner_matcher_(m), count_matcher_(std::move(count_matcher)) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {  // NOLINT
+    return Matcher<Container>(new ContainsTimesMatcherImpl<const Container&>(
+        inner_matcher_, count_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+  const Matcher<size_t> count_matcher_;
+};
+
+// Implements polymorphic Contains(element_matcher).
+template <typename M>
+class ContainsMatcher {
+ public:
+  explicit ContainsMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {  // NOLINT
+    return Matcher<Container>(
+        new ContainsMatcherImpl<const Container&>(inner_matcher_));
+  }
+
+  ContainsTimesMatcher<M> Times(Matcher<size_t> count_matcher) const {
+    return ContainsTimesMatcher<M>(inner_matcher_, std::move(count_matcher));
+  }
+
+ private:
+  const M inner_matcher_;
+};
+
+// Implements polymorphic Each(element_matcher).
+template <typename M>
+class EachMatcher {
+ public:
+  explicit EachMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {  // NOLINT
+    return Matcher<Container>(
+        new EachMatcherImpl<const Container&>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+};
+
+// Use go/ranked-overloads for dispatching.
+struct Rank0 {};
+struct Rank1 : Rank0 {};
+
+namespace pair_getters {
+using std::get;
+template <typename T>
+auto First(T& x, Rank0) -> decltype(get<0>(x)) {  // NOLINT
+  return get<0>(x);
+}
+template <typename T>
+auto First(T& x, Rank1) -> decltype((x.first)) {  // NOLINT
+  return x.first;
+}
+
+template <typename T>
+auto Second(T& x, Rank0) -> decltype(get<1>(x)) {  // NOLINT
+  return get<1>(x);
+}
+template <typename T>
+auto Second(T& x, Rank1) -> decltype((x.second)) {  // NOLINT
+  return x.second;
+}
+}  // namespace pair_getters
+
+// Implements Key(inner_matcher) for the given argument pair type.
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename PairType>
+class KeyMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type KeyType;
+
+  template <typename InnerMatcher>
+  explicit KeyMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+            testing::SafeMatcherCast<const KeyType&>(inner_matcher)) {}
+
+  // Returns true if and only if 'key_value.first' (the key) matches the inner
+  // matcher.
+  bool MatchAndExplain(PairType key_value,
+                       MatchResultListener* listener) const override {
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(
+        pair_getters::First(key_value, Rank1()), &inner_listener);
+    const std::string explanation = inner_listener.str();
+    if (!explanation.empty()) {
+      *listener << "whose first field is a value " << explanation;
+    }
+    return match;
+  }
+
+  // Describes what this matcher does.
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "has a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "doesn't have a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<const KeyType&> inner_matcher_;
+};
+
+// Implements polymorphic Key(matcher_for_key).
+template <typename M>
+class KeyMatcher {
+ public:
+  explicit KeyMatcher(M m) : matcher_for_key_(m) {}
+
+  template <typename PairType>
+  operator Matcher<PairType>() const {
+    return Matcher<PairType>(
+        new KeyMatcherImpl<const PairType&>(matcher_for_key_));
+  }
+
+ private:
+  const M matcher_for_key_;
+};
+
+// Implements polymorphic Address(matcher_for_address).
+template <typename InnerMatcher>
+class AddressMatcher {
+ public:
+  explicit AddressMatcher(InnerMatcher m) : matcher_(m) {}
+
+  template <typename Type>
+  operator Matcher<Type>() const {  // NOLINT
+    return Matcher<Type>(new Impl<const Type&>(matcher_));
+  }
+
+ private:
+  // The monomorphic implementation that works for a particular object type.
+  template <typename Type>
+  class Impl : public MatcherInterface<Type> {
+   public:
+    using Address = const GTEST_REMOVE_REFERENCE_AND_CONST_(Type) *;
+    explicit Impl(const InnerMatcher& matcher)
+        : matcher_(MatcherCast<Address>(matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "has address that ";
+      matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "does not have address that ";
+      matcher_.DescribeTo(os);
+    }
+
+    bool MatchAndExplain(Type object,
+                         MatchResultListener* listener) const override {
+      *listener << "which has address ";
+      Address address = std::addressof(object);
+      return MatchPrintAndExplain(address, matcher_, listener);
+    }
+
+   private:
+    const Matcher<Address> matcher_;
+  };
+  const InnerMatcher matcher_;
+};
+
+// Implements Pair(first_matcher, second_matcher) for the given argument pair
+// type with its two matchers. See Pair() function below.
+template <typename PairType>
+class PairMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type FirstType;
+  typedef typename RawPairType::second_type SecondType;
+
+  template <typename FirstMatcher, typename SecondMatcher>
+  PairMatcherImpl(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(
+            testing::SafeMatcherCast<const FirstType&>(first_matcher)),
+        second_matcher_(
+            testing::SafeMatcherCast<const SecondType&>(second_matcher)) {}
+
+  // Describes what this matcher does.
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "has a first field that ";
+    first_matcher_.DescribeTo(os);
+    *os << ", and has a second field that ";
+    second_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "has a first field that ";
+    first_matcher_.DescribeNegationTo(os);
+    *os << ", or has a second field that ";
+    second_matcher_.DescribeNegationTo(os);
+  }
+
+  // Returns true if and only if 'a_pair.first' matches first_matcher and
+  // 'a_pair.second' matches second_matcher.
+  bool MatchAndExplain(PairType a_pair,
+                       MatchResultListener* listener) const override {
+    if (!listener->IsInterested()) {
+      // If the listener is not interested, we don't need to construct the
+      // explanation.
+      return first_matcher_.Matches(pair_getters::First(a_pair, Rank1())) &&
+             second_matcher_.Matches(pair_getters::Second(a_pair, Rank1()));
+    }
+    StringMatchResultListener first_inner_listener;
+    if (!first_matcher_.MatchAndExplain(pair_getters::First(a_pair, Rank1()),
+                                        &first_inner_listener)) {
+      *listener << "whose first field does not match";
+      PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
+      return false;
+    }
+    StringMatchResultListener second_inner_listener;
+    if (!second_matcher_.MatchAndExplain(pair_getters::Second(a_pair, Rank1()),
+                                         &second_inner_listener)) {
+      *listener << "whose second field does not match";
+      PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
+      return false;
+    }
+    ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(),
+                   listener);
+    return true;
+  }
+
+ private:
+  void ExplainSuccess(const std::string& first_explanation,
+                      const std::string& second_explanation,
+                      MatchResultListener* listener) const {
+    *listener << "whose both fields match";
+    if (!first_explanation.empty()) {
+      *listener << ", where the first field is a value " << first_explanation;
+    }
+    if (!second_explanation.empty()) {
+      *listener << ", ";
+      if (!first_explanation.empty()) {
+        *listener << "and ";
+      } else {
+        *listener << "where ";
+      }
+      *listener << "the second field is a value " << second_explanation;
+    }
+  }
+
+  const Matcher<const FirstType&> first_matcher_;
+  const Matcher<const SecondType&> second_matcher_;
+};
+
+// Implements polymorphic Pair(first_matcher, second_matcher).
+template <typename FirstMatcher, typename SecondMatcher>
+class PairMatcher {
+ public:
+  PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(first_matcher), second_matcher_(second_matcher) {}
+
+  template <typename PairType>
+  operator Matcher<PairType>() const {
+    return Matcher<PairType>(
+        new PairMatcherImpl<const PairType&>(first_matcher_, second_matcher_));
+  }
+
+ private:
+  const FirstMatcher first_matcher_;
+  const SecondMatcher second_matcher_;
+};
+
+template <typename T, size_t... I>
+auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
+                      int) -> decltype(std::tie(get<I>(t)...)) {
+  static_assert(std::tuple_size<T>::value == sizeof...(I),
+                "Number of arguments doesn't match the number of fields.");
+  return std::tie(get<I>(t)...);
+}
+
+#if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<1>, char) {
+  const auto& [a] = t;
+  return std::tie(a);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<2>, char) {
+  const auto& [a, b] = t;
+  return std::tie(a, b);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<3>, char) {
+  const auto& [a, b, c] = t;
+  return std::tie(a, b, c);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<4>, char) {
+  const auto& [a, b, c, d] = t;
+  return std::tie(a, b, c, d);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<5>, char) {
+  const auto& [a, b, c, d, e] = t;
+  return std::tie(a, b, c, d, e);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<6>, char) {
+  const auto& [a, b, c, d, e, f] = t;
+  return std::tie(a, b, c, d, e, f);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<7>, char) {
+  const auto& [a, b, c, d, e, f, g] = t;
+  return std::tie(a, b, c, d, e, f, g);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<8>, char) {
+  const auto& [a, b, c, d, e, f, g, h] = t;
+  return std::tie(a, b, c, d, e, f, g, h);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<9>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<10>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<11>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<12>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<13>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<14>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<15>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<16>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<17>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<18>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
+}
+template <typename T>
+auto UnpackStructImpl(const T& t, std::make_index_sequence<19>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
+}
+#endif  // defined(__cpp_structured_bindings)
+
+template <size_t I, typename T>
+auto UnpackStruct(const T& t)
+    -> decltype((UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0)) {
+  return (UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0);
+}
+
+// Helper function to do comma folding in C++11.
+// The array ensures left-to-right order of evaluation.
+// Usage: VariadicExpand({expr...});
+template <typename T, size_t N>
+void VariadicExpand(const T (&)[N]) {}
+
+template <typename Struct, typename StructSize>
+class FieldsAreMatcherImpl;
+
+template <typename Struct, size_t... I>
+class FieldsAreMatcherImpl<Struct, std::index_sequence<I...>>
+    : public MatcherInterface<Struct> {
+  using UnpackedType =
+      decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>()));
+  using MatchersType = std::tuple<
+      Matcher<const typename std::tuple_element<I, UnpackedType>::type&>...>;
+
+ public:
+  template <typename Inner>
+  explicit FieldsAreMatcherImpl(const Inner& matchers)
+      : matchers_(testing::SafeMatcherCast<
+                  const typename std::tuple_element<I, UnpackedType>::type&>(
+            std::get<I>(matchers))...) {}
+
+  void DescribeTo(::std::ostream* os) const override {
+    const char* separator = "";
+    VariadicExpand(
+        {(*os << separator << "has field #" << I << " that ",
+          std::get<I>(matchers_).DescribeTo(os), separator = ", and ")...});
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    const char* separator = "";
+    VariadicExpand({(*os << separator << "has field #" << I << " that ",
+                     std::get<I>(matchers_).DescribeNegationTo(os),
+                     separator = ", or ")...});
+  }
+
+  bool MatchAndExplain(Struct t, MatchResultListener* listener) const override {
+    return MatchInternal((UnpackStruct<sizeof...(I)>)(t), listener);
+  }
+
+ private:
+  bool MatchInternal(UnpackedType tuple, MatchResultListener* listener) const {
+    if (!listener->IsInterested()) {
+      // If the listener is not interested, we don't need to construct the
+      // explanation.
+      bool good = true;
+      VariadicExpand({good = good && std::get<I>(matchers_).Matches(
+                                         std::get<I>(tuple))...});
+      return good;
+    }
+
+    size_t failed_pos = ~size_t{};
+
+    std::vector<StringMatchResultListener> inner_listener(sizeof...(I));
+
+    VariadicExpand(
+        {failed_pos == ~size_t{} && !std::get<I>(matchers_).MatchAndExplain(
+                                        std::get<I>(tuple), &inner_listener[I])
+             ? failed_pos = I
+             : 0 ...});
+    if (failed_pos != ~size_t{}) {
+      *listener << "whose field #" << failed_pos << " does not match";
+      PrintIfNotEmpty(inner_listener[failed_pos].str(), listener->stream());
+      return false;
+    }
+
+    *listener << "whose all elements match";
+    const char* separator = ", where";
+    for (size_t index = 0; index < sizeof...(I); ++index) {
+      const std::string str = inner_listener[index].str();
+      if (!str.empty()) {
+        *listener << separator << " field #" << index << " is a value " << str;
+        separator = ", and";
+      }
+    }
+
+    return true;
+  }
+
+  MatchersType matchers_;
+};
+
+template <typename... Inner>
+class FieldsAreMatcher {
+ public:
+  explicit FieldsAreMatcher(Inner... inner) : matchers_(std::move(inner)...) {}
+
+  template <typename Struct>
+  operator Matcher<Struct>() const {  // NOLINT
+    return Matcher<Struct>(
+        new FieldsAreMatcherImpl<const Struct&,
+                                 std::index_sequence_for<Inner...>>(matchers_));
+  }
+
+ private:
+  std::tuple<Inner...> matchers_;
+};
+
+// Implements ElementsAre() and ElementsAreArray().
+template <typename Container>
+class ElementsAreMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  // Constructs the matcher from a sequence of element values or
+  // element matchers.
+  template <typename InputIter>
+  ElementsAreMatcherImpl(InputIter first, InputIter last) {
+    while (first != last) {
+      matchers_.push_back(MatcherCast<const Element&>(*first++));
+    }
+  }
+
+  // Describes what this matcher does.
+  void DescribeTo(::std::ostream* os) const override {
+    if (count() == 0) {
+      *os << "is empty";
+    } else if (count() == 1) {
+      *os << "has 1 element that ";
+      matchers_[0].DescribeTo(os);
+    } else {
+      *os << "has " << Elements(count()) << " where\n";
+      for (size_t i = 0; i != count(); ++i) {
+        *os << "element #" << i << " ";
+        matchers_[i].DescribeTo(os);
+        if (i + 1 < count()) {
+          *os << ",\n";
+        }
+      }
+    }
+  }
+
+  // Describes what the negation of this matcher does.
+  void DescribeNegationTo(::std::ostream* os) const override {
+    if (count() == 0) {
+      *os << "isn't empty";
+      return;
+    }
+
+    *os << "doesn't have " << Elements(count()) << ", or\n";
+    for (size_t i = 0; i != count(); ++i) {
+      *os << "element #" << i << " ";
+      matchers_[i].DescribeNegationTo(os);
+      if (i + 1 < count()) {
+        *os << ", or\n";
+      }
+    }
+  }
+
+  bool MatchAndExplain(Container container,
+                       MatchResultListener* listener) const override {
+    // To work with stream-like "containers", we must only walk
+    // through the elements in one pass.
+
+    const bool listener_interested = listener->IsInterested();
+
+    // explanations[i] is the explanation of the element at index i.
+    ::std::vector<std::string> explanations(count());
+    StlContainerReference stl_container = View::ConstReference(container);
+    auto it = stl_container.begin();
+    size_t exam_pos = 0;
+    bool mismatch_found = false;  // Have we found a mismatched element yet?
+
+    // Go through the elements and matchers in pairs, until we reach
+    // the end of either the elements or the matchers, or until we find a
+    // mismatch.
+    for (; it != stl_container.end() && exam_pos != count(); ++it, ++exam_pos) {
+      bool match;  // Does the current element match the current matcher?
+      if (listener_interested) {
+        StringMatchResultListener s;
+        match = matchers_[exam_pos].MatchAndExplain(*it, &s);
+        explanations[exam_pos] = s.str();
+      } else {
+        match = matchers_[exam_pos].Matches(*it);
+      }
+
+      if (!match) {
+        mismatch_found = true;
+        break;
+      }
+    }
+    // If mismatch_found is true, 'exam_pos' is the index of the mismatch.
+
+    // Find how many elements the actual container has.  We avoid
+    // calling size() s.t. this code works for stream-like "containers"
+    // that don't define size().
+    size_t actual_count = exam_pos;
+    for (; it != stl_container.end(); ++it) {
+      ++actual_count;
+    }
+
+    if (actual_count != count()) {
+      // The element count doesn't match.  If the container is empty,
+      // there's no need to explain anything as Google Mock already
+      // prints the empty container.  Otherwise we just need to show
+      // how many elements there actually are.
+      if (listener_interested && (actual_count != 0)) {
+        *listener << "which has " << Elements(actual_count);
+      }
+      return false;
+    }
+
+    if (mismatch_found) {
+      // The element count matches, but the exam_pos-th element doesn't match.
+      if (listener_interested) {
+        *listener << "whose element #" << exam_pos << " doesn't match";
+        PrintIfNotEmpty(explanations[exam_pos], listener->stream());
+      }
+      return false;
+    }
+
+    // Every element matches its expectation.  We need to explain why
+    // (the obvious ones can be skipped).
+    if (listener_interested) {
+      bool reason_printed = false;
+      for (size_t i = 0; i != count(); ++i) {
+        const std::string& s = explanations[i];
+        if (!s.empty()) {
+          if (reason_printed) {
+            *listener << ",\nand ";
+          }
+          *listener << "whose element #" << i << " matches, " << s;
+          reason_printed = true;
+        }
+      }
+    }
+    return true;
+  }
+
+ private:
+  static Message Elements(size_t count) {
+    return Message() << count << (count == 1 ? " element" : " elements");
+  }
+
+  size_t count() const { return matchers_.size(); }
+
+  ::std::vector<Matcher<const Element&>> matchers_;
+};
+
+// Connectivity matrix of (elements X matchers), in element-major order.
+// Initially, there are no edges.
+// Use NextGraph() to iterate over all possible edge configurations.
+// Use Randomize() to generate a random edge configuration.
+class GTEST_API_ MatchMatrix {
+ public:
+  MatchMatrix(size_t num_elements, size_t num_matchers)
+      : num_elements_(num_elements),
+        num_matchers_(num_matchers),
+        matched_(num_elements_ * num_matchers_, 0) {}
+
+  size_t LhsSize() const { return num_elements_; }
+  size_t RhsSize() const { return num_matchers_; }
+  bool HasEdge(size_t ilhs, size_t irhs) const {
+    return matched_[SpaceIndex(ilhs, irhs)] == 1;
+  }
+  void SetEdge(size_t ilhs, size_t irhs, bool b) {
+    matched_[SpaceIndex(ilhs, irhs)] = b ? 1 : 0;
+  }
+
+  // Treating the connectivity matrix as a (LhsSize()*RhsSize())-bit number,
+  // adds 1 to that number; returns false if incrementing the graph left it
+  // empty.
+  bool NextGraph();
+
+  void Randomize();
+
+  std::string DebugString() const;
+
+ private:
+  size_t SpaceIndex(size_t ilhs, size_t irhs) const {
+    return ilhs * num_matchers_ + irhs;
+  }
+
+  size_t num_elements_;
+  size_t num_matchers_;
+
+  // Each element is a char interpreted as bool. They are stored as a
+  // flattened array in lhs-major order, use 'SpaceIndex()' to translate
+  // a (ilhs, irhs) matrix coordinate into an offset.
+  ::std::vector<char> matched_;
+};
+
+typedef ::std::pair<size_t, size_t> ElementMatcherPair;
+typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
+
+// Returns a maximum bipartite matching for the specified graph 'g'.
+// The matching is represented as a vector of {element, matcher} pairs.
+GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g);
+
+struct UnorderedMatcherRequire {
+  enum Flags {
+    Superset = 1 << 0,
+    Subset = 1 << 1,
+    ExactMatch = Superset | Subset,
+  };
+};
+
+// Untyped base class for implementing UnorderedElementsAre.  By
+// putting logic that's not specific to the element type here, we
+// reduce binary bloat and increase compilation speed.
+class GTEST_API_ UnorderedElementsAreMatcherImplBase {
+ protected:
+  explicit UnorderedElementsAreMatcherImplBase(
+      UnorderedMatcherRequire::Flags matcher_flags)
+      : match_flags_(matcher_flags) {}
+
+  // A vector of matcher describers, one for each element matcher.
+  // Does not own the describers (and thus can be used only when the
+  // element matchers are alive).
+  typedef ::std::vector<const MatcherDescriberInterface*> MatcherDescriberVec;
+
+  // Describes this UnorderedElementsAre matcher.
+  void DescribeToImpl(::std::ostream* os) const;
+
+  // Describes the negation of this UnorderedElementsAre matcher.
+  void DescribeNegationToImpl(::std::ostream* os) const;
+
+  bool VerifyMatchMatrix(const ::std::vector<std::string>& element_printouts,
+                         const MatchMatrix& matrix,
+                         MatchResultListener* listener) const;
+
+  bool FindPairing(const MatchMatrix& matrix,
+                   MatchResultListener* listener) const;
+
+  MatcherDescriberVec& matcher_describers() { return matcher_describers_; }
+
+  static Message Elements(size_t n) {
+    return Message() << n << " element" << (n == 1 ? "" : "s");
+  }
+
+  UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; }
+
+ private:
+  UnorderedMatcherRequire::Flags match_flags_;
+  MatcherDescriberVec matcher_describers_;
+};
+
+// Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and
+// IsSupersetOf.
+template <typename Container>
+class UnorderedElementsAreMatcherImpl
+    : public MatcherInterface<Container>,
+      public UnorderedElementsAreMatcherImplBase {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  template <typename InputIter>
+  UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags,
+                                  InputIter first, InputIter last)
+      : UnorderedElementsAreMatcherImplBase(matcher_flags) {
+    for (; first != last; ++first) {
+      matchers_.push_back(MatcherCast<const Element&>(*first));
+    }
+    for (const auto& m : matchers_) {
+      matcher_describers().push_back(m.GetDescriber());
+    }
+  }
+
+  // Describes what this matcher does.
+  void DescribeTo(::std::ostream* os) const override {
+    return UnorderedElementsAreMatcherImplBase::DescribeToImpl(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  void DescribeNegationTo(::std::ostream* os) const override {
+    return UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(os);
+  }
+
+  bool MatchAndExplain(Container container,
+                       MatchResultListener* listener) const override {
+    StlContainerReference stl_container = View::ConstReference(container);
+    ::std::vector<std::string> element_printouts;
+    MatchMatrix matrix =
+        AnalyzeElements(stl_container.begin(), stl_container.end(),
+                        &element_printouts, listener);
+
+    return VerifyMatchMatrix(element_printouts, matrix, listener) &&
+           FindPairing(matrix, listener);
+  }
+
+ private:
+  template <typename ElementIter>
+  MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last,
+                              ::std::vector<std::string>* element_printouts,
+                              MatchResultListener* listener) const {
+    element_printouts->clear();
+    ::std::vector<char> did_match;
+    size_t num_elements = 0;
+    DummyMatchResultListener dummy;
+    for (; elem_first != elem_last; ++num_elements, ++elem_first) {
+      if (listener->IsInterested()) {
+        element_printouts->push_back(PrintToString(*elem_first));
+      }
+      for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) {
+        did_match.push_back(
+            matchers_[irhs].MatchAndExplain(*elem_first, &dummy));
+      }
+    }
+
+    MatchMatrix matrix(num_elements, matchers_.size());
+    ::std::vector<char>::const_iterator did_match_iter = did_match.begin();
+    for (size_t ilhs = 0; ilhs != num_elements; ++ilhs) {
+      for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) {
+        matrix.SetEdge(ilhs, irhs, *did_match_iter++ != 0);
+      }
+    }
+    return matrix;
+  }
+
+  ::std::vector<Matcher<const Element&>> matchers_;
+};
+
+// Functor for use in TransformTuple.
+// Performs MatcherCast<Target> on an input argument of any type.
+template <typename Target>
+struct CastAndAppendTransform {
+  template <typename Arg>
+  Matcher<Target> operator()(const Arg& a) const {
+    return MatcherCast<Target>(a);
+  }
+};
+
+// Implements UnorderedElementsAre.
+template <typename MatcherTuple>
+class UnorderedElementsAreMatcher {
+ public:
+  explicit UnorderedElementsAreMatcher(const MatcherTuple& args)
+      : matchers_(args) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type View;
+    typedef typename View::value_type Element;
+    typedef ::std::vector<Matcher<const Element&>> MatcherVec;
+    MatcherVec matchers;
+    matchers.reserve(::std::tuple_size<MatcherTuple>::value);
+    TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
+                         ::std::back_inserter(matchers));
+    return Matcher<Container>(
+        new UnorderedElementsAreMatcherImpl<const Container&>(
+            UnorderedMatcherRequire::ExactMatch, matchers.begin(),
+            matchers.end()));
+  }
+
+ private:
+  const MatcherTuple matchers_;
+};
+
+// Implements ElementsAre.
+template <typename MatcherTuple>
+class ElementsAreMatcher {
+ public:
+  explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    static_assert(
+        !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value ||
+            ::std::tuple_size<MatcherTuple>::value < 2,
+        "use UnorderedElementsAre with hash tables");
+
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type View;
+    typedef typename View::value_type Element;
+    typedef ::std::vector<Matcher<const Element&>> MatcherVec;
+    MatcherVec matchers;
+    matchers.reserve(::std::tuple_size<MatcherTuple>::value);
+    TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
+                         ::std::back_inserter(matchers));
+    return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>(
+        matchers.begin(), matchers.end()));
+  }
+
+ private:
+  const MatcherTuple matchers_;
+};
+
+// Implements UnorderedElementsAreArray(), IsSubsetOf(), and IsSupersetOf().
+template <typename T>
+class UnorderedElementsAreArrayMatcher {
+ public:
+  template <typename Iter>
+  UnorderedElementsAreArrayMatcher(UnorderedMatcherRequire::Flags match_flags,
+                                   Iter first, Iter last)
+      : match_flags_(match_flags), matchers_(first, last) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return Matcher<Container>(
+        new UnorderedElementsAreMatcherImpl<const Container&>(
+            match_flags_, matchers_.begin(), matchers_.end()));
+  }
+
+ private:
+  UnorderedMatcherRequire::Flags match_flags_;
+  ::std::vector<T> matchers_;
+};
+
+// Implements ElementsAreArray().
+template <typename T>
+class ElementsAreArrayMatcher {
+ public:
+  template <typename Iter>
+  ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    static_assert(
+        !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value,
+        "use UnorderedElementsAreArray with hash tables");
+
+    return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>(
+        matchers_.begin(), matchers_.end()));
+  }
+
+ private:
+  const ::std::vector<T> matchers_;
+};
+
+// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
+// of type Second, BoundSecondMatcher<Tuple2Matcher, Second>(tm,
+// second) is a polymorphic matcher that matches a value x if and only if
+// tm matches tuple (x, second).  Useful for implementing
+// UnorderedPointwise() in terms of UnorderedElementsAreArray().
+//
+// BoundSecondMatcher is copyable and assignable, as we need to put
+// instances of this class in a vector when implementing
+// UnorderedPointwise().
+template <typename Tuple2Matcher, typename Second>
+class BoundSecondMatcher {
+ public:
+  BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second)
+      : tuple2_matcher_(tm), second_value_(second) {}
+
+  BoundSecondMatcher(const BoundSecondMatcher& other) = default;
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return MakeMatcher(new Impl<T>(tuple2_matcher_, second_value_));
+  }
+
+  // We have to define this for UnorderedPointwise() to compile in
+  // C++98 mode, as it puts BoundSecondMatcher instances in a vector,
+  // which requires the elements to be assignable in C++98.  The
+  // compiler cannot generate the operator= for us, as Tuple2Matcher
+  // and Second may not be assignable.
+  //
+  // However, this should never be called, so the implementation just
+  // need to assert.
+  void operator=(const BoundSecondMatcher& /*rhs*/) {
+    GTEST_LOG_(FATAL) << "BoundSecondMatcher should never be assigned.";
+  }
+
+ private:
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    typedef ::std::tuple<T, Second> ArgTuple;
+
+    Impl(const Tuple2Matcher& tm, const Second& second)
+        : mono_tuple2_matcher_(SafeMatcherCast<const ArgTuple&>(tm)),
+          second_value_(second) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "and ";
+      UniversalPrint(second_value_, os);
+      *os << " ";
+      mono_tuple2_matcher_.DescribeTo(os);
+    }
+
+    bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+      return mono_tuple2_matcher_.MatchAndExplain(ArgTuple(x, second_value_),
+                                                  listener);
+    }
+
+   private:
+    const Matcher<const ArgTuple&> mono_tuple2_matcher_;
+    const Second second_value_;
+  };
+
+  const Tuple2Matcher tuple2_matcher_;
+  const Second second_value_;
+};
+
+// Given a 2-tuple matcher tm and a value second,
+// MatcherBindSecond(tm, second) returns a matcher that matches a
+// value x if and only if tm matches tuple (x, second).  Useful for
+// implementing UnorderedPointwise() in terms of UnorderedElementsAreArray().
+template <typename Tuple2Matcher, typename Second>
+BoundSecondMatcher<Tuple2Matcher, Second> MatcherBindSecond(
+    const Tuple2Matcher& tm, const Second& second) {
+  return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second);
+}
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+GTEST_API_ std::string FormatMatcherDescription(
+    bool negation, const char* matcher_name,
+    const std::vector<const char*>& param_names, const Strings& param_values);
+
+// Implements a matcher that checks the value of a optional<> type variable.
+template <typename ValueMatcher>
+class OptionalMatcher {
+ public:
+  explicit OptionalMatcher(const ValueMatcher& value_matcher)
+      : value_matcher_(value_matcher) {}
+
+  template <typename Optional>
+  operator Matcher<Optional>() const {
+    return Matcher<Optional>(new Impl<const Optional&>(value_matcher_));
+  }
+
+  template <typename Optional>
+  class Impl : public MatcherInterface<Optional> {
+   public:
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Optional) OptionalView;
+    typedef typename OptionalView::value_type ValueType;
+    explicit Impl(const ValueMatcher& value_matcher)
+        : value_matcher_(MatcherCast<ValueType>(value_matcher)) {}
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "value ";
+      value_matcher_.DescribeTo(os);
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "value ";
+      value_matcher_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(Optional optional,
+                         MatchResultListener* listener) const override {
+      if (!optional) {
+        *listener << "which is not engaged";
+        return false;
+      }
+      const ValueType& value = *optional;
+      StringMatchResultListener value_listener;
+      const bool match = value_matcher_.MatchAndExplain(value, &value_listener);
+      *listener << "whose value " << PrintToString(value)
+                << (match ? " matches" : " doesn't match");
+      PrintIfNotEmpty(value_listener.str(), listener->stream());
+      return match;
+    }
+
+   private:
+    const Matcher<ValueType> value_matcher_;
+  };
+
+ private:
+  const ValueMatcher value_matcher_;
+};
+
+namespace variant_matcher {
+// Overloads to allow VariantMatcher to do proper ADL lookup.
+template <typename T>
+void holds_alternative() {}
+template <typename T>
+void get() {}
+
+// Implements a matcher that checks the value of a variant<> type variable.
+template <typename T>
+class VariantMatcher {
+ public:
+  explicit VariantMatcher(::testing::Matcher<const T&> matcher)
+      : matcher_(std::move(matcher)) {}
+
+  template <typename Variant>
+  bool MatchAndExplain(const Variant& value,
+                       ::testing::MatchResultListener* listener) const {
+    using std::get;
+    if (!listener->IsInterested()) {
+      return holds_alternative<T>(value) && matcher_.Matches(get<T>(value));
+    }
+
+    if (!holds_alternative<T>(value)) {
+      *listener << "whose value is not of type '" << GetTypeName() << "'";
+      return false;
+    }
+
+    const T& elem = get<T>(value);
+    StringMatchResultListener elem_listener;
+    const bool match = matcher_.MatchAndExplain(elem, &elem_listener);
+    *listener << "whose value " << PrintToString(elem)
+              << (match ? " matches" : " doesn't match");
+    PrintIfNotEmpty(elem_listener.str(), listener->stream());
+    return match;
+  }
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "is a variant<> with value of type '" << GetTypeName()
+        << "' and the value ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "is a variant<> with value of type other than '" << GetTypeName()
+        << "' or the value ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  static std::string GetTypeName() {
+#if GTEST_HAS_RTTI
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        return internal::GetTypeName<T>());
+#endif
+    return "the element type";
+  }
+
+  const ::testing::Matcher<const T&> matcher_;
+};
+
+}  // namespace variant_matcher
+
+namespace any_cast_matcher {
+
+// Overloads to allow AnyCastMatcher to do proper ADL lookup.
+template <typename T>
+void any_cast() {}
+
+// Implements a matcher that any_casts the value.
+template <typename T>
+class AnyCastMatcher {
+ public:
+  explicit AnyCastMatcher(const ::testing::Matcher<const T&>& matcher)
+      : matcher_(matcher) {}
+
+  template <typename AnyType>
+  bool MatchAndExplain(const AnyType& value,
+                       ::testing::MatchResultListener* listener) const {
+    if (!listener->IsInterested()) {
+      const T* ptr = any_cast<T>(&value);
+      return ptr != nullptr && matcher_.Matches(*ptr);
+    }
+
+    const T* elem = any_cast<T>(&value);
+    if (elem == nullptr) {
+      *listener << "whose value is not of type '" << GetTypeName() << "'";
+      return false;
+    }
+
+    StringMatchResultListener elem_listener;
+    const bool match = matcher_.MatchAndExplain(*elem, &elem_listener);
+    *listener << "whose value " << PrintToString(*elem)
+              << (match ? " matches" : " doesn't match");
+    PrintIfNotEmpty(elem_listener.str(), listener->stream());
+    return match;
+  }
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "is an 'any' type with value of type '" << GetTypeName()
+        << "' and the value ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "is an 'any' type with value of type other than '" << GetTypeName()
+        << "' or the value ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  static std::string GetTypeName() {
+#if GTEST_HAS_RTTI
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        return internal::GetTypeName<T>());
+#endif
+    return "the element type";
+  }
+
+  const ::testing::Matcher<const T&> matcher_;
+};
+
+}  // namespace any_cast_matcher
+
+// Implements the Args() matcher.
+template <class ArgsTuple, size_t... k>
+class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
+ public:
+  using RawArgsTuple = typename std::decay<ArgsTuple>::type;
+  using SelectedArgs =
+      std::tuple<typename std::tuple_element<k, RawArgsTuple>::type...>;
+  using MonomorphicInnerMatcher = Matcher<const SelectedArgs&>;
+
+  template <typename InnerMatcher>
+  explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
+      : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
+
+  bool MatchAndExplain(ArgsTuple args,
+                       MatchResultListener* listener) const override {
+    // Workaround spurious C4100 on MSVC<=15.7 when k is empty.
+    (void)args;
+    const SelectedArgs& selected_args =
+        std::forward_as_tuple(std::get<k>(args)...);
+    if (!listener->IsInterested()) return inner_matcher_.Matches(selected_args);
+
+    PrintIndices(listener->stream());
+    *listener << "are " << PrintToString(selected_args);
+
+    StringMatchResultListener inner_listener;
+    const bool match =
+        inner_matcher_.MatchAndExplain(selected_args, &inner_listener);
+    PrintIfNotEmpty(inner_listener.str(), listener->stream());
+    return match;
+  }
+
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  // Prints the indices of the selected fields.
+  static void PrintIndices(::std::ostream* os) {
+    *os << "whose fields (";
+    const char* sep = "";
+    // Workaround spurious C4189 on MSVC<=15.7 when k is empty.
+    (void)sep;
+    // The static_cast to void is needed to silence Clang's -Wcomma warning.
+    // This pattern looks suspiciously like we may have mismatched parentheses
+    // and may have been trying to use the first operation of the comma operator
+    // as a member of the array, so Clang warns that we may have made a mistake.
+    const char* dummy[] = {
+        "", (static_cast<void>(*os << sep << "#" << k), sep = ", ")...};
+    (void)dummy;
+    *os << ") ";
+  }
+
+  MonomorphicInnerMatcher inner_matcher_;
+};
+
+template <class InnerMatcher, size_t... k>
+class ArgsMatcher {
+ public:
+  explicit ArgsMatcher(InnerMatcher inner_matcher)
+      : inner_matcher_(std::move(inner_matcher)) {}
+
+  template <typename ArgsTuple>
+  operator Matcher<ArgsTuple>() const {  // NOLINT
+    return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k...>(inner_matcher_));
+  }
+
+ private:
+  InnerMatcher inner_matcher_;
+};
+
+}  // namespace internal
+
+// ElementsAreArray(iterator_first, iterator_last)
+// ElementsAreArray(pointer, count)
+// ElementsAreArray(array)
+// ElementsAreArray(container)
+// ElementsAreArray({ e1, e2, ..., en })
+//
+// The ElementsAreArray() functions are like ElementsAre(...), except
+// that they are given a homogeneous sequence rather than taking each
+// element as a function argument. The sequence can be specified as an
+// array, a pointer and count, a vector, an initializer list, or an
+// STL iterator range. In each of these cases, the underlying sequence
+// can be either a sequence of values or a sequence of matchers.
+//
+// All forms of ElementsAreArray() make a copy of the input matcher sequence.
+
+template <typename Iter>
+inline internal::ElementsAreArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+ElementsAreArray(Iter first, Iter last) {
+  typedef typename ::std::iterator_traits<Iter>::value_type T;
+  return internal::ElementsAreArrayMatcher<T>(first, last);
+}
+
+template <typename T>
+inline auto ElementsAreArray(const T* pointer, size_t count)
+    -> decltype(ElementsAreArray(pointer, pointer + count)) {
+  return ElementsAreArray(pointer, pointer + count);
+}
+
+template <typename T, size_t N>
+inline auto ElementsAreArray(const T (&array)[N])
+    -> decltype(ElementsAreArray(array, N)) {
+  return ElementsAreArray(array, N);
+}
+
+template <typename Container>
+inline auto ElementsAreArray(const Container& container)
+    -> decltype(ElementsAreArray(container.begin(), container.end())) {
+  return ElementsAreArray(container.begin(), container.end());
+}
+
+template <typename T>
+inline auto ElementsAreArray(::std::initializer_list<T> xs)
+    -> decltype(ElementsAreArray(xs.begin(), xs.end())) {
+  return ElementsAreArray(xs.begin(), xs.end());
+}
+
+// UnorderedElementsAreArray(iterator_first, iterator_last)
+// UnorderedElementsAreArray(pointer, count)
+// UnorderedElementsAreArray(array)
+// UnorderedElementsAreArray(container)
+// UnorderedElementsAreArray({ e1, e2, ..., en })
+//
+// UnorderedElementsAreArray() verifies that a bijective mapping onto a
+// collection of matchers exists.
+//
+// The matchers can be specified as an array, a pointer and count, a container,
+// an initializer list, or an STL iterator range. In each of these cases, the
+// underlying matchers can be either values or matchers.
+
+template <typename Iter>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+UnorderedElementsAreArray(Iter first, Iter last) {
+  typedef typename ::std::iterator_traits<Iter>::value_type T;
+  return internal::UnorderedElementsAreArrayMatcher<T>(
+      internal::UnorderedMatcherRequire::ExactMatch, first, last);
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T> UnorderedElementsAreArray(
+    const T* pointer, size_t count) {
+  return UnorderedElementsAreArray(pointer, pointer + count);
+}
+
+template <typename T, size_t N>
+inline internal::UnorderedElementsAreArrayMatcher<T> UnorderedElementsAreArray(
+    const T (&array)[N]) {
+  return UnorderedElementsAreArray(array, N);
+}
+
+template <typename Container>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename Container::value_type>
+UnorderedElementsAreArray(const Container& container) {
+  return UnorderedElementsAreArray(container.begin(), container.end());
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T> UnorderedElementsAreArray(
+    ::std::initializer_list<T> xs) {
+  return UnorderedElementsAreArray(xs.begin(), xs.end());
+}
+
+// _ is a matcher that matches anything of any type.
+//
+// This definition is fine as:
+//
+//   1. The C++ standard permits using the name _ in a namespace that
+//      is not the global namespace or ::std.
+//   2. The AnythingMatcher class has no data member or constructor,
+//      so it's OK to create global variables of this type.
+//   3. c-style has approved of using _ in this case.
+const internal::AnythingMatcher _ = {};
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> A() {
+  return _;
+}
+
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> An() {
+  return _;
+}
+
+template <typename T, typename M>
+Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl(
+    const M& value, std::false_type /* convertible_to_matcher */,
+    std::false_type /* convertible_to_T */) {
+  return Eq(value);
+}
+
+// Creates a polymorphic matcher that matches any NULL pointer.
+inline PolymorphicMatcher<internal::IsNullMatcher> IsNull() {
+  return MakePolymorphicMatcher(internal::IsNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any non-NULL pointer.
+// This is convenient as Not(NULL) doesn't compile (the compiler
+// thinks that that expression is comparing a pointer with an integer).
+inline PolymorphicMatcher<internal::NotNullMatcher> NotNull() {
+  return MakePolymorphicMatcher(internal::NotNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any argument that
+// references variable x.
+template <typename T>
+inline internal::RefMatcher<T&> Ref(T& x) {  // NOLINT
+  return internal::RefMatcher<T&>(x);
+}
+
+// Creates a polymorphic matcher that matches any NaN floating point.
+inline PolymorphicMatcher<internal::IsNanMatcher> IsNan() {
+  return MakePolymorphicMatcher(internal::IsNanMatcher());
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, false);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, true);
+}
+
+// Creates a matcher that matches any double argument approximately equal to
+// rhs, up to the specified max absolute error bound, where two NANs are
+// considered unequal.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
+                                                      double max_abs_error) {
+  return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
+}
+
+// Creates a matcher that matches any double argument approximately equal to
+// rhs, up to the specified max absolute error bound, including NaN values when
+// rhs is NaN.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<double> NanSensitiveDoubleNear(
+    double rhs, double max_abs_error) {
+  return internal::FloatingEqMatcher<double>(rhs, true, max_abs_error);
+}
+
+// Creates a matcher that matches any float argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<float> FloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, false);
+}
+
+// Creates a matcher that matches any float argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, true);
+}
+
+// Creates a matcher that matches any float argument approximately equal to
+// rhs, up to the specified max absolute error bound, where two NANs are
+// considered unequal.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<float> FloatNear(float rhs,
+                                                    float max_abs_error) {
+  return internal::FloatingEqMatcher<float>(rhs, false, max_abs_error);
+}
+
+// Creates a matcher that matches any float argument approximately equal to
+// rhs, up to the specified max absolute error bound, including NaN values when
+// rhs is NaN.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<float> NanSensitiveFloatNear(
+    float rhs, float max_abs_error) {
+  return internal::FloatingEqMatcher<float>(rhs, true, max_abs_error);
+}
+
+// Creates a matcher that matches a pointer (raw or smart) that points
+// to a value that matches inner_matcher.
+template <typename InnerMatcher>
+inline internal::PointeeMatcher<InnerMatcher> Pointee(
+    const InnerMatcher& inner_matcher) {
+  return internal::PointeeMatcher<InnerMatcher>(inner_matcher);
+}
+
+#if GTEST_HAS_RTTI
+// Creates a matcher that matches a pointer or reference that matches
+// inner_matcher when dynamic_cast<To> is applied.
+// The result of dynamic_cast<To> is forwarded to the inner matcher.
+// If To is a pointer and the cast fails, the inner matcher will receive NULL.
+// If To is a reference and the cast fails, this matcher returns false
+// immediately.
+template <typename To>
+inline PolymorphicMatcher<internal::WhenDynamicCastToMatcher<To>>
+WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
+  return MakePolymorphicMatcher(
+      internal::WhenDynamicCastToMatcher<To>(inner_matcher));
+}
+#endif  // GTEST_HAS_RTTI
+
+// Creates a matcher that matches an object whose given field matches
+// 'matcher'.  For example,
+//   Field(&Foo::number, Ge(5))
+// matches a Foo object x if and only if x.number >= 5.
+template <typename Class, typename FieldType, typename FieldMatcher>
+inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
+    FieldType Class::*field, const FieldMatcher& matcher) {
+  return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
+      field, MatcherCast<const FieldType&>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Field(&Foo::bar, m)
+  // to compile where bar is an int32 and m is a matcher for int64.
+}
+
+// Same as Field() but also takes the name of the field to provide better error
+// messages.
+template <typename Class, typename FieldType, typename FieldMatcher>
+inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
+    const std::string& field_name, FieldType Class::*field,
+    const FieldMatcher& matcher) {
+  return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
+      field_name, field, MatcherCast<const FieldType&>(matcher)));
+}
+
+// Creates a matcher that matches an object whose given property
+// matches 'matcher'.  For example,
+//   Property(&Foo::str, StartsWith("hi"))
+// matches a Foo object x if and only if x.str() starts with "hi".
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<internal::PropertyMatcher<
+    Class, PropertyType, PropertyType (Class::*)() const>>
+Property(PropertyType (Class::*property)() const,
+         const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType,
+                                PropertyType (Class::*)() const>(
+          property, MatcherCast<const PropertyType&>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Property(&Foo::bar, m)
+  // to compile where bar() returns an int32 and m is a matcher for int64.
+}
+
+// Same as Property() above, but also takes the name of the property to provide
+// better error messages.
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<internal::PropertyMatcher<
+    Class, PropertyType, PropertyType (Class::*)() const>>
+Property(const std::string& property_name,
+         PropertyType (Class::*property)() const,
+         const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType,
+                                PropertyType (Class::*)() const>(
+          property_name, property, MatcherCast<const PropertyType&>(matcher)));
+}
+
+// The same as above but for reference-qualified member functions.
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<internal::PropertyMatcher<
+    Class, PropertyType, PropertyType (Class::*)() const&>>
+Property(PropertyType (Class::*property)() const&,
+         const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType,
+                                PropertyType (Class::*)() const&>(
+          property, MatcherCast<const PropertyType&>(matcher)));
+}
+
+// Three-argument form for reference-qualified member functions.
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<internal::PropertyMatcher<
+    Class, PropertyType, PropertyType (Class::*)() const&>>
+Property(const std::string& property_name,
+         PropertyType (Class::*property)() const&,
+         const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType,
+                                PropertyType (Class::*)() const&>(
+          property_name, property, MatcherCast<const PropertyType&>(matcher)));
+}
+
+// Creates a matcher that matches an object if and only if the result of
+// applying a callable to x matches 'matcher'. For example,
+//   ResultOf(f, StartsWith("hi"))
+// matches a Foo object x if and only if f(x) starts with "hi".
+// `callable` parameter can be a function, function pointer, or a functor. It is
+// required to keep no state affecting the results of the calls on it and make
+// no assumptions about how many calls will be made. Any state it keeps must be
+// protected from the concurrent access.
+template <typename Callable, typename InnerMatcher>
+internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
+    Callable callable, InnerMatcher matcher) {
+  return internal::ResultOfMatcher<Callable, InnerMatcher>(std::move(callable),
+                                                           std::move(matcher));
+}
+
+// Same as ResultOf() above, but also takes a description of the `callable`
+// result to provide better error messages.
+template <typename Callable, typename InnerMatcher>
+internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
+    const std::string& result_description, Callable callable,
+    InnerMatcher matcher) {
+  return internal::ResultOfMatcher<Callable, InnerMatcher>(
+      result_description, std::move(callable), std::move(matcher));
+}
+
+// String matchers.
+
+// Matches a string equal to str.
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrEq(
+    const internal::StringLike<T>& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::string>(std::string(str), true, true));
+}
+
+// Matches a string not equal to str.
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrNe(
+    const internal::StringLike<T>& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::string>(std::string(str), false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrCaseEq(
+    const internal::StringLike<T>& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::string>(std::string(str), true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrCaseNe(
+    const internal::StringLike<T>& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>(
+      std::string(str), false, false));
+}
+
+// Creates a matcher that matches any string, std::string, or C string
+// that contains the given substring.
+template <typename T = std::string>
+PolymorphicMatcher<internal::HasSubstrMatcher<std::string>> HasSubstr(
+    const internal::StringLike<T>& substring) {
+  return MakePolymorphicMatcher(
+      internal::HasSubstrMatcher<std::string>(std::string(substring)));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+template <typename T = std::string>
+PolymorphicMatcher<internal::StartsWithMatcher<std::string>> StartsWith(
+    const internal::StringLike<T>& prefix) {
+  return MakePolymorphicMatcher(
+      internal::StartsWithMatcher<std::string>(std::string(prefix)));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+template <typename T = std::string>
+PolymorphicMatcher<internal::EndsWithMatcher<std::string>> EndsWith(
+    const internal::StringLike<T>& suffix) {
+  return MakePolymorphicMatcher(
+      internal::EndsWithMatcher<std::string>(std::string(suffix)));
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Wide string matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrEq(
+    const std::wstring& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::wstring>(str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrNe(
+    const std::wstring& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::wstring>(str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseEq(
+    const std::wstring& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::wstring>(str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseNe(
+    const std::wstring& str) {
+  return MakePolymorphicMatcher(
+      internal::StrEqualityMatcher<std::wstring>(str, false, false));
+}
+
+// Creates a matcher that matches any ::wstring, std::wstring, or C wide string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<std::wstring>> HasSubstr(
+    const std::wstring& substring) {
+  return MakePolymorphicMatcher(
+      internal::HasSubstrMatcher<std::wstring>(substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<std::wstring>> StartsWith(
+    const std::wstring& prefix) {
+  return MakePolymorphicMatcher(
+      internal::StartsWithMatcher<std::wstring>(prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<std::wstring>> EndsWith(
+    const std::wstring& suffix) {
+  return MakePolymorphicMatcher(
+      internal::EndsWithMatcher<std::wstring>(suffix));
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field == the second field.
+inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field >= the second field.
+inline internal::Ge2Matcher Ge() { return internal::Ge2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field > the second field.
+inline internal::Gt2Matcher Gt() { return internal::Gt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field <= the second field.
+inline internal::Le2Matcher Le() { return internal::Le2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field < the second field.
+inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field != the second field.
+inline internal::Ne2Matcher Ne() { return internal::Ne2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// FloatEq(first field) matches the second field.
+inline internal::FloatingEq2Matcher<float> FloatEq() {
+  return internal::FloatingEq2Matcher<float>();
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// DoubleEq(first field) matches the second field.
+inline internal::FloatingEq2Matcher<double> DoubleEq() {
+  return internal::FloatingEq2Matcher<double>();
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// FloatEq(first field) matches the second field with NaN equality.
+inline internal::FloatingEq2Matcher<float> NanSensitiveFloatEq() {
+  return internal::FloatingEq2Matcher<float>(true);
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// DoubleEq(first field) matches the second field with NaN equality.
+inline internal::FloatingEq2Matcher<double> NanSensitiveDoubleEq() {
+  return internal::FloatingEq2Matcher<double>(true);
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// FloatNear(first field, max_abs_error) matches the second field.
+inline internal::FloatingEq2Matcher<float> FloatNear(float max_abs_error) {
+  return internal::FloatingEq2Matcher<float>(max_abs_error);
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// DoubleNear(first field, max_abs_error) matches the second field.
+inline internal::FloatingEq2Matcher<double> DoubleNear(double max_abs_error) {
+  return internal::FloatingEq2Matcher<double>(max_abs_error);
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// FloatNear(first field, max_abs_error) matches the second field with NaN
+// equality.
+inline internal::FloatingEq2Matcher<float> NanSensitiveFloatNear(
+    float max_abs_error) {
+  return internal::FloatingEq2Matcher<float>(max_abs_error, true);
+}
+
+// Creates a polymorphic matcher that matches a 2-tuple where
+// DoubleNear(first field, max_abs_error) matches the second field with NaN
+// equality.
+inline internal::FloatingEq2Matcher<double> NanSensitiveDoubleNear(
+    double max_abs_error) {
+  return internal::FloatingEq2Matcher<double>(max_abs_error, true);
+}
+
+// Creates a matcher that matches any value of type T that m doesn't
+// match.
+template <typename InnerMatcher>
+inline internal::NotMatcher<InnerMatcher> Not(InnerMatcher m) {
+  return internal::NotMatcher<InnerMatcher>(m);
+}
+
+// Returns a matcher that matches anything that satisfies the given
+// predicate.  The predicate can be any unary function or functor
+// whose return type can be implicitly converted to bool.
+template <typename Predicate>
+inline PolymorphicMatcher<internal::TrulyMatcher<Predicate>> Truly(
+    Predicate pred) {
+  return MakePolymorphicMatcher(internal::TrulyMatcher<Predicate>(pred));
+}
+
+// Returns a matcher that matches the container size. The container must
+// support both size() and size_type which all STL-like containers provide.
+// Note that the parameter 'size' can be a value of type size_type as well as
+// matcher. For instance:
+//   EXPECT_THAT(container, SizeIs(2));     // Checks container has 2 elements.
+//   EXPECT_THAT(container, SizeIs(Le(2));  // Checks container has at most 2.
+template <typename SizeMatcher>
+inline internal::SizeIsMatcher<SizeMatcher> SizeIs(
+    const SizeMatcher& size_matcher) {
+  return internal::SizeIsMatcher<SizeMatcher>(size_matcher);
+}
+
+// Returns a matcher that matches the distance between the container's begin()
+// iterator and its end() iterator, i.e. the size of the container. This matcher
+// can be used instead of SizeIs with containers such as std::forward_list which
+// do not implement size(). The container must provide const_iterator (with
+// valid iterator_traits), begin() and end().
+template <typename DistanceMatcher>
+inline internal::BeginEndDistanceIsMatcher<DistanceMatcher> BeginEndDistanceIs(
+    const DistanceMatcher& distance_matcher) {
+  return internal::BeginEndDistanceIsMatcher<DistanceMatcher>(distance_matcher);
+}
+
+// Returns a matcher that matches an equal container.
+// This matcher behaves like Eq(), but in the event of mismatch lists the
+// values that are included in one container but not the other. (Duplicate
+// values and order differences are not explained.)
+template <typename Container>
+inline PolymorphicMatcher<
+    internal::ContainerEqMatcher<typename std::remove_const<Container>::type>>
+ContainerEq(const Container& rhs) {
+  return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs));
+}
+
+// Returns a matcher that matches a container that, when sorted using
+// the given comparator, matches container_matcher.
+template <typename Comparator, typename ContainerMatcher>
+inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher> WhenSortedBy(
+    const Comparator& comparator, const ContainerMatcher& container_matcher) {
+  return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>(
+      comparator, container_matcher);
+}
+
+// Returns a matcher that matches a container that, when sorted using
+// the < operator, matches container_matcher.
+template <typename ContainerMatcher>
+inline internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>
+WhenSorted(const ContainerMatcher& container_matcher) {
+  return internal::WhenSortedByMatcher<internal::LessComparator,
+                                       ContainerMatcher>(
+      internal::LessComparator(), container_matcher);
+}
+
+// Matches an STL-style container or a native array that contains the
+// same number of elements as in rhs, where its i-th element and rhs's
+// i-th element (as a pair) satisfy the given pair matcher, for all i.
+// TupleMatcher must be able to be safely cast to Matcher<std::tuple<const
+// T1&, const T2&> >, where T1 and T2 are the types of elements in the
+// LHS container and the RHS container respectively.
+template <typename TupleMatcher, typename Container>
+inline internal::PointwiseMatcher<TupleMatcher,
+                                  typename std::remove_const<Container>::type>
+Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
+  return internal::PointwiseMatcher<TupleMatcher, Container>(tuple_matcher,
+                                                             rhs);
+}
+
+// Supports the Pointwise(m, {a, b, c}) syntax.
+template <typename TupleMatcher, typename T>
+inline internal::PointwiseMatcher<TupleMatcher, std::vector<T>> Pointwise(
+    const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
+  return Pointwise(tuple_matcher, std::vector<T>(rhs));
+}
+
+// UnorderedPointwise(pair_matcher, rhs) matches an STL-style
+// container or a native array that contains the same number of
+// elements as in rhs, where in some permutation of the container, its
+// i-th element and rhs's i-th element (as a pair) satisfy the given
+// pair matcher, for all i.  Tuple2Matcher must be able to be safely
+// cast to Matcher<std::tuple<const T1&, const T2&> >, where T1 and T2 are
+// the types of elements in the LHS container and the RHS container
+// respectively.
+//
+// This is like Pointwise(pair_matcher, rhs), except that the element
+// order doesn't matter.
+template <typename Tuple2Matcher, typename RhsContainer>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename internal::BoundSecondMatcher<
+        Tuple2Matcher,
+        typename internal::StlContainerView<
+            typename std::remove_const<RhsContainer>::type>::type::value_type>>
+UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
+                   const RhsContainer& rhs_container) {
+  // RhsView allows the same code to handle RhsContainer being a
+  // STL-style container and it being a native C-style array.
+  typedef typename internal::StlContainerView<RhsContainer> RhsView;
+  typedef typename RhsView::type RhsStlContainer;
+  typedef typename RhsStlContainer::value_type Second;
+  const RhsStlContainer& rhs_stl_container =
+      RhsView::ConstReference(rhs_container);
+
+  // Create a matcher for each element in rhs_container.
+  ::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second>> matchers;
+  for (auto it = rhs_stl_container.begin(); it != rhs_stl_container.end();
+       ++it) {
+    matchers.push_back(internal::MatcherBindSecond(tuple2_matcher, *it));
+  }
+
+  // Delegate the work to UnorderedElementsAreArray().
+  return UnorderedElementsAreArray(matchers);
+}
+
+// Supports the UnorderedPointwise(m, {a, b, c}) syntax.
+template <typename Tuple2Matcher, typename T>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename internal::BoundSecondMatcher<Tuple2Matcher, T>>
+UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
+                   std::initializer_list<T> rhs) {
+  return UnorderedPointwise(tuple2_matcher, std::vector<T>(rhs));
+}
+
+// Matches an STL-style container or a native array that contains at
+// least one element matching the given value or matcher.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   page_ids.insert(3);
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Contains(1));
+//   EXPECT_THAT(page_ids, Contains(Gt(2)));
+//   EXPECT_THAT(page_ids, Not(Contains(4)));  // See below for Times(0)
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   EXPECT_THAT(page_lengths,
+//               Contains(::std::pair<const int, size_t>(1, 100)));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
+//
+// The matcher supports a modifier `Times` that allows to check for arbitrary
+// occurrences including testing for absence with Times(0).
+//
+// Examples:
+//   ::std::vector<int> ids;
+//   ids.insert(1);
+//   ids.insert(1);
+//   ids.insert(3);
+//   EXPECT_THAT(ids, Contains(1).Times(2));      // 1 occurs 2 times
+//   EXPECT_THAT(ids, Contains(2).Times(0));      // 2 is not present
+//   EXPECT_THAT(ids, Contains(3).Times(Ge(1)));  // 3 occurs at least once
+
+template <typename M>
+inline internal::ContainsMatcher<M> Contains(M matcher) {
+  return internal::ContainsMatcher<M>(matcher);
+}
+
+// IsSupersetOf(iterator_first, iterator_last)
+// IsSupersetOf(pointer, count)
+// IsSupersetOf(array)
+// IsSupersetOf(container)
+// IsSupersetOf({e1, e2, ..., en})
+//
+// IsSupersetOf() verifies that a surjective partial mapping onto a collection
+// of matchers exists. In other words, a container matches
+// IsSupersetOf({e1, ..., en}) if and only if there is a permutation
+// {y1, ..., yn} of some of the container's elements where y1 matches e1,
+// ..., and yn matches en. Obviously, the size of the container must be >= n
+// in order to have a match. Examples:
+//
+// - {1, 2, 3} matches IsSupersetOf({Ge(3), Ne(0)}), as 3 matches Ge(3) and
+//   1 matches Ne(0).
+// - {1, 2} doesn't match IsSupersetOf({Eq(1), Lt(2)}), even though 1 matches
+//   both Eq(1) and Lt(2). The reason is that different matchers must be used
+//   for elements in different slots of the container.
+// - {1, 1, 2} matches IsSupersetOf({Eq(1), Lt(2)}), as (the first) 1 matches
+//   Eq(1) and (the second) 1 matches Lt(2).
+// - {1, 2, 3} matches IsSupersetOf(Gt(1), Gt(1)), as 2 matches (the first)
+//   Gt(1) and 3 matches (the second) Gt(1).
+//
+// The matchers can be specified as an array, a pointer and count, a container,
+// an initializer list, or an STL iterator range. In each of these cases, the
+// underlying matchers can be either values or matchers.
+
+template <typename Iter>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+IsSupersetOf(Iter first, Iter last) {
+  typedef typename ::std::iterator_traits<Iter>::value_type T;
+  return internal::UnorderedElementsAreArrayMatcher<T>(
+      internal::UnorderedMatcherRequire::Superset, first, last);
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
+    const T* pointer, size_t count) {
+  return IsSupersetOf(pointer, pointer + count);
+}
+
+template <typename T, size_t N>
+inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
+    const T (&array)[N]) {
+  return IsSupersetOf(array, N);
+}
+
+template <typename Container>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename Container::value_type>
+IsSupersetOf(const Container& container) {
+  return IsSupersetOf(container.begin(), container.end());
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
+    ::std::initializer_list<T> xs) {
+  return IsSupersetOf(xs.begin(), xs.end());
+}
+
+// IsSubsetOf(iterator_first, iterator_last)
+// IsSubsetOf(pointer, count)
+// IsSubsetOf(array)
+// IsSubsetOf(container)
+// IsSubsetOf({e1, e2, ..., en})
+//
+// IsSubsetOf() verifies that an injective mapping onto a collection of matchers
+// exists.  In other words, a container matches IsSubsetOf({e1, ..., en}) if and
+// only if there is a subset of matchers {m1, ..., mk} which would match the
+// container using UnorderedElementsAre.  Obviously, the size of the container
+// must be <= n in order to have a match. Examples:
+//
+// - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
+// - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
+//   matches Lt(0).
+// - {1, 2} doesn't matches IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
+//   match Gt(0). The reason is that different matchers must be used for
+//   elements in different slots of the container.
+//
+// The matchers can be specified as an array, a pointer and count, a container,
+// an initializer list, or an STL iterator range. In each of these cases, the
+// underlying matchers can be either values or matchers.
+
+template <typename Iter>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+IsSubsetOf(Iter first, Iter last) {
+  typedef typename ::std::iterator_traits<Iter>::value_type T;
+  return internal::UnorderedElementsAreArrayMatcher<T>(
+      internal::UnorderedMatcherRequire::Subset, first, last);
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
+    const T* pointer, size_t count) {
+  return IsSubsetOf(pointer, pointer + count);
+}
+
+template <typename T, size_t N>
+inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
+    const T (&array)[N]) {
+  return IsSubsetOf(array, N);
+}
+
+template <typename Container>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename Container::value_type>
+IsSubsetOf(const Container& container) {
+  return IsSubsetOf(container.begin(), container.end());
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
+    ::std::initializer_list<T> xs) {
+  return IsSubsetOf(xs.begin(), xs.end());
+}
+
+// Matches an STL-style container or a native array that contains only
+// elements matching the given value or matcher.
+//
+// Each(m) is semantically equivalent to `Not(Contains(Not(m)))`. Only
+// the messages are different.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   // Each(m) matches an empty container, regardless of what m is.
+//   EXPECT_THAT(page_ids, Each(Eq(1)));
+//   EXPECT_THAT(page_ids, Each(Eq(77)));
+//
+//   page_ids.insert(3);
+//   EXPECT_THAT(page_ids, Each(Gt(0)));
+//   EXPECT_THAT(page_ids, Not(Each(Gt(4))));
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Not(Each(Lt(2))));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   page_lengths[2] = 200;
+//   page_lengths[3] = 300;
+//   EXPECT_THAT(page_lengths, Not(Each(Pair(1, 100))));
+//   EXPECT_THAT(page_lengths, Each(Key(Le(3))));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Not(Each(Eq(::std::string("tom")))));
+template <typename M>
+inline internal::EachMatcher<M> Each(M matcher) {
+  return internal::EachMatcher<M>(matcher);
+}
+
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename M>
+inline internal::KeyMatcher<M> Key(M inner_matcher) {
+  return internal::KeyMatcher<M>(inner_matcher);
+}
+
+// Pair(first_matcher, second_matcher) matches a std::pair whose 'first' field
+// matches first_matcher and whose 'second' field matches second_matcher.  For
+// example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used
+// to match a std::map<int, string> that contains exactly one element whose key
+// is >= 5 and whose value equals "foo".
+template <typename FirstMatcher, typename SecondMatcher>
+inline internal::PairMatcher<FirstMatcher, SecondMatcher> Pair(
+    FirstMatcher first_matcher, SecondMatcher second_matcher) {
+  return internal::PairMatcher<FirstMatcher, SecondMatcher>(first_matcher,
+                                                            second_matcher);
+}
+
+namespace no_adl {
+// Conditional() creates a matcher that conditionally uses either the first or
+// second matcher provided. For example, we could create an `equal if, and only
+// if' matcher using the Conditional wrapper as follows:
+//
+//   EXPECT_THAT(result, Conditional(condition, Eq(expected), Ne(expected)));
+template <typename MatcherTrue, typename MatcherFalse>
+internal::ConditionalMatcher<MatcherTrue, MatcherFalse> Conditional(
+    bool condition, MatcherTrue matcher_true, MatcherFalse matcher_false) {
+  return internal::ConditionalMatcher<MatcherTrue, MatcherFalse>(
+      condition, std::move(matcher_true), std::move(matcher_false));
+}
+
+// FieldsAre(matchers...) matches piecewise the fields of compatible structs.
+// These include those that support `get<I>(obj)`, and when structured bindings
+// are enabled any class that supports them.
+// In particular, `std::tuple`, `std::pair`, `std::array` and aggregate types.
+template <typename... M>
+internal::FieldsAreMatcher<typename std::decay<M>::type...> FieldsAre(
+    M&&... matchers) {
+  return internal::FieldsAreMatcher<typename std::decay<M>::type...>(
+      std::forward<M>(matchers)...);
+}
+
+// Creates a matcher that matches a pointer (raw or smart) that matches
+// inner_matcher.
+template <typename InnerMatcher>
+inline internal::PointerMatcher<InnerMatcher> Pointer(
+    const InnerMatcher& inner_matcher) {
+  return internal::PointerMatcher<InnerMatcher>(inner_matcher);
+}
+
+// Creates a matcher that matches an object that has an address that matches
+// inner_matcher.
+template <typename InnerMatcher>
+inline internal::AddressMatcher<InnerMatcher> Address(
+    const InnerMatcher& inner_matcher) {
+  return internal::AddressMatcher<InnerMatcher>(inner_matcher);
+}
+
+// Matches a base64 escaped string, when the unescaped string matches the
+// internal matcher.
+template <typename MatcherType>
+internal::WhenBase64UnescapedMatcher WhenBase64Unescaped(
+    const MatcherType& internal_matcher) {
+  return internal::WhenBase64UnescapedMatcher(internal_matcher);
+}
+}  // namespace no_adl
+
+// Returns a predicate that is satisfied by anything that matches the
+// given matcher.
+template <typename M>
+inline internal::MatcherAsPredicate<M> Matches(M matcher) {
+  return internal::MatcherAsPredicate<M>(matcher);
+}
+
+// Returns true if and only if the value matches the matcher.
+template <typename T, typename M>
+inline bool Value(const T& value, M matcher) {
+  return testing::Matches(matcher)(value);
+}
+
+// Matches the value against the given matcher and explains the match
+// result to listener.
+template <typename T, typename M>
+inline bool ExplainMatchResult(M matcher, const T& value,
+                               MatchResultListener* listener) {
+  return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
+}
+
+// Returns a string representation of the given matcher.  Useful for description
+// strings of matchers defined using MATCHER_P* macros that accept matchers as
+// their arguments.  For example:
+//
+// MATCHER_P(XAndYThat, matcher,
+//           "X that " + DescribeMatcher<int>(matcher, negation) +
+//               (negation ? " or" : " and") + " Y that " +
+//               DescribeMatcher<double>(matcher, negation)) {
+//   return ExplainMatchResult(matcher, arg.x(), result_listener) &&
+//          ExplainMatchResult(matcher, arg.y(), result_listener);
+// }
+template <typename T, typename M>
+std::string DescribeMatcher(const M& matcher, bool negation = false) {
+  ::std::stringstream ss;
+  Matcher<T> monomorphic_matcher = SafeMatcherCast<T>(matcher);
+  if (negation) {
+    monomorphic_matcher.DescribeNegationTo(&ss);
+  } else {
+    monomorphic_matcher.DescribeTo(&ss);
+  }
+  return ss.str();
+}
+
+template <typename... Args>
+internal::ElementsAreMatcher<
+    std::tuple<typename std::decay<const Args&>::type...>>
+ElementsAre(const Args&... matchers) {
+  return internal::ElementsAreMatcher<
+      std::tuple<typename std::decay<const Args&>::type...>>(
+      std::make_tuple(matchers...));
+}
+
+template <typename... Args>
+internal::UnorderedElementsAreMatcher<
+    std::tuple<typename std::decay<const Args&>::type...>>
+UnorderedElementsAre(const Args&... matchers) {
+  return internal::UnorderedElementsAreMatcher<
+      std::tuple<typename std::decay<const Args&>::type...>>(
+      std::make_tuple(matchers...));
+}
+
+// Define variadic matcher versions.
+template <typename... Args>
+internal::AllOfMatcher<typename std::decay<const Args&>::type...> AllOf(
+    const Args&... matchers) {
+  return internal::AllOfMatcher<typename std::decay<const Args&>::type...>(
+      matchers...);
+}
+
+template <typename... Args>
+internal::AnyOfMatcher<typename std::decay<const Args&>::type...> AnyOf(
+    const Args&... matchers) {
+  return internal::AnyOfMatcher<typename std::decay<const Args&>::type...>(
+      matchers...);
+}
+
+// AnyOfArray(array)
+// AnyOfArray(pointer, count)
+// AnyOfArray(container)
+// AnyOfArray({ e1, e2, ..., en })
+// AnyOfArray(iterator_first, iterator_last)
+//
+// AnyOfArray() verifies whether a given value matches any member of a
+// collection of matchers.
+//
+// AllOfArray(array)
+// AllOfArray(pointer, count)
+// AllOfArray(container)
+// AllOfArray({ e1, e2, ..., en })
+// AllOfArray(iterator_first, iterator_last)
+//
+// AllOfArray() verifies whether a given value matches all members of a
+// collection of matchers.
+//
+// The matchers can be specified as an array, a pointer and count, a container,
+// an initializer list, or an STL iterator range. In each of these cases, the
+// underlying matchers can be either values or matchers.
+
+template <typename Iter>
+inline internal::AnyOfArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+AnyOfArray(Iter first, Iter last) {
+  return internal::AnyOfArrayMatcher<
+      typename ::std::iterator_traits<Iter>::value_type>(first, last);
+}
+
+template <typename Iter>
+inline internal::AllOfArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+AllOfArray(Iter first, Iter last) {
+  return internal::AllOfArrayMatcher<
+      typename ::std::iterator_traits<Iter>::value_type>(first, last);
+}
+
+template <typename T>
+inline internal::AnyOfArrayMatcher<T> AnyOfArray(const T* ptr, size_t count) {
+  return AnyOfArray(ptr, ptr + count);
+}
+
+template <typename T>
+inline internal::AllOfArrayMatcher<T> AllOfArray(const T* ptr, size_t count) {
+  return AllOfArray(ptr, ptr + count);
+}
+
+template <typename T, size_t N>
+inline internal::AnyOfArrayMatcher<T> AnyOfArray(const T (&array)[N]) {
+  return AnyOfArray(array, N);
+}
+
+template <typename T, size_t N>
+inline internal::AllOfArrayMatcher<T> AllOfArray(const T (&array)[N]) {
+  return AllOfArray(array, N);
+}
+
+template <typename Container>
+inline internal::AnyOfArrayMatcher<typename Container::value_type> AnyOfArray(
+    const Container& container) {
+  return AnyOfArray(container.begin(), container.end());
+}
+
+template <typename Container>
+inline internal::AllOfArrayMatcher<typename Container::value_type> AllOfArray(
+    const Container& container) {
+  return AllOfArray(container.begin(), container.end());
+}
+
+template <typename T>
+inline internal::AnyOfArrayMatcher<T> AnyOfArray(
+    ::std::initializer_list<T> xs) {
+  return AnyOfArray(xs.begin(), xs.end());
+}
+
+template <typename T>
+inline internal::AllOfArrayMatcher<T> AllOfArray(
+    ::std::initializer_list<T> xs) {
+  return AllOfArray(xs.begin(), xs.end());
+}
+
+// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
+// fields of it matches a_matcher.  C++ doesn't support default
+// arguments for function templates, so we have to overload it.
+template <size_t... k, typename InnerMatcher>
+internal::ArgsMatcher<typename std::decay<InnerMatcher>::type, k...> Args(
+    InnerMatcher&& matcher) {
+  return internal::ArgsMatcher<typename std::decay<InnerMatcher>::type, k...>(
+      std::forward<InnerMatcher>(matcher));
+}
+
+// AllArgs(m) is a synonym of m.  This is useful in
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq()));
+//
+// which is easier to read than
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(Eq());
+template <typename InnerMatcher>
+inline InnerMatcher AllArgs(const InnerMatcher& matcher) {
+  return matcher;
+}
+
+// Returns a matcher that matches the value of an optional<> type variable.
+// The matcher implementation only uses '!arg' and requires that the optional<>
+// type has a 'value_type' member type and that '*arg' is of type 'value_type'
+// and is printable using 'PrintToString'. It is compatible with
+// std::optional/std::experimental::optional.
+// Note that to compare an optional type variable against nullopt you should
+// use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the
+// optional value contains an optional itself.
+template <typename ValueMatcher>
+inline internal::OptionalMatcher<ValueMatcher> Optional(
+    const ValueMatcher& value_matcher) {
+  return internal::OptionalMatcher<ValueMatcher>(value_matcher);
+}
+
+// Returns a matcher that matches the value of a absl::any type variable.
+template <typename T>
+PolymorphicMatcher<internal::any_cast_matcher::AnyCastMatcher<T>> AnyWith(
+    const Matcher<const T&>& matcher) {
+  return MakePolymorphicMatcher(
+      internal::any_cast_matcher::AnyCastMatcher<T>(matcher));
+}
+
+// Returns a matcher that matches the value of a variant<> type variable.
+// The matcher implementation uses ADL to find the holds_alternative and get
+// functions.
+// It is compatible with std::variant.
+template <typename T>
+PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T>> VariantWith(
+    const Matcher<const T&>& matcher) {
+  return MakePolymorphicMatcher(
+      internal::variant_matcher::VariantMatcher<T>(matcher));
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Anything inside the `internal` namespace is internal to the implementation
+// and must not be used in user code!
+namespace internal {
+
+class WithWhatMatcherImpl {
+ public:
+  WithWhatMatcherImpl(Matcher<std::string> matcher)
+      : matcher_(std::move(matcher)) {}
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "contains .what() that ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "contains .what() that does not ";
+    matcher_.DescribeTo(os);
+  }
+
+  template <typename Err>
+  bool MatchAndExplain(const Err& err, MatchResultListener* listener) const {
+    *listener << "which contains .what() (of value = " << err.what()
+              << ") that ";
+    return matcher_.MatchAndExplain(err.what(), listener);
+  }
+
+ private:
+  const Matcher<std::string> matcher_;
+};
+
+inline PolymorphicMatcher<WithWhatMatcherImpl> WithWhat(
+    Matcher<std::string> m) {
+  return MakePolymorphicMatcher(WithWhatMatcherImpl(std::move(m)));
+}
+
+template <typename Err>
+class ExceptionMatcherImpl {
+  class NeverThrown {
+   public:
+    const char* what() const noexcept {
+      return "this exception should never be thrown";
+    }
+  };
+
+  // If the matchee raises an exception of a wrong type, we'd like to
+  // catch it and print its message and type. To do that, we add an additional
+  // catch clause:
+  //
+  //     try { ... }
+  //     catch (const Err&) { /* an expected exception */ }
+  //     catch (const std::exception&) { /* exception of a wrong type */ }
+  //
+  // However, if the `Err` itself is `std::exception`, we'd end up with two
+  // identical `catch` clauses:
+  //
+  //     try { ... }
+  //     catch (const std::exception&) { /* an expected exception */ }
+  //     catch (const std::exception&) { /* exception of a wrong type */ }
+  //
+  // This can cause a warning or an error in some compilers. To resolve
+  // the issue, we use a fake error type whenever `Err` is `std::exception`:
+  //
+  //     try { ... }
+  //     catch (const std::exception&) { /* an expected exception */ }
+  //     catch (const NeverThrown&) { /* exception of a wrong type */ }
+  using DefaultExceptionType = typename std::conditional<
+      std::is_same<typename std::remove_cv<
+                       typename std::remove_reference<Err>::type>::type,
+                   std::exception>::value,
+      const NeverThrown&, const std::exception&>::type;
+
+ public:
+  ExceptionMatcherImpl(Matcher<const Err&> matcher)
+      : matcher_(std::move(matcher)) {}
+
+  void DescribeTo(std::ostream* os) const {
+    *os << "throws an exception which is a " << GetTypeName<Err>();
+    *os << " which ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "throws an exception which is not a " << GetTypeName<Err>();
+    *os << " which ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(T&& x, MatchResultListener* listener) const {
+    try {
+      (void)(std::forward<T>(x)());
+    } catch (const Err& err) {
+      *listener << "throws an exception which is a " << GetTypeName<Err>();
+      *listener << " ";
+      return matcher_.MatchAndExplain(err, listener);
+    } catch (DefaultExceptionType err) {
+#if GTEST_HAS_RTTI
+      *listener << "throws an exception of type " << GetTypeName(typeid(err));
+      *listener << " ";
+#else
+      *listener << "throws an std::exception-derived type ";
+#endif
+      *listener << "with description \"" << err.what() << "\"";
+      return false;
+    } catch (...) {
+      *listener << "throws an exception of an unknown type";
+      return false;
+    }
+
+    *listener << "does not throw any exception";
+    return false;
+  }
+
+ private:
+  const Matcher<const Err&> matcher_;
+};
+
+}  // namespace internal
+
+// Throws()
+// Throws(exceptionMatcher)
+// ThrowsMessage(messageMatcher)
+//
+// This matcher accepts a callable and verifies that when invoked, it throws
+// an exception with the given type and properties.
+//
+// Examples:
+//
+//   EXPECT_THAT(
+//       []() { throw std::runtime_error("message"); },
+//       Throws<std::runtime_error>());
+//
+//   EXPECT_THAT(
+//       []() { throw std::runtime_error("message"); },
+//       ThrowsMessage<std::runtime_error>(HasSubstr("message")));
+//
+//   EXPECT_THAT(
+//       []() { throw std::runtime_error("message"); },
+//       Throws<std::runtime_error>(
+//           Property(&std::runtime_error::what, HasSubstr("message"))));
+
+template <typename Err>
+PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> Throws() {
+  return MakePolymorphicMatcher(
+      internal::ExceptionMatcherImpl<Err>(A<const Err&>()));
+}
+
+template <typename Err, typename ExceptionMatcher>
+PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> Throws(
+    const ExceptionMatcher& exception_matcher) {
+  // Using matcher cast allows users to pass a matcher of a more broad type.
+  // For example user may want to pass Matcher<std::exception>
+  // to Throws<std::runtime_error>, or Matcher<int64> to Throws<int32>.
+  return MakePolymorphicMatcher(internal::ExceptionMatcherImpl<Err>(
+      SafeMatcherCast<const Err&>(exception_matcher)));
+}
+
+template <typename Err, typename MessageMatcher>
+PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
+    MessageMatcher&& message_matcher) {
+  static_assert(std::is_base_of<std::exception, Err>::value,
+                "expected an std::exception-derived type");
+  return Throws<Err>(internal::WithWhat(
+      MatcherCast<std::string>(std::forward<MessageMatcher>(message_matcher))));
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// These macros allow using matchers to check values in Google Test
+// tests.  ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
+// succeed if and only if the value matches the matcher.  If the assertion
+// fails, the value and the description of the matcher will be printed.
+#define ASSERT_THAT(value, matcher) \
+  ASSERT_PRED_FORMAT1(              \
+      ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+#define EXPECT_THAT(value, matcher) \
+  EXPECT_PRED_FORMAT1(              \
+      ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+
+// MATCHER* macros itself are listed below.
+#define MATCHER(name, description)                                            \
+  class name##Matcher                                                         \
+      : public ::testing::internal::MatcherBaseImpl<name##Matcher> {          \
+   public:                                                                    \
+    template <typename arg_type>                                              \
+    class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> {  \
+     public:                                                                  \
+      gmock_Impl() {}                                                         \
+      bool MatchAndExplain(                                                   \
+          const arg_type& arg,                                                \
+          ::testing::MatchResultListener* result_listener) const override;    \
+      void DescribeTo(::std::ostream* gmock_os) const override {              \
+        *gmock_os << FormatDescription(false);                                \
+      }                                                                       \
+      void DescribeNegationTo(::std::ostream* gmock_os) const override {      \
+        *gmock_os << FormatDescription(true);                                 \
+      }                                                                       \
+                                                                              \
+     private:                                                                 \
+      ::std::string FormatDescription(bool negation) const {                  \
+        /* NOLINTNEXTLINE readability-redundant-string-init */                \
+        ::std::string gmock_description = (description);                      \
+        if (!gmock_description.empty()) {                                     \
+          return gmock_description;                                           \
+        }                                                                     \
+        return ::testing::internal::FormatMatcherDescription(negation, #name, \
+                                                             {}, {});         \
+      }                                                                       \
+    };                                                                        \
+  };                                                                          \
+  inline name##Matcher GMOCK_INTERNAL_WARNING_PUSH()                          \
+      GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-function")              \
+          GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function")   \
+              name GMOCK_INTERNAL_WARNING_POP()() {                           \
+    return {};                                                                \
+  }                                                                           \
+  template <typename arg_type>                                                \
+  bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(                  \
+      const arg_type& arg,                                                    \
+      GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing::MatchResultListener*   \
+          result_listener) const
+
+#define MATCHER_P(name, p0, description) \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
+#define MATCHER_P2(name, p0, p1, description)                            \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (#p0, #p1), \
+                         (p0, p1))
+#define MATCHER_P3(name, p0, p1, p2, description)                             \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (#p0, #p1, #p2), \
+                         (p0, p1, p2))
+#define MATCHER_P4(name, p0, p1, p2, p3, description)        \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, \
+                         (#p0, #p1, #p2, #p3), (p0, p1, p2, p3))
+#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)    \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \
+                         (#p0, #p1, #p2, #p3, #p4), (p0, p1, p2, p3, p4))
+#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description,  \
+                         (#p0, #p1, #p2, #p3, #p4, #p5),      \
+                         (p0, p1, p2, p3, p4, p5))
+#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description,      \
+                         (#p0, #p1, #p2, #p3, #p4, #p5, #p6),     \
+                         (p0, p1, p2, p3, p4, p5, p6))
+#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description,          \
+                         (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7),    \
+                         (p0, p1, p2, p3, p4, p5, p6, p7))
+#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description,              \
+                         (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8),   \
+                         (p0, p1, p2, p3, p4, p5, p6, p7, p8))
+#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \
+  GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description,                  \
+                         (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8, #p9),   \
+                         (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9))
+
+#define GMOCK_INTERNAL_MATCHER(name, full_name, description, arg_names, args)  \
+  template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)>                      \
+  class full_name : public ::testing::internal::MatcherBaseImpl<               \
+                        full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>> { \
+   public:                                                                     \
+    using full_name::MatcherBaseImpl::MatcherBaseImpl;                         \
+    template <typename arg_type>                                               \
+    class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> {   \
+     public:                                                                   \
+      explicit gmock_Impl(GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args))          \
+          : GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) {}                       \
+      bool MatchAndExplain(                                                    \
+          const arg_type& arg,                                                 \
+          ::testing::MatchResultListener* result_listener) const override;     \
+      void DescribeTo(::std::ostream* gmock_os) const override {               \
+        *gmock_os << FormatDescription(false);                                 \
+      }                                                                        \
+      void DescribeNegationTo(::std::ostream* gmock_os) const override {       \
+        *gmock_os << FormatDescription(true);                                  \
+      }                                                                        \
+      GMOCK_INTERNAL_MATCHER_MEMBERS(args)                                     \
+                                                                               \
+     private:                                                                  \
+      ::std::string FormatDescription(bool negation) const {                   \
+        ::std::string gmock_description;                                       \
+        gmock_description = (description);                                     \
+        if (!gmock_description.empty()) {                                      \
+          return gmock_description;                                            \
+        }                                                                      \
+        return ::testing::internal::FormatMatcherDescription(                  \
+            negation, #name, {GMOCK_PP_REMOVE_PARENS(arg_names)},              \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(      \
+                ::std::tuple<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>(        \
+                    GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args))));             \
+      }                                                                        \
+    };                                                                         \
+  };                                                                           \
+  template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)>                      \
+  inline full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)> name(             \
+      GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) {                            \
+    return full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>(                \
+        GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args));                              \
+  }                                                                            \
+  template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)>                      \
+  template <typename arg_type>                                                 \
+  bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::                   \
+      gmock_Impl<arg_type>::MatchAndExplain(                                   \
+          const arg_type& arg,                                                 \
+          GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing::                    \
+              MatchResultListener* result_listener) const
+
+#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
+  GMOCK_PP_TAIL(                                     \
+      GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM, , args))
+#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM(i_unused, data_unused, arg) \
+  , typename arg##_type
+
+#define GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TYPE_PARAM, , args))
+#define GMOCK_INTERNAL_MATCHER_TYPE_PARAM(i_unused, data_unused, arg) \
+  , arg##_type
+
+#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args) \
+  GMOCK_PP_TAIL(dummy_first GMOCK_PP_FOR_EACH(     \
+      GMOCK_INTERNAL_MATCHER_FUNCTION_ARG, , args))
+#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARG(i, data_unused, arg) \
+  , arg##_type gmock_p##i
+
+#define GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_FORWARD_ARG, , args))
+#define GMOCK_INTERNAL_MATCHER_FORWARD_ARG(i, data_unused, arg) \
+  , arg(::std::forward<arg##_type>(gmock_p##i))
+
+#define GMOCK_INTERNAL_MATCHER_MEMBERS(args) \
+  GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER, , args)
+#define GMOCK_INTERNAL_MATCHER_MEMBER(i_unused, data_unused, arg) \
+  const arg##_type arg;
+
+#define GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER_USAGE, , args))
+#define GMOCK_INTERNAL_MATCHER_MEMBER_USAGE(i_unused, data_unused, arg) , arg
+
+#define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \
+  GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args))
+#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg) \
+  , ::std::forward<arg##_type>(gmock_p##i)
+
+// To prevent ADL on certain functions we put them on a separate namespace.
+using namespace no_adl;  // NOLINT
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251 5046
+
+// Include any custom callback matchers added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+#include "gmock/internal/custom/gmock-matchers.h"
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-more-actions.h b/3rd-party/googletest/googlemock/include/gmock/gmock-more-actions.h
new file mode 100644
index 0000000..55294db
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-more-actions.h
@@ -0,0 +1,660 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic actions.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+
+#include <memory>
+#include <utility>
+
+#include "gmock/gmock-actions.h"
+#include "gmock/internal/gmock-port.h"
+
+// Include any custom callback actions added by the local installation.
+#include "gmock/internal/custom/gmock-generated-actions.h"
+
+// Sometimes you want to give an action explicit template parameters
+// that cannot be inferred from its value parameters.  ACTION() and
+// ACTION_P*() don't support that.  ACTION_TEMPLATE() remedies that
+// and can be viewed as an extension to ACTION() and ACTION_P*().
+//
+// The syntax:
+//
+//   ACTION_TEMPLATE(ActionName,
+//                   HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+//                   AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+//
+// defines an action template that takes m explicit template
+// parameters and n value parameters.  name_i is the name of the i-th
+// template parameter, and kind_i specifies whether it's a typename,
+// an integral constant, or a template.  p_i is the name of the i-th
+// value parameter.
+//
+// Example:
+//
+//   // DuplicateArg<k, T>(output) converts the k-th argument of the mock
+//   // function to type T and copies it to *output.
+//   ACTION_TEMPLATE(DuplicateArg,
+//                   HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+//                   AND_1_VALUE_PARAMS(output)) {
+//     *output = T(::std::get<k>(args));
+//   }
+//   ...
+//     int n;
+//     EXPECT_CALL(mock, Foo(_, _))
+//         .WillOnce(DuplicateArg<1, unsigned char>(&n));
+//
+// To create an instance of an action template, write:
+//
+//   ActionName<t1, ..., t_m>(v1, ..., v_n)
+//
+// where the ts are the template arguments and the vs are the value
+// arguments.  The value argument types are inferred by the compiler.
+// If you want to explicitly specify the value argument types, you can
+// provide additional template arguments:
+//
+//   ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+//
+// where u_i is the desired type of v_i.
+//
+// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
+// number of value parameters, but not on the number of template
+// parameters.  Without the restriction, the meaning of the following
+// is unclear:
+//
+//   OverloadedAction<int, bool>(x);
+//
+// Are we using a single-template-parameter action where 'bool' refers
+// to the type of x, or are we using a two-template-parameter action
+// where the compiler is asked to infer the type of x?
+//
+// Implementation notes:
+//
+// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
+// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
+// implementing ACTION_TEMPLATE.  The main trick we use is to create
+// new macro invocations when expanding a macro.  For example, we have
+//
+//   #define ACTION_TEMPLATE(name, template_params, value_params)
+//       ... GMOCK_INTERNAL_DECL_##template_params ...
+//
+// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
+// to expand to
+//
+//       ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
+//
+// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
+// preprocessor will continue to expand it to
+//
+//       ... typename T ...
+//
+// This technique conforms to the C++ standard and is portable.  It
+// allows us to implement action templates using O(N) code, where N is
+// the maximum number of template/value parameters supported.  Without
+// using it, we'd have to devote O(N^2) amount of code to implement all
+// combinations of m and n.
+
+// Declares the template parameters.
+#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0
+#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, name1) \
+  kind0 name0, kind1 name1
+#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+                                                  kind2, name2)               \
+  kind0 name0, kind1 name1, kind2 name2
+#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+                                                  kind2, name2, kind3, name3) \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3
+#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4) \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4
+#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+                                                  kind2, name2, kind3, name3, \
+                                                  kind4, name4, kind5, name5) \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5
+#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6)                                           \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4,        \
+      kind5 name5, kind6 name6
+#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6, kind7, name7)                             \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4,        \
+      kind5 name5, kind6 name6, kind7 name7
+#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6, kind7, name7, kind8, name8)               \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4,        \
+      kind5 name5, kind6 name6, kind7 name7, kind8 name8
+#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(                       \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6, kind7, name7, kind8, name8, kind9, name9) \
+  kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4,        \
+      kind5 name5, kind6 name6, kind7 name7, kind8 name8, kind9 name9
+
+// Lists the template parameters.
+#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0
+#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, name1) \
+  name0, name1
+#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+                                                  kind2, name2)               \
+  name0, name1, name2
+#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+                                                  kind2, name2, kind3, name3) \
+  name0, name1, name2, name3
+#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4) \
+  name0, name1, name2, name3, name4
+#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+                                                  kind2, name2, kind3, name3, \
+                                                  kind4, name4, kind5, name5) \
+  name0, name1, name2, name3, name4, name5
+#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6)                                           \
+  name0, name1, name2, name3, name4, name5, name6
+#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6, kind7, name7)                             \
+  name0, name1, name2, name3, name4, name5, name6, name7
+#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(                        \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6, kind7, name7, kind8, name8)               \
+  name0, name1, name2, name3, name4, name5, name6, name7, name8
+#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(                       \
+    kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
+    kind5, name5, kind6, name6, kind7, name7, kind8, name8, kind9, name9) \
+  name0, name1, name2, name3, name4, name5, name6, name7, name8, name9
+
+// Declares the types of value parameters.
+#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) \
+  , typename p0##_type, typename p1##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) \
+  , typename p0##_type, typename p1##_type, typename p2##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
+  , typename p0##_type, typename p1##_type, typename p2##_type,     \
+      typename p3##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
+  , typename p0##_type, typename p1##_type, typename p2##_type,         \
+      typename p3##_type, typename p4##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
+  , typename p0##_type, typename p1##_type, typename p2##_type,             \
+      typename p3##_type, typename p4##_type, typename p5##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                    p6)                     \
+  , typename p0##_type, typename p1##_type, typename p2##_type,             \
+      typename p3##_type, typename p4##_type, typename p5##_type,           \
+      typename p6##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                    p6, p7)                 \
+  , typename p0##_type, typename p1##_type, typename p2##_type,             \
+      typename p3##_type, typename p4##_type, typename p5##_type,           \
+      typename p6##_type, typename p7##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                    p6, p7, p8)             \
+  , typename p0##_type, typename p1##_type, typename p2##_type,             \
+      typename p3##_type, typename p4##_type, typename p5##_type,           \
+      typename p6##_type, typename p7##_type, typename p8##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                     p6, p7, p8, p9)         \
+  , typename p0##_type, typename p1##_type, typename p2##_type,              \
+      typename p3##_type, typename p4##_type, typename p5##_type,            \
+      typename p6##_type, typename p7##_type, typename p8##_type,            \
+      typename p9##_type
+
+// Initializes the value parameters.
+#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS() ()
+#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0) \
+  (p0##_type gmock_p0) : p0(::std::move(gmock_p0))
+#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1) \
+  (p0##_type gmock_p0, p1##_type gmock_p1)             \
+      : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1))
+#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)     \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2) \
+      : p0(::std::move(gmock_p0)),                             \
+        p1(::std::move(gmock_p1)),                             \
+        p2(::std::move(gmock_p2))
+#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+   p3##_type gmock_p3)                                         \
+      : p0(::std::move(gmock_p0)),                             \
+        p1(::std::move(gmock_p1)),                             \
+        p2(::std::move(gmock_p2)),                             \
+        p3(::std::move(gmock_p3))
+#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2,     \
+   p3##_type gmock_p3, p4##_type gmock_p4)                         \
+      : p0(::std::move(gmock_p0)),                                 \
+        p1(::std::move(gmock_p1)),                                 \
+        p2(::std::move(gmock_p2)),                                 \
+        p3(::std::move(gmock_p3)),                                 \
+        p4(::std::move(gmock_p4))
+#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2,         \
+   p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)         \
+      : p0(::std::move(gmock_p0)),                                     \
+        p1(::std::move(gmock_p1)),                                     \
+        p2(::std::move(gmock_p2)),                                     \
+        p3(::std::move(gmock_p3)),                                     \
+        p4(::std::move(gmock_p4)),                                     \
+        p5(::std::move(gmock_p5))
+#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2,             \
+   p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5,             \
+   p6##_type gmock_p6)                                                     \
+      : p0(::std::move(gmock_p0)),                                         \
+        p1(::std::move(gmock_p1)),                                         \
+        p2(::std::move(gmock_p2)),                                         \
+        p3(::std::move(gmock_p3)),                                         \
+        p4(::std::move(gmock_p4)),                                         \
+        p5(::std::move(gmock_p5)),                                         \
+        p6(::std::move(gmock_p6))
+#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2,                 \
+   p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5,                 \
+   p6##_type gmock_p6, p7##_type gmock_p7)                                     \
+      : p0(::std::move(gmock_p0)),                                             \
+        p1(::std::move(gmock_p1)),                                             \
+        p2(::std::move(gmock_p2)),                                             \
+        p3(::std::move(gmock_p3)),                                             \
+        p4(::std::move(gmock_p4)),                                             \
+        p5(::std::move(gmock_p5)),                                             \
+        p6(::std::move(gmock_p6)),                                             \
+        p7(::std::move(gmock_p7))
+#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
+                                               p8)                             \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2,                 \
+   p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5,                 \
+   p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)                 \
+      : p0(::std::move(gmock_p0)),                                             \
+        p1(::std::move(gmock_p1)),                                             \
+        p2(::std::move(gmock_p2)),                                             \
+        p3(::std::move(gmock_p3)),                                             \
+        p4(::std::move(gmock_p4)),                                             \
+        p5(::std::move(gmock_p5)),                                             \
+        p6(::std::move(gmock_p6)),                                             \
+        p7(::std::move(gmock_p7)),                                             \
+        p8(::std::move(gmock_p8))
+#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                p7, p8, p9)                 \
+  (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2,              \
+   p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5,              \
+   p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8,              \
+   p9##_type gmock_p9)                                                      \
+      : p0(::std::move(gmock_p0)),                                          \
+        p1(::std::move(gmock_p1)),                                          \
+        p2(::std::move(gmock_p2)),                                          \
+        p3(::std::move(gmock_p3)),                                          \
+        p4(::std::move(gmock_p4)),                                          \
+        p5(::std::move(gmock_p5)),                                          \
+        p6(::std::move(gmock_p6)),                                          \
+        p7(::std::move(gmock_p7)),                                          \
+        p8(::std::move(gmock_p8)),                                          \
+        p9(::std::move(gmock_p9))
+
+// Defines the copy constructor
+#define GMOCK_INTERNAL_DEFN_COPY_AND_0_VALUE_PARAMS() \
+  {}  // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134
+#define GMOCK_INTERNAL_DEFN_COPY_AND_1_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_2_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_3_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_4_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_5_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_6_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_7_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_8_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_9_VALUE_PARAMS(...) = default;
+#define GMOCK_INTERNAL_DEFN_COPY_AND_10_VALUE_PARAMS(...) = default;
+
+// Declares the fields for storing the value parameters.
+#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0;
+#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) \
+  p0##_type p0;                                        \
+  p1##_type p1;
+#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) \
+  p0##_type p0;                                            \
+  p1##_type p1;                                            \
+  p2##_type p2;
+#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
+  p0##_type p0;                                                \
+  p1##_type p1;                                                \
+  p2##_type p2;                                                \
+  p3##_type p3;
+#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
+  p0##_type p0;                                                    \
+  p1##_type p1;                                                    \
+  p2##_type p2;                                                    \
+  p3##_type p3;                                                    \
+  p4##_type p4;
+#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
+  p0##_type p0;                                                        \
+  p1##_type p1;                                                        \
+  p2##_type p2;                                                        \
+  p3##_type p3;                                                        \
+  p4##_type p4;                                                        \
+  p5##_type p5;
+#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
+  p0##_type p0;                                                            \
+  p1##_type p1;                                                            \
+  p2##_type p2;                                                            \
+  p3##_type p3;                                                            \
+  p4##_type p4;                                                            \
+  p5##_type p5;                                                            \
+  p6##_type p6;
+#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
+  p0##_type p0;                                                                \
+  p1##_type p1;                                                                \
+  p2##_type p2;                                                                \
+  p3##_type p3;                                                                \
+  p4##_type p4;                                                                \
+  p5##_type p5;                                                                \
+  p6##_type p6;                                                                \
+  p7##_type p7;
+#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
+                                               p8)                             \
+  p0##_type p0;                                                                \
+  p1##_type p1;                                                                \
+  p2##_type p2;                                                                \
+  p3##_type p3;                                                                \
+  p4##_type p4;                                                                \
+  p5##_type p5;                                                                \
+  p6##_type p6;                                                                \
+  p7##_type p7;                                                                \
+  p8##_type p8;
+#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                p7, p8, p9)                 \
+  p0##_type p0;                                                             \
+  p1##_type p1;                                                             \
+  p2##_type p2;                                                             \
+  p3##_type p3;                                                             \
+  p4##_type p4;                                                             \
+  p5##_type p5;                                                             \
+  p6##_type p6;                                                             \
+  p7##_type p7;                                                             \
+  p8##_type p8;                                                             \
+  p9##_type p9;
+
+// Lists the value parameters.
+#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0
+#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1
+#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2
+#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3
+#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
+  p0, p1, p2, p3, p4
+#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
+  p0, p1, p2, p3, p4, p5
+#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
+  p0, p1, p2, p3, p4, p5, p6
+#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
+  p0, p1, p2, p3, p4, p5, p6, p7
+#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
+                                               p8)                             \
+  p0, p1, p2, p3, p4, p5, p6, p7, p8
+#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                p7, p8, p9)                 \
+  p0, p1, p2, p3, p4, p5, p6, p7, p8, p9
+
+// Lists the value parameter types.
+#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) \
+  , p0##_type, p1##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) \
+  , p0##_type, p1##_type, p2##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
+  , p0##_type, p1##_type, p2##_type, p3##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
+  , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
+  , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                    p6)                     \
+  , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, p6##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                    p6, p7)                 \
+  , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type,       \
+      p6##_type, p7##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                    p6, p7, p8)             \
+  , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type,       \
+      p6##_type, p7##_type, p8##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+                                                     p6, p7, p8, p9)         \
+  , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type,        \
+      p6##_type, p7##_type, p8##_type, p9##_type
+
+// Declares the value parameters.
+#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0
+#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) \
+  p0##_type p0, p1##_type p1
+#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) \
+  p0##_type p0, p1##_type p1, p2##_type p2
+#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3
+#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4
+#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)  \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+      p5##_type p5
+#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4,    \
+      p5##_type p5, p6##_type p6
+#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4,        \
+      p5##_type p5, p6##_type p6, p7##_type p7
+#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
+                                               p8)                             \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4,        \
+      p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8
+#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                p7, p8, p9)                 \
+  p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4,     \
+      p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, p9##_type p9
+
+// The suffix of the class template implementing the action template.
+#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P
+#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2
+#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3
+#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4
+#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5
+#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6
+#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7
+#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                p7)                         \
+  P8
+#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                p7, p8)                     \
+  P9
+#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+                                                 p7, p8, p9)                 \
+  P10
+
+// The name of the class template implementing the action template.
+#define GMOCK_ACTION_CLASS_(name, value_params) \
+  GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
+
+#define ACTION_TEMPLATE(name, template_params, value_params)                   \
+  template <GMOCK_INTERNAL_DECL_##template_params                              \
+                GMOCK_INTERNAL_DECL_TYPE_##value_params>                       \
+  class GMOCK_ACTION_CLASS_(name, value_params) {                              \
+   public:                                                                     \
+    explicit GMOCK_ACTION_CLASS_(name, value_params)(                          \
+        GMOCK_INTERNAL_DECL_##value_params)                                    \
+        GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params),    \
+                    = default;                                                 \
+                    ,                                                          \
+                    : impl_(std::make_shared<gmock_Impl>(                      \
+                        GMOCK_INTERNAL_LIST_##value_params)){})                \
+            GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
+                name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_      \
+        ##value_params                                                         \
+        GMOCK_ACTION_CLASS_(name, value_params)(GMOCK_ACTION_CLASS_(           \
+            name, value_params) &&) noexcept GMOCK_INTERNAL_DEFN_COPY_         \
+        ##value_params template <typename F>                                   \
+        operator ::testing::Action<F>() const {                                \
+      return GMOCK_PP_IF(                                                      \
+          GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params),              \
+          (::testing::internal::MakeAction<F, gmock_Impl>()),                  \
+          (::testing::internal::MakeAction<F>(impl_)));                        \
+    }                                                                          \
+                                                                               \
+   private:                                                                    \
+    class gmock_Impl {                                                         \
+     public:                                                                   \
+      explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}                \
+      template <typename function_type, typename return_type,                  \
+                typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>         \
+      return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;  \
+      GMOCK_INTERNAL_DEFN_##value_params                                       \
+    };                                                                         \
+    GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), ,      \
+                std::shared_ptr<const gmock_Impl> impl_;)                      \
+  };                                                                           \
+  template <GMOCK_INTERNAL_DECL_##template_params                              \
+                GMOCK_INTERNAL_DECL_TYPE_##value_params>                       \
+  GMOCK_ACTION_CLASS_(                                                         \
+      name, value_params)<GMOCK_INTERNAL_LIST_##template_params                \
+                              GMOCK_INTERNAL_LIST_TYPE_##value_params>         \
+      name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_;         \
+  template <GMOCK_INTERNAL_DECL_##template_params                              \
+                GMOCK_INTERNAL_DECL_TYPE_##value_params>                       \
+  inline GMOCK_ACTION_CLASS_(                                                  \
+      name, value_params)<GMOCK_INTERNAL_LIST_##template_params                \
+                              GMOCK_INTERNAL_LIST_TYPE_##value_params>         \
+  name(GMOCK_INTERNAL_DECL_##value_params) {                                   \
+    return GMOCK_ACTION_CLASS_(                                                \
+        name, value_params)<GMOCK_INTERNAL_LIST_##template_params              \
+                                GMOCK_INTERNAL_LIST_TYPE_##value_params>(      \
+        GMOCK_INTERNAL_LIST_##value_params);                                   \
+  }                                                                            \
+  template <GMOCK_INTERNAL_DECL_##template_params                              \
+                GMOCK_INTERNAL_DECL_TYPE_##value_params>                       \
+  template <typename function_type, typename return_type, typename args_type,  \
+            GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>                                 \
+  return_type GMOCK_ACTION_CLASS_(                                             \
+      name, value_params)<GMOCK_INTERNAL_LIST_##template_params                \
+                              GMOCK_INTERNAL_LIST_TYPE_##value_params>::       \
+      gmock_Impl::gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_)  \
+          const
+
+namespace testing {
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+
+namespace internal {
+
+// internal::InvokeArgument - a helper for InvokeArgument action.
+// The basic overloads are provided here for generic functors.
+// Overloads for other custom-callables are provided in the
+// internal/custom/gmock-generated-actions.h header.
+template <typename F, typename... Args>
+auto InvokeArgument(F &&f,
+                    Args... args) -> decltype(std::forward<F>(f)(args...)) {
+  return std::forward<F>(f)(args...);
+}
+
+template <std::size_t index, typename... Params>
+struct InvokeArgumentAction {
+  template <typename... Args,
+            typename = typename std::enable_if<(index < sizeof...(Args))>::type>
+  auto operator()(Args &&...args) const
+      -> decltype(internal::InvokeArgument(
+          std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
+          std::declval<const Params &>()...)) {
+    internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{},
+                                               std::forward<Args>(args)...);
+    return params.Apply([&](const Params &...unpacked_params) {
+      auto &&callable = std::move(args_tuple.template Get<index>());
+      return internal::InvokeArgument(
+          std::forward<decltype(callable)>(callable), unpacked_params...);
+    });
+  }
+
+  internal::FlatTuple<Params...> params;
+};
+
+}  // namespace internal
+
+// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
+// (0-based) argument, which must be a k-ary callable, of the mock
+// function, with arguments a1, a2, ..., a_k.
+//
+// Notes:
+//
+//   1. The arguments are passed by value by default.  If you need to
+//   pass an argument by reference, wrap it inside std::ref().  For
+//   example,
+//
+//     InvokeArgument<1>(5, string("Hello"), std::ref(foo))
+//
+//   passes 5 and string("Hello") by value, and passes foo by
+//   reference.
+//
+//   2. If the callable takes an argument by reference but std::ref() is
+//   not used, it will receive the reference to a copy of the value,
+//   instead of the original value.  For example, when the 0-th
+//   argument of the mock function takes a const string&, the action
+//
+//     InvokeArgument<0>(string("Hello"))
+//
+//   makes a copy of the temporary string("Hello") object and passes a
+//   reference of the copy, instead of the original temporary object,
+//   to the callable.  This makes it easy for a user to define an
+//   InvokeArgument action from temporary values and have it performed
+//   later.
+template <std::size_t index, typename... Params>
+internal::InvokeArgumentAction<index, typename std::decay<Params>::type...>
+InvokeArgument(Params &&...params) {
+  return {internal::FlatTuple<typename std::decay<Params>::type...>(
+      internal::FlatTupleConstructTag{}, std::forward<Params>(params)...)};
+}
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
+
+}  // namespace testing
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-more-matchers.h b/3rd-party/googletest/googlemock/include/gmock/gmock-more-matchers.h
new file mode 100644
index 0000000..54ea68b
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-more-matchers.h
@@ -0,0 +1,120 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some matchers that depend on gmock-matchers.h.
+//
+// Note that tests are implemented in gmock-matchers_test.cc rather than
+// gmock-more-matchers-test.cc.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_MATCHERS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_MATCHERS_H_
+
+#include <ostream>
+#include <string>
+
+#include "gmock/gmock-matchers.h"
+
+namespace testing {
+
+// Silence C4100 (unreferenced formal
+// parameter) for MSVC
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+// and silence C4800 (C4800: 'int *const ': forcing value
+// to bool 'true' or 'false') for MSVC 14
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800)
+#endif
+
+namespace internal {
+
+// Implements the polymorphic IsEmpty matcher, which
+// can be used as a Matcher<T> as long as T is either a container that defines
+// empty() and size() (e.g. std::vector or std::string), or a C-style string.
+class IsEmptyMatcher {
+ public:
+  // Matches anything that defines empty() and size().
+  template <typename MatcheeContainerType>
+  bool MatchAndExplain(const MatcheeContainerType& c,
+                       MatchResultListener* listener) const {
+    if (c.empty()) {
+      return true;
+    }
+    *listener << "whose size is " << c.size();
+    return false;
+  }
+
+  // Matches C-style strings.
+  bool MatchAndExplain(const char* s, MatchResultListener* listener) const {
+    return MatchAndExplain(std::string(s), listener);
+  }
+
+  // Describes what this matcher matches.
+  void DescribeTo(std::ostream* os) const { *os << "is empty"; }
+
+  void DescribeNegationTo(std::ostream* os) const { *os << "isn't empty"; }
+};
+
+}  // namespace internal
+
+// Creates a polymorphic matcher that matches an empty container or C-style
+// string. The container must support both size() and empty(), which all
+// STL-like containers provide.
+inline PolymorphicMatcher<internal::IsEmptyMatcher> IsEmpty() {
+  return MakePolymorphicMatcher(internal::IsEmptyMatcher());
+}
+
+// Define a matcher that matches a value that evaluates in boolean
+// context to true.  Useful for types that define "explicit operator
+// bool" operators and so can't be compared for equality with true
+// and false.
+MATCHER(IsTrue, negation ? "is false" : "is true") {
+  return static_cast<bool>(arg);
+}
+
+// Define a matcher that matches a value that evaluates in boolean
+// context to false.  Useful for types that define "explicit operator
+// bool" operators and so can't be compared for equality with true
+// and false.
+MATCHER(IsFalse, negation ? "is true" : "is false") {
+  return !static_cast<bool>(arg);
+}
+
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4800
+#endif
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
+
+}  // namespace testing
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_MATCHERS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-nice-strict.h b/3rd-party/googletest/googlemock/include/gmock/gmock-nice-strict.h
new file mode 100644
index 0000000..056d471
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-nice-strict.h
@@ -0,0 +1,277 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Implements class templates NiceMock, NaggyMock, and StrictMock.
+//
+// Given a mock class MockFoo that is created using Google Mock,
+// NiceMock<MockFoo> is a subclass of MockFoo that allows
+// uninteresting calls (i.e. calls to mock methods that have no
+// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo
+// that prints a warning when an uninteresting call occurs, and
+// StrictMock<MockFoo> is a subclass of MockFoo that treats all
+// uninteresting calls as errors.
+//
+// Currently a mock is naggy by default, so MockFoo and
+// NaggyMock<MockFoo> behave like the same.  However, we will soon
+// switch the default behavior of mocks to be nice, as that in general
+// leads to more maintainable tests.  When that happens, MockFoo will
+// stop behaving like NaggyMock<MockFoo> and start behaving like
+// NiceMock<MockFoo>.
+//
+// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
+// their respective base class.  Therefore you can write
+// NiceMock<MockFoo>(5, "a") to construct a nice mock where MockFoo
+// has a constructor that accepts (int, const char*), for example.
+//
+// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
+// and StrictMock<MockFoo> only works for mock methods defined using
+// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.
+// If a mock method is defined in a base class of MockFoo, the "nice"
+// or "strict" modifier may not affect it, depending on the compiler.
+// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
+// supported.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
+
+#include <cstdint>
+#include <type_traits>
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+template <class MockClass>
+class NiceMock;
+template <class MockClass>
+class NaggyMock;
+template <class MockClass>
+class StrictMock;
+
+namespace internal {
+template <typename T>
+std::true_type StrictnessModifierProbe(const NiceMock<T>&);
+template <typename T>
+std::true_type StrictnessModifierProbe(const NaggyMock<T>&);
+template <typename T>
+std::true_type StrictnessModifierProbe(const StrictMock<T>&);
+std::false_type StrictnessModifierProbe(...);
+
+template <typename T>
+constexpr bool HasStrictnessModifier() {
+  return decltype(StrictnessModifierProbe(std::declval<const T&>()))::value;
+}
+
+// Base classes that register and deregister with testing::Mock to alter the
+// default behavior around uninteresting calls. Inheriting from one of these
+// classes first and then MockClass ensures the MockClass constructor is run
+// after registration, and that the MockClass destructor runs before
+// deregistration. This guarantees that MockClass's constructor and destructor
+// run with the same level of strictness as its instance methods.
+
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW) && \
+    (defined(_MSC_VER) || defined(__clang__))
+// We need to mark these classes with this declspec to ensure that
+// the empty base class optimization is performed.
+#define GTEST_INTERNAL_EMPTY_BASE_CLASS __declspec(empty_bases)
+#else
+#define GTEST_INTERNAL_EMPTY_BASE_CLASS
+#endif
+
+template <typename Base>
+class NiceMockImpl {
+ public:
+  NiceMockImpl() {
+    ::testing::Mock::AllowUninterestingCalls(reinterpret_cast<uintptr_t>(this));
+  }
+
+  ~NiceMockImpl() {
+    ::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));
+  }
+};
+
+template <typename Base>
+class NaggyMockImpl {
+ public:
+  NaggyMockImpl() {
+    ::testing::Mock::WarnUninterestingCalls(reinterpret_cast<uintptr_t>(this));
+  }
+
+  ~NaggyMockImpl() {
+    ::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));
+  }
+};
+
+template <typename Base>
+class StrictMockImpl {
+ public:
+  StrictMockImpl() {
+    ::testing::Mock::FailUninterestingCalls(reinterpret_cast<uintptr_t>(this));
+  }
+
+  ~StrictMockImpl() {
+    ::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));
+  }
+};
+
+}  // namespace internal
+
+template <class MockClass>
+class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
+    : private internal::NiceMockImpl<MockClass>,
+      public MockClass {
+ public:
+  static_assert(!internal::HasStrictnessModifier<MockClass>(),
+                "Can't apply NiceMock to a class hierarchy that already has a "
+                "strictness modifier. See "
+                "https://google.github.io/googletest/"
+                "gmock_cook_book.html#NiceStrictNaggy");
+  NiceMock() : MockClass() {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+  // Ideally, we would inherit base class's constructors through a using
+  // declaration, which would preserve their visibility. However, many existing
+  // tests rely on the fact that current implementation reexports protected
+  // constructors as public. These tests would need to be cleaned up first.
+
+  // Single argument constructor is special-cased so that it can be
+  // made explicit.
+  template <typename A>
+  explicit NiceMock(A&& arg) : MockClass(std::forward<A>(arg)) {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+  template <typename TArg1, typename TArg2, typename... An>
+  NiceMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
+      : MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
+                  std::forward<An>(args)...) {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+ private:
+  NiceMock(const NiceMock&) = delete;
+  NiceMock& operator=(const NiceMock&) = delete;
+};
+
+template <class MockClass>
+class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
+    : private internal::NaggyMockImpl<MockClass>,
+      public MockClass {
+  static_assert(!internal::HasStrictnessModifier<MockClass>(),
+                "Can't apply NaggyMock to a class hierarchy that already has a "
+                "strictness modifier. See "
+                "https://google.github.io/googletest/"
+                "gmock_cook_book.html#NiceStrictNaggy");
+
+ public:
+  NaggyMock() : MockClass() {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+  // Ideally, we would inherit base class's constructors through a using
+  // declaration, which would preserve their visibility. However, many existing
+  // tests rely on the fact that current implementation reexports protected
+  // constructors as public. These tests would need to be cleaned up first.
+
+  // Single argument constructor is special-cased so that it can be
+  // made explicit.
+  template <typename A>
+  explicit NaggyMock(A&& arg) : MockClass(std::forward<A>(arg)) {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+  template <typename TArg1, typename TArg2, typename... An>
+  NaggyMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
+      : MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
+                  std::forward<An>(args)...) {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+ private:
+  NaggyMock(const NaggyMock&) = delete;
+  NaggyMock& operator=(const NaggyMock&) = delete;
+};
+
+template <class MockClass>
+class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
+    : private internal::StrictMockImpl<MockClass>,
+      public MockClass {
+ public:
+  static_assert(
+      !internal::HasStrictnessModifier<MockClass>(),
+      "Can't apply StrictMock to a class hierarchy that already has a "
+      "strictness modifier. See "
+      "https://google.github.io/googletest/"
+      "gmock_cook_book.html#NiceStrictNaggy");
+  StrictMock() : MockClass() {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+  // Ideally, we would inherit base class's constructors through a using
+  // declaration, which would preserve their visibility. However, many existing
+  // tests rely on the fact that current implementation reexports protected
+  // constructors as public. These tests would need to be cleaned up first.
+
+  // Single argument constructor is special-cased so that it can be
+  // made explicit.
+  template <typename A>
+  explicit StrictMock(A&& arg) : MockClass(std::forward<A>(arg)) {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+  template <typename TArg1, typename TArg2, typename... An>
+  StrictMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
+      : MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
+                  std::forward<An>(args)...) {
+    static_assert(sizeof(*this) == sizeof(MockClass),
+                  "The impl subclass shouldn't introduce any padding");
+  }
+
+ private:
+  StrictMock(const StrictMock&) = delete;
+  StrictMock& operator=(const StrictMock&) = delete;
+};
+
+#undef GTEST_INTERNAL_EMPTY_BASE_CLASS
+
+}  // namespace testing
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock-spec-builders.h b/3rd-party/googletest/googlemock/include/gmock/gmock-spec-builders.h
new file mode 100644
index 0000000..c4c42b7
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock-spec-builders.h
@@ -0,0 +1,2146 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the ON_CALL() and EXPECT_CALL() macros.
+//
+// A user can use the ON_CALL() macro to specify the default action of
+// a mock method.  The syntax is:
+//
+//   ON_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matcher)
+//       .WillByDefault(action);
+//
+//  where the .With() clause is optional.
+//
+// A user can use the EXPECT_CALL() macro to specify an expectation on
+// a mock method.  The syntax is:
+//
+//   EXPECT_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matchers)
+//       .Times(cardinality)
+//       .InSequence(sequences)
+//       .After(expectations)
+//       .WillOnce(action)
+//       .WillRepeatedly(action)
+//       .RetiresOnSaturation();
+//
+// where all clauses are optional, and .InSequence()/.After()/
+// .WillOnce() can appear any number of times.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_EXCEPTIONS
+#include <stdexcept>  // NOLINT
+#endif
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// An abstract handle of an expectation.
+class Expectation;
+
+// A set of expectation handles.
+class ExpectationSet;
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// Implements a mock function.
+template <typename F>
+class FunctionMocker;
+
+// Base class for expectations.
+class ExpectationBase;
+
+// Implements an expectation.
+template <typename F>
+class TypedExpectation;
+
+// Helper class for testing the Expectation class template.
+class ExpectationTester;
+
+// Helper classes for implementing NiceMock, StrictMock, and NaggyMock.
+template <typename MockClass>
+class NiceMockImpl;
+template <typename MockClass>
+class StrictMockImpl;
+template <typename MockClass>
+class NaggyMockImpl;
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+//
+// The reason we don't use more fine-grained protection is: when a
+// mock function Foo() is called, it needs to consult its expectations
+// to see which one should be picked.  If another thread is allowed to
+// call a mock function (either Foo() or a different one) at the same
+// time, it could affect the "retired" attributes of Foo()'s
+// expectations when InSequence() is used, and thus affect which
+// expectation gets picked.  Therefore, we sequence all mock function
+// calls to ensure the integrity of the mock objects' states.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Abstract base class of FunctionMocker.  This is the
+// type-agnostic part of the function mocker interface.  Its pure
+// virtual methods are implemented by FunctionMocker.
+class GTEST_API_ UntypedFunctionMockerBase {
+ public:
+  UntypedFunctionMockerBase();
+  virtual ~UntypedFunctionMockerBase();
+
+  // Verifies that all expectations on this mock function have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  bool VerifyAndClearExpectationsLocked()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Clears the ON_CALL()s set on this mock function.
+  virtual void ClearDefaultActionsLocked()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) = 0;
+
+  // In all of the following Untyped* functions, it's the caller's
+  // responsibility to guarantee the correctness of the arguments'
+  // types.
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0;
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args, const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why)
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0;
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const = 0;
+
+  // Sets the mock object this mock method belongs to, and registers
+  // this information in the global mock registry.  Will be called
+  // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+  // method.
+  void RegisterOwner(const void* mock_obj) GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Sets the mock object this mock method belongs to, and sets the
+  // name of the mock function.  Will be called upon each invocation
+  // of this mock function.
+  void SetOwnerAndName(const void* mock_obj, const char* name)
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Returns the mock object this mock method belongs to.  Must be
+  // called after RegisterOwner() or SetOwnerAndName() has been
+  // called.
+  const void* MockObject() const GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Returns the name of this mock method.  Must be called after
+  // SetOwnerAndName() has been called.
+  const char* Name() const GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+ protected:
+  typedef std::vector<const void*> UntypedOnCallSpecs;
+
+  using UntypedExpectations = std::vector<std::shared_ptr<ExpectationBase>>;
+
+  struct UninterestingCallCleanupHandler;
+  struct FailureCleanupHandler;
+
+  // Returns an Expectation object that references and co-owns exp,
+  // which must be an expectation on this mock function.
+  Expectation GetHandleOf(ExpectationBase* exp);
+
+  // Address of the mock object this mock method belongs to.  Only
+  // valid after this mock method has been called or
+  // ON_CALL/EXPECT_CALL has been invoked on it.
+  const void* mock_obj_;  // Protected by g_gmock_mutex.
+
+  // Name of the function being mocked.  Only valid after this mock
+  // method has been called.
+  const char* name_;  // Protected by g_gmock_mutex.
+
+  // All default action specs for this function mocker.
+  UntypedOnCallSpecs untyped_on_call_specs_;
+
+  // All expectations for this function mocker.
+  //
+  // It's undefined behavior to interleave expectations (EXPECT_CALLs
+  // or ON_CALLs) and mock function calls.  Also, the order of
+  // expectations is important.  Therefore it's a logic race condition
+  // to read/write untyped_expectations_ concurrently.  In order for
+  // tools like tsan to catch concurrent read/write accesses to
+  // untyped_expectations, we deliberately leave accesses to it
+  // unprotected.
+  UntypedExpectations untyped_expectations_;
+};  // class UntypedFunctionMockerBase
+
+// Untyped base class for OnCallSpec<F>.
+class UntypedOnCallSpecBase {
+ public:
+  // The arguments are the location of the ON_CALL() statement.
+  UntypedOnCallSpecBase(const char* a_file, int a_line)
+      : file_(a_file), line_(a_line), last_clause_(kNone) {}
+
+  // Where in the source file was the default action spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+
+ protected:
+  // Gives each clause in the ON_CALL() statement a name.
+  enum Clause {
+    // Do not change the order of the enum members!  The run-time
+    // syntax checking relies on it.
+    kNone,
+    kWith,
+    kWillByDefault
+  };
+
+  // Asserts that the ON_CALL() statement has a certain property.
+  void AssertSpecProperty(bool property,
+                          const std::string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the ON_CALL() statement has a certain property.
+  void ExpectSpecProperty(bool property,
+                          const std::string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  const char* file_;
+  int line_;
+
+  // The last clause in the ON_CALL() statement as seen so far.
+  // Initially kNone and changes as the statement is parsed.
+  Clause last_clause_;
+};  // class UntypedOnCallSpecBase
+
+// This template class implements an ON_CALL spec.
+template <typename F>
+class OnCallSpec : public UntypedOnCallSpecBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  // Constructs an OnCallSpec object from the information inside
+  // the parenthesis of an ON_CALL() statement.
+  OnCallSpec(const char* a_file, int a_line,
+             const ArgumentMatcherTuple& matchers)
+      : UntypedOnCallSpecBase(a_file, a_line),
+        matchers_(matchers),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that causes ambiguity between
+        // Matcher's copy and move constructor for some argument types.
+        extra_matcher_(A<const ArgumentTuple&>()) {}
+
+  // Implements the .With() clause.
+  OnCallSpec& With(const Matcher<const ArgumentTuple&>& m) {
+    // Makes sure this is called at most once.
+    ExpectSpecProperty(last_clause_ < kWith,
+                       ".With() cannot appear "
+                       "more than once in an ON_CALL().");
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    return *this;
+  }
+
+  // Implements the .WillByDefault() clause.
+  OnCallSpec& WillByDefault(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ < kWillByDefault,
+                       ".WillByDefault() must appear "
+                       "exactly once in an ON_CALL().");
+    last_clause_ = kWillByDefault;
+
+    ExpectSpecProperty(!action.IsDoDefault(),
+                       "DoDefault() cannot be used in ON_CALL().");
+    action_ = action;
+    return *this;
+  }
+
+  // Returns true if and only if the given arguments match the matchers.
+  bool Matches(const ArgumentTuple& args) const {
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns the action specified by the user.
+  const Action<F>& GetAction() const {
+    AssertSpecProperty(last_clause_ == kWillByDefault,
+                       ".WillByDefault() must appear exactly "
+                       "once in an ON_CALL().");
+    return action_;
+  }
+
+ private:
+  // The information in statement
+  //
+  //   ON_CALL(mock_object, Method(matchers))
+  //       .With(multi-argument-matcher)
+  //       .WillByDefault(action);
+  //
+  // is recorded in the data members like this:
+  //
+  //   source file that contains the statement => file_
+  //   line number of the statement            => line_
+  //   matchers                                => matchers_
+  //   multi-argument-matcher                  => extra_matcher_
+  //   action                                  => action_
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> action_;
+};  // class OnCallSpec
+
+// Possible reactions on uninteresting calls.
+enum CallReaction {
+  kAllow,
+  kWarn,
+  kFail,
+};
+
+}  // namespace internal
+
+// Utilities for manipulating mock objects.
+class GTEST_API_ Mock {
+ public:
+  // The following public methods can be called concurrently.
+
+  // Tells Google Mock to ignore mock_obj when checking for leaked
+  // mock objects.
+  static void AllowLeak(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Verifies and clears all expectations on the given mock object.
+  // If the expectations aren't satisfied, generates one or more
+  // Google Test non-fatal failures and returns false.
+  static bool VerifyAndClearExpectations(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Verifies all expectations on the given mock object and clears its
+  // default actions and expectations.  Returns true if and only if the
+  // verification was successful.
+  static bool VerifyAndClear(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Returns whether the mock was created as a naggy mock (default)
+  static bool IsNaggy(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+  // Returns whether the mock was created as a nice mock
+  static bool IsNice(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+  // Returns whether the mock was created as a strict mock
+  static bool IsStrict(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+ private:
+  friend class internal::UntypedFunctionMockerBase;
+
+  // Needed for a function mocker to register itself (so that we know
+  // how to clear a mock object).
+  template <typename F>
+  friend class internal::FunctionMocker;
+
+  template <typename MockClass>
+  friend class internal::NiceMockImpl;
+  template <typename MockClass>
+  friend class internal::NaggyMockImpl;
+  template <typename MockClass>
+  friend class internal::StrictMockImpl;
+
+  // Tells Google Mock to allow uninteresting calls on the given mock
+  // object.
+  static void AllowUninterestingCalls(uintptr_t mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock to warn the user about uninteresting calls on
+  // the given mock object.
+  static void WarnUninterestingCalls(uintptr_t mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock to fail uninteresting calls on the given mock
+  // object.
+  static void FailUninterestingCalls(uintptr_t mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock the given mock object is being destroyed and
+  // its entry in the call-reaction table should be removed.
+  static void UnregisterCallReaction(uintptr_t mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Returns the reaction Google Mock will have on uninteresting calls
+  // made on the given mock object.
+  static internal::CallReaction GetReactionOnUninterestingCalls(
+      const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Verifies that all expectations on the given mock object have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  static bool VerifyAndClearExpectationsLocked(void* mock_obj)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
+
+  // Clears all ON_CALL()s set on the given mock object.
+  static void ClearDefaultActionsLocked(void* mock_obj)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
+
+  // Registers a mock object and a mock method it owns.
+  static void Register(const void* mock_obj,
+                       internal::UntypedFunctionMockerBase* mocker)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock where in the source code mock_obj is used in an
+  // ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+  // information helps the user identify which object it is.
+  static void RegisterUseByOnCallOrExpectCall(const void* mock_obj,
+                                              const char* file, int line)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Unregisters a mock method; removes the owning mock object from
+  // the registry when the last mock method associated with it has
+  // been unregistered.  This is called only in the destructor of
+  // FunctionMocker.
+  static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
+};  // class Mock
+
+// An abstract handle of an expectation.  Useful in the .After()
+// clause of EXPECT_CALL() for setting the (partial) order of
+// expectations.  The syntax:
+//
+//   Expectation e1 = EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(e1)...;
+//
+// sets two expectations where the latter can only be matched after
+// the former has been satisfied.
+//
+// Notes:
+//   - This class is copyable and has value semantics.
+//   - Constness is shallow: a const Expectation object itself cannot
+//     be modified, but the mutable methods of the ExpectationBase
+//     object it references can be called via expectation_base().
+
+class GTEST_API_ Expectation {
+ public:
+  // Constructs a null object that doesn't reference any expectation.
+  Expectation();
+  Expectation(Expectation&&) = default;
+  Expectation(const Expectation&) = default;
+  Expectation& operator=(Expectation&&) = default;
+  Expectation& operator=(const Expectation&) = default;
+  ~Expectation();
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   Expectation e = EXPECT_CALL(...);
+  // syntax.
+  //
+  // A TypedExpectation object stores its pre-requisites as
+  // Expectation objects, and needs to call the non-const Retire()
+  // method on the ExpectationBase objects they reference.  Therefore
+  // Expectation must receive a *non-const* reference to the
+  // ExpectationBase object.
+  Expectation(internal::ExpectationBase& exp);  // NOLINT
+
+  // The compiler-generated copy ctor and operator= work exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true if and only if rhs references the same expectation as this
+  // object does.
+  bool operator==(const Expectation& rhs) const {
+    return expectation_base_ == rhs.expectation_base_;
+  }
+
+  bool operator!=(const Expectation& rhs) const { return !(*this == rhs); }
+
+ private:
+  friend class ExpectationSet;
+  friend class Sequence;
+  friend class ::testing::internal::ExpectationBase;
+  friend class ::testing::internal::UntypedFunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::FunctionMocker;
+
+  template <typename F>
+  friend class ::testing::internal::TypedExpectation;
+
+  // This comparator is needed for putting Expectation objects into a set.
+  class Less {
+   public:
+    bool operator()(const Expectation& lhs, const Expectation& rhs) const {
+      return lhs.expectation_base_.get() < rhs.expectation_base_.get();
+    }
+  };
+
+  typedef ::std::set<Expectation, Less> Set;
+
+  Expectation(
+      const std::shared_ptr<internal::ExpectationBase>& expectation_base);
+
+  // Returns the expectation this object references.
+  const std::shared_ptr<internal::ExpectationBase>& expectation_base() const {
+    return expectation_base_;
+  }
+
+  // A shared_ptr that co-owns the expectation this handle references.
+  std::shared_ptr<internal::ExpectationBase> expectation_base_;
+};
+
+// A set of expectation handles.  Useful in the .After() clause of
+// EXPECT_CALL() for setting the (partial) order of expectations.  The
+// syntax:
+//
+//   ExpectationSet es;
+//   es += EXPECT_CALL(...)...;
+//   es += EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(es)...;
+//
+// sets three expectations where the last one can only be matched
+// after the first two have both been satisfied.
+//
+// This class is copyable and has value semantics.
+class ExpectationSet {
+ public:
+  // A bidirectional iterator that can read a const element in the set.
+  typedef Expectation::Set::const_iterator const_iterator;
+
+  // An object stored in the set.  This is an alias of Expectation.
+  typedef Expectation::Set::value_type value_type;
+
+  // Constructs an empty set.
+  ExpectationSet() = default;
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   ExpectationSet es = EXPECT_CALL(...);
+  // syntax.
+  ExpectationSet(internal::ExpectationBase& exp) {  // NOLINT
+    *this += Expectation(exp);
+  }
+
+  // This single-argument ctor implements implicit conversion from
+  // Expectation and thus must not be explicit.  This allows either an
+  // Expectation or an ExpectationSet to be used in .After().
+  ExpectationSet(const Expectation& e) {  // NOLINT
+    *this += e;
+  }
+
+  // The compiler-generator ctor and operator= works exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true if and only if rhs contains the same set of Expectation
+  // objects as this does.
+  bool operator==(const ExpectationSet& rhs) const {
+    return expectations_ == rhs.expectations_;
+  }
+
+  bool operator!=(const ExpectationSet& rhs) const { return !(*this == rhs); }
+
+  // Implements the syntax
+  //   expectation_set += EXPECT_CALL(...);
+  ExpectationSet& operator+=(const Expectation& e) {
+    expectations_.insert(e);
+    return *this;
+  }
+
+  int size() const { return static_cast<int>(expectations_.size()); }
+
+  const_iterator begin() const { return expectations_.begin(); }
+  const_iterator end() const { return expectations_.end(); }
+
+ private:
+  Expectation::Set expectations_;
+};
+
+// Sequence objects are used by a user to specify the relative order
+// in which the expectations should match.  They are copyable (we rely
+// on the compiler-defined copy constructor and assignment operator).
+class GTEST_API_ Sequence {
+ public:
+  // Constructs an empty sequence.
+  Sequence() : last_expectation_(new Expectation) {}
+
+  // Adds an expectation to this sequence.  The caller must ensure
+  // that no other thread is accessing this Sequence object.
+  void AddExpectation(const Expectation& expectation) const;
+
+ private:
+  // The last expectation in this sequence.
+  std::shared_ptr<Expectation> last_expectation_;
+};  // class Sequence
+
+// An object of this type causes all EXPECT_CALL() statements
+// encountered in its scope to be put in an anonymous sequence.  The
+// work is done in the constructor and destructor.  You should only
+// create an InSequence object on the stack.
+//
+// The sole purpose for this class is to support easy definition of
+// sequential expectations, e.g.
+//
+//   {
+//     InSequence dummy;  // The name of the object doesn't matter.
+//
+//     // The following expectations must match in the order they appear.
+//     EXPECT_CALL(a, Bar())...;
+//     EXPECT_CALL(a, Baz())...;
+//     ...
+//     EXPECT_CALL(b, Xyz())...;
+//   }
+//
+// You can create InSequence objects in multiple threads, as long as
+// they are used to affect different mock objects.  The idea is that
+// each thread can create and set up its own mocks as if it's the only
+// thread.  However, for clarity of your tests we recommend you to set
+// up mocks in the main thread unless you have a good reason not to do
+// so.
+class GTEST_API_ InSequence {
+ public:
+  InSequence();
+  ~InSequence();
+
+ private:
+  bool sequence_created_;
+
+  InSequence(const InSequence&) = delete;
+  InSequence& operator=(const InSequence&) = delete;
+};
+
+namespace internal {
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+GTEST_API_ extern ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Base class for implementing expectations.
+//
+// There are two reasons for having a type-agnostic base class for
+// Expectation:
+//
+//   1. We need to store collections of expectations of different
+//   types (e.g. all pre-requisites of a particular expectation, all
+//   expectations in a sequence).  Therefore these expectation objects
+//   must share a common base class.
+//
+//   2. We can avoid binary code bloat by moving methods not depending
+//   on the template argument of Expectation to the base class.
+//
+// This class is internal and mustn't be used by user code directly.
+class GTEST_API_ ExpectationBase {
+ public:
+  // source_text is the EXPECT_CALL(...) source that created this Expectation.
+  ExpectationBase(const char* file, int line, const std::string& source_text);
+
+  virtual ~ExpectationBase();
+
+  // Where in the source file was the expectation spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+  const char* source_text() const { return source_text_.c_str(); }
+  // Returns the cardinality specified in the expectation spec.
+  const Cardinality& cardinality() const { return cardinality_; }
+
+  // Describes the source file location of this expectation.
+  void DescribeLocationTo(::std::ostream* os) const {
+    *os << FormatFileLocation(file(), line()) << " ";
+  }
+
+  // Describes how many times a function call matching this
+  // expectation has occurred.
+  void DescribeCallCountTo(::std::ostream* os) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0;
+
+  // Do not rely on this for correctness.
+  // This is only for making human-readable test output easier to understand.
+  void UntypedDescription(std::string description) {
+    description_ = std::move(description);
+  }
+
+ protected:
+  friend class ::testing::Expectation;
+  friend class UntypedFunctionMockerBase;
+
+  enum Clause {
+    // Don't change the order of the enum members!
+    kNone,
+    kWith,
+    kTimes,
+    kInSequence,
+    kAfter,
+    kWillOnce,
+    kWillRepeatedly,
+    kRetiresOnSaturation
+  };
+
+  typedef std::vector<const void*> UntypedActions;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() = 0;
+
+  // Asserts that the EXPECT_CALL() statement has the given property.
+  void AssertSpecProperty(bool property,
+                          const std::string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the EXPECT_CALL() statement has the given property.
+  void ExpectSpecProperty(bool property,
+                          const std::string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  // Explicitly specifies the cardinality of this expectation.  Used
+  // by the subclasses to implement the .Times() clause.
+  void SpecifyCardinality(const Cardinality& cardinality);
+
+  // Returns true if and only if the user specified the cardinality
+  // explicitly using a .Times().
+  bool cardinality_specified() const { return cardinality_specified_; }
+
+  // Sets the cardinality of this expectation spec.
+  void set_cardinality(const Cardinality& a_cardinality) {
+    cardinality_ = a_cardinality;
+  }
+
+  // The following group of methods should only be called after the
+  // EXPECT_CALL() statement, and only when g_gmock_mutex is held by
+  // the current thread.
+
+  // Retires all pre-requisites of this expectation.
+  void RetireAllPreRequisites() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Returns true if and only if this expectation is retired.
+  bool is_retired() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return retired_;
+  }
+
+  // Retires this expectation.
+  void Retire() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    retired_ = true;
+  }
+
+  // Returns a human-readable description of this expectation.
+  // Do not rely on this for correctness. It is only for human readability.
+  const std::string& GetDescription() const { return description_; }
+
+  // Returns true if and only if this expectation is satisfied.
+  bool IsSatisfied() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSatisfiedByCallCount(call_count_);
+  }
+
+  // Returns true if and only if this expectation is saturated.
+  bool IsSaturated() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true if and only if this expectation is over-saturated.
+  bool IsOverSaturated() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsOverSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true if and only if all pre-requisites of this expectation are
+  // satisfied.
+  bool AllPrerequisitesAreSatisfied() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Adds unsatisfied pre-requisites of this expectation to 'result'.
+  void FindUnsatisfiedPrerequisites(ExpectationSet* result) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Returns the number this expectation has been invoked.
+  int call_count() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return call_count_;
+  }
+
+  // Increments the number this expectation has been invoked.
+  void IncrementCallCount() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    call_count_++;
+  }
+
+  // Checks the action count (i.e. the number of WillOnce() and
+  // WillRepeatedly() clauses) against the cardinality if this hasn't
+  // been done before.  Prints a warning if there are too many or too
+  // few actions.
+  void CheckActionCountIfNotDone() const GTEST_LOCK_EXCLUDED_(mutex_);
+
+  friend class ::testing::Sequence;
+  friend class ::testing::internal::ExpectationTester;
+
+  template <typename Function>
+  friend class TypedExpectation;
+
+  // Implements the .Times() clause.
+  void UntypedTimes(const Cardinality& a_cardinality);
+
+  // This group of fields are part of the spec and won't change after
+  // an EXPECT_CALL() statement finishes.
+  const char* file_;               // The file that contains the expectation.
+  int line_;                       // The line number of the expectation.
+  const std::string source_text_;  // The EXPECT_CALL(...) source text.
+  std::string description_;        // User-readable name for the expectation.
+  // True if and only if the cardinality is specified explicitly.
+  bool cardinality_specified_;
+  Cardinality cardinality_;  // The cardinality of the expectation.
+  // The immediate pre-requisites (i.e. expectations that must be
+  // satisfied before this expectation can be matched) of this
+  // expectation.  We use std::shared_ptr in the set because we want an
+  // Expectation object to be co-owned by its FunctionMocker and its
+  // successors.  This allows multiple mock objects to be deleted at
+  // different times.
+  ExpectationSet immediate_prerequisites_;
+
+  // This group of fields are the current state of the expectation,
+  // and can change as the mock function is called.
+  int call_count_;  // How many times this expectation has been invoked.
+  bool retired_;    // True if and only if this expectation has retired.
+  UntypedActions untyped_actions_;
+  bool extra_matcher_specified_;
+  bool repeated_action_specified_;  // True if a WillRepeatedly() was specified.
+  bool retires_on_saturation_;
+  Clause last_clause_;
+  mutable bool action_count_checked_;  // Under mutex_.
+  mutable Mutex mutex_;                // Protects action_count_checked_.
+};  // class ExpectationBase
+
+template <typename F>
+class TypedExpectation;
+
+// Implements an expectation for the given function type.
+template <typename R, typename... Args>
+class TypedExpectation<R(Args...)> : public ExpectationBase {
+ private:
+  using F = R(Args...);
+
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+  typedef typename Function<F>::Result Result;
+
+  TypedExpectation(FunctionMocker<F>* owner, const char* a_file, int a_line,
+                   const std::string& a_source_text,
+                   const ArgumentMatcherTuple& m)
+      : ExpectationBase(a_file, a_line, a_source_text),
+        owner_(owner),
+        matchers_(m),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that causes ambiguity between
+        // Matcher's copy and move constructor for some argument types.
+        extra_matcher_(A<const ArgumentTuple&>()),
+        repeated_action_(DoDefault()) {}
+
+  ~TypedExpectation() override {
+    // Check the validity of the action count if it hasn't been done
+    // yet (for example, if the expectation was never used).
+    CheckActionCountIfNotDone();
+    for (UntypedActions::const_iterator it = untyped_actions_.begin();
+         it != untyped_actions_.end(); ++it) {
+      delete static_cast<const Action<F>*>(*it);
+    }
+  }
+
+  // Implements the .With() clause.
+  TypedExpectation& With(const Matcher<const ArgumentTuple&>& m) {
+    if (last_clause_ == kWith) {
+      ExpectSpecProperty(false,
+                         ".With() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWith,
+                         ".With() must be the first "
+                         "clause in an EXPECT_CALL().");
+    }
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    extra_matcher_specified_ = true;
+    return *this;
+  }
+
+  // Do not rely on this for correctness.
+  // This is only for making human-readable test output easier to understand.
+  TypedExpectation& Description(std::string name) {
+    ExpectationBase::UntypedDescription(std::move(name));
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(const Cardinality& a_cardinality) {
+    ExpectationBase::UntypedTimes(a_cardinality);
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(int n) { return Times(Exactly(n)); }
+
+  // Implements the .InSequence() clause.
+  TypedExpectation& InSequence(const Sequence& s) {
+    ExpectSpecProperty(last_clause_ <= kInSequence,
+                       ".InSequence() cannot appear after .After(),"
+                       " .WillOnce(), .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kInSequence;
+
+    s.AddExpectation(GetHandle());
+    return *this;
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2) {
+    return InSequence(s1).InSequence(s2);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3) {
+    return InSequence(s1, s2).InSequence(s3);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4) {
+    return InSequence(s1, s2, s3).InSequence(s4);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4,
+                               const Sequence& s5) {
+    return InSequence(s1, s2, s3, s4).InSequence(s5);
+  }
+
+  // Implements that .After() clause.
+  TypedExpectation& After(const ExpectationSet& s) {
+    ExpectSpecProperty(last_clause_ <= kAfter,
+                       ".After() cannot appear after .WillOnce(),"
+                       " .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kAfter;
+
+    for (ExpectationSet::const_iterator it = s.begin(); it != s.end(); ++it) {
+      immediate_prerequisites_ += *it;
+    }
+    return *this;
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2) {
+    return After(s1).After(s2);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3) {
+    return After(s1, s2).After(s3);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4) {
+    return After(s1, s2, s3).After(s4);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4,
+                          const ExpectationSet& s5) {
+    return After(s1, s2, s3, s4).After(s5);
+  }
+
+  // Preferred, type-safe overload: consume anything that can be directly
+  // converted to a OnceAction, except for Action<F> objects themselves.
+  TypedExpectation& WillOnce(OnceAction<F> once_action) {
+    // Call the overload below, smuggling the OnceAction as a copyable callable.
+    // We know this is safe because a WillOnce action will not be called more
+    // than once.
+    return WillOnce(Action<F>(ActionAdaptor{
+        std::make_shared<OnceAction<F>>(std::move(once_action)),
+    }));
+  }
+
+  // Fallback overload: accept Action<F> objects and those actions that define
+  // `operator Action<F>` but not `operator OnceAction<F>`.
+  //
+  // This is templated in order to cause the overload above to be preferred
+  // when the input is convertible to either type.
+  template <int&... ExplicitArgumentBarrier, typename = void>
+  TypedExpectation& WillOnce(Action<F> action) {
+    ExpectSpecProperty(last_clause_ <= kWillOnce,
+                       ".WillOnce() cannot appear after "
+                       ".WillRepeatedly() or .RetiresOnSaturation().");
+    last_clause_ = kWillOnce;
+
+    untyped_actions_.push_back(new Action<F>(std::move(action)));
+
+    if (!cardinality_specified()) {
+      set_cardinality(Exactly(static_cast<int>(untyped_actions_.size())));
+    }
+    return *this;
+  }
+
+  // Implements the .WillRepeatedly() clause.
+  TypedExpectation& WillRepeatedly(const Action<F>& action) {
+    if (last_clause_ == kWillRepeatedly) {
+      ExpectSpecProperty(false,
+                         ".WillRepeatedly() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWillRepeatedly,
+                         ".WillRepeatedly() cannot appear "
+                         "after .RetiresOnSaturation().");
+    }
+    last_clause_ = kWillRepeatedly;
+    repeated_action_specified_ = true;
+
+    repeated_action_ = action;
+    if (!cardinality_specified()) {
+      set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
+    }
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Implements the .RetiresOnSaturation() clause.
+  TypedExpectation& RetiresOnSaturation() {
+    ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
+                       ".RetiresOnSaturation() cannot appear "
+                       "more than once.");
+    last_clause_ = kRetiresOnSaturation;
+    retires_on_saturation_ = true;
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Returns the matchers for the arguments as specified inside the
+  // EXPECT_CALL() macro.
+  const ArgumentMatcherTuple& matchers() const { return matchers_; }
+
+  // Returns the matcher specified by the .With() clause.
+  const Matcher<const ArgumentTuple&>& extra_matcher() const {
+    return extra_matcher_;
+  }
+
+  // Returns the action specified by the .WillRepeatedly() clause.
+  const Action<F>& repeated_action() const { return repeated_action_; }
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  void MaybeDescribeExtraMatcherTo(::std::ostream* os) override {
+    if (extra_matcher_specified_) {
+      *os << "    Expected args: ";
+      extra_matcher_.DescribeTo(os);
+      *os << "\n";
+    }
+  }
+
+ private:
+  template <typename Function>
+  friend class FunctionMocker;
+
+  // An adaptor that turns a OneAction<F> into something compatible with
+  // Action<F>. Must be called at most once.
+  struct ActionAdaptor {
+    std::shared_ptr<OnceAction<R(Args...)>> once_action;
+
+    R operator()(Args&&... args) const {
+      return std::move(*once_action).Call(std::forward<Args>(args)...);
+    }
+  };
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  Expectation GetHandle() override { return owner_->GetHandleOf(this); }
+
+  // The following methods will be called only after the EXPECT_CALL()
+  // statement finishes and when the current thread holds
+  // g_gmock_mutex.
+
+  // Returns true if and only if this expectation matches the given arguments.
+  bool Matches(const ArgumentTuple& args) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns true if and only if this expectation should handle the given
+  // arguments.
+  bool ShouldHandleArguments(const ArgumentTuple& args) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+
+    // In case the action count wasn't checked when the expectation
+    // was defined (e.g. if this expectation has no WillRepeatedly()
+    // or RetiresOnSaturation() clause), we check it when the
+    // expectation is used for the first time.
+    CheckActionCountIfNotDone();
+    return !is_retired() && AllPrerequisitesAreSatisfied() && Matches(args);
+  }
+
+  // Describes the result of matching the arguments against this
+  // expectation to the given ostream.
+  void ExplainMatchResultTo(const ArgumentTuple& args, ::std::ostream* os) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+
+    if (is_retired()) {
+      *os << "         Expected: the expectation is active\n"
+          << "           Actual: it is retired\n";
+    } else if (!Matches(args)) {
+      if (!TupleMatches(matchers_, args)) {
+        ExplainMatchFailureTupleTo(matchers_, args, os);
+      }
+      StringMatchResultListener listener;
+      if (!extra_matcher_.MatchAndExplain(args, &listener)) {
+        *os << "    Expected args: ";
+        extra_matcher_.DescribeTo(os);
+        *os << "\n           Actual: don't match";
+
+        internal::PrintIfNotEmpty(listener.str(), os);
+        *os << "\n";
+      }
+    } else if (!AllPrerequisitesAreSatisfied()) {
+      *os << "         Expected: all pre-requisites are satisfied\n"
+          << "           Actual: the following immediate pre-requisites "
+          << "are not satisfied:\n";
+      ExpectationSet unsatisfied_prereqs;
+      FindUnsatisfiedPrerequisites(&unsatisfied_prereqs);
+      int i = 0;
+      for (ExpectationSet::const_iterator it = unsatisfied_prereqs.begin();
+           it != unsatisfied_prereqs.end(); ++it) {
+        it->expectation_base()->DescribeLocationTo(os);
+        *os << "pre-requisite #" << i++ << "\n";
+      }
+      *os << "                   (end of pre-requisites)\n";
+    } else {
+      // This line is here just for completeness' sake.  It will never
+      // be executed as currently the ExplainMatchResultTo() function
+      // is called only when the mock function call does NOT match the
+      // expectation.
+      *os << "The call matches the expectation.\n";
+    }
+  }
+
+  // Returns the action that should be taken for the current invocation.
+  const Action<F>& GetCurrentAction(const FunctionMocker<F>* mocker,
+                                    const ArgumentTuple& args) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    const int count = call_count();
+    Assert(count >= 1, __FILE__, __LINE__,
+           "call_count() is <= 0 when GetCurrentAction() is "
+           "called - this should never happen.");
+
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    if (action_count > 0 && !repeated_action_specified_ &&
+        count > action_count) {
+      // If there is at least one WillOnce() and no WillRepeatedly(),
+      // we warn the user when the WillOnce() clauses ran out.
+      ::std::stringstream ss;
+      DescribeLocationTo(&ss);
+      ss << "Actions ran out in " << source_text() << "...\n"
+         << "Called " << count << " times, but only " << action_count
+         << " WillOnce()" << (action_count == 1 ? " is" : "s are")
+         << " specified - ";
+      mocker->DescribeDefaultActionTo(args, &ss);
+      Log(kWarning, ss.str(), 1);
+    }
+
+    return count <= action_count
+               ? *static_cast<const Action<F>*>(
+                     untyped_actions_[static_cast<size_t>(count - 1)])
+               : repeated_action();
+  }
+
+  // Given the arguments of a mock function call, if the call will
+  // over-saturate this expectation, returns the default action;
+  // otherwise, returns the next action in this expectation.  Also
+  // describes *what* happened to 'what', and explains *why* Google
+  // Mock does it to 'why'.  This method is not const as it calls
+  // IncrementCallCount().  A return value of NULL means the default
+  // action.
+  const Action<F>* GetActionForArguments(const FunctionMocker<F>* mocker,
+                                         const ArgumentTuple& args,
+                                         ::std::ostream* what,
+                                         ::std::ostream* why)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    const ::std::string& expectation_description = GetDescription();
+    if (IsSaturated()) {
+      // We have an excessive call.
+      IncrementCallCount();
+      *what << "Mock function ";
+      if (!expectation_description.empty()) {
+        *what << "\"" << expectation_description << "\" ";
+      }
+      *what << "called more times than expected - ";
+      mocker->DescribeDefaultActionTo(args, what);
+      DescribeCallCountTo(why);
+
+      return nullptr;
+    }
+
+    IncrementCallCount();
+    RetireAllPreRequisites();
+
+    if (retires_on_saturation_ && IsSaturated()) {
+      Retire();
+    }
+
+    // Must be done after IncrementCount()!
+    *what << "Mock function ";
+    if (!expectation_description.empty()) {
+      *what << "\"" << expectation_description << "\" ";
+    }
+    *what << "call matches " << source_text() << "...\n";
+    return &(GetCurrentAction(mocker, args));
+  }
+
+  // All the fields below won't change once the EXPECT_CALL()
+  // statement finishes.
+  FunctionMocker<F>* const owner_;
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> repeated_action_;
+
+  TypedExpectation(const TypedExpectation&) = delete;
+  TypedExpectation& operator=(const TypedExpectation&) = delete;
+};  // class TypedExpectation
+
+// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
+// specifying the default behavior of, or expectation on, a mock
+// function.
+
+// Note: class MockSpec really belongs to the ::testing namespace.
+// However if we define it in ::testing, MSVC will complain when
+// classes in ::testing::internal declare it as a friend class
+// template.  To workaround this compiler bug, we define MockSpec in
+// ::testing::internal and import it into ::testing.
+
+// Logs a message including file and line number information.
+GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity,
+                                const char* file, int line,
+                                const std::string& message);
+
+template <typename F>
+class MockSpec {
+ public:
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+  typedef
+      typename internal::Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  // Constructs a MockSpec object, given the function mocker object
+  // that the spec is associated with.
+  MockSpec(internal::FunctionMocker<F>* function_mocker,
+           const ArgumentMatcherTuple& matchers)
+      : function_mocker_(function_mocker), matchers_(matchers) {}
+
+  // Adds a new default action spec to the function mocker and returns
+  // the newly created spec.
+  internal::OnCallSpec<F>& InternalDefaultActionSetAt(const char* file,
+                                                      int line, const char* obj,
+                                                      const char* call) {
+    LogWithLocation(internal::kInfo, file, line,
+                    std::string("ON_CALL(") + obj + ", " + call + ") invoked");
+    return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
+  }
+
+  // Adds a new expectation spec to the function mocker and returns
+  // the newly created spec.
+  internal::TypedExpectation<F>& InternalExpectedAt(const char* file, int line,
+                                                    const char* obj,
+                                                    const char* call) {
+    const std::string source_text(std::string("EXPECT_CALL(") + obj + ", " +
+                                  call + ")");
+    LogWithLocation(internal::kInfo, file, line, source_text + " invoked");
+    return function_mocker_->AddNewExpectation(file, line, source_text,
+                                               matchers_);
+  }
+
+  // This operator overload is used to swallow the superfluous parameter list
+  // introduced by the ON/EXPECT_CALL macros. See the macro comments for more
+  // explanation.
+  MockSpec<F>& operator()(const internal::WithoutMatchers&, void* const) {
+    return *this;
+  }
+
+ private:
+  template <typename Function>
+  friend class internal::FunctionMocker;
+
+  // The function mocker that owns this spec.
+  internal::FunctionMocker<F>* const function_mocker_;
+  // The argument matchers specified in the spec.
+  ArgumentMatcherTuple matchers_;
+};  // class MockSpec
+
+// Wrapper type for generically holding an ordinary value or lvalue reference.
+// If T is not a reference type, it must be copyable or movable.
+// ReferenceOrValueWrapper<T> is movable, and will also be copyable unless
+// T is a move-only value type (which means that it will always be copyable
+// if the current platform does not support move semantics).
+//
+// The primary template defines handling for values, but function header
+// comments describe the contract for the whole template (including
+// specializations).
+template <typename T>
+class ReferenceOrValueWrapper {
+ public:
+  // Constructs a wrapper from the given value/reference.
+  explicit ReferenceOrValueWrapper(T value) : value_(std::move(value)) {}
+
+  // Unwraps and returns the underlying value/reference, exactly as
+  // originally passed. The behavior of calling this more than once on
+  // the same object is unspecified.
+  T Unwrap() { return std::move(value_); }
+
+  // Provides nondestructive access to the underlying value/reference.
+  // Always returns a const reference (more precisely,
+  // const std::add_lvalue_reference<T>::type). The behavior of calling this
+  // after calling Unwrap on the same object is unspecified.
+  const T& Peek() const { return value_; }
+
+ private:
+  T value_;
+};
+
+// Specialization for lvalue reference types. See primary template
+// for documentation.
+template <typename T>
+class ReferenceOrValueWrapper<T&> {
+ public:
+  // Workaround for debatable pass-by-reference lint warning (c-library-team
+  // policy precludes NOLINT in this context)
+  typedef T& reference;
+  explicit ReferenceOrValueWrapper(reference ref) : value_ptr_(&ref) {}
+  T& Unwrap() { return *value_ptr_; }
+  const T& Peek() const { return *value_ptr_; }
+
+ private:
+  T* value_ptr_;
+};
+
+// Prints the held value as an action's result to os.
+template <typename T>
+void PrintAsActionResult(const T& result, std::ostream& os) {
+  os << "\n          Returns: ";
+  // T may be a reference type, so we don't use UniversalPrint().
+  UniversalPrinter<T>::Print(result, &os);
+}
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+GTEST_API_ void ReportUninterestingCall(CallReaction reaction,
+                                        const std::string& msg);
+
+// A generic RAII type that runs a user-provided function in its destructor.
+class Cleanup final {
+ public:
+  explicit Cleanup(std::function<void()> f) : f_(std::move(f)) {}
+  ~Cleanup() { f_(); }
+
+ private:
+  std::function<void()> f_;
+};
+
+struct UntypedFunctionMockerBase::UninterestingCallCleanupHandler {
+  CallReaction reaction;
+  std::stringstream& ss;
+
+  ~UninterestingCallCleanupHandler() {
+    ReportUninterestingCall(reaction, ss.str());
+  }
+};
+
+struct UntypedFunctionMockerBase::FailureCleanupHandler {
+  std::stringstream& ss;
+  std::stringstream& why;
+  std::stringstream& loc;
+  const ExpectationBase* untyped_expectation;
+  bool found;
+  bool is_excessive;
+
+  ~FailureCleanupHandler() {
+    ss << "\n" << why.str();
+
+    if (!found) {
+      // No expectation matches this call - reports a failure.
+      Expect(false, nullptr, -1, ss.str());
+    } else if (is_excessive) {
+      // We had an upper-bound violation and the failure message is in ss.
+      Expect(false, untyped_expectation->file(), untyped_expectation->line(),
+             ss.str());
+    } else {
+      // We had an expected call and the matching expectation is
+      // described in ss.
+      Log(kInfo, loc.str() + ss.str(), 2);
+    }
+  }
+};
+
+template <typename F>
+class FunctionMocker;
+
+template <typename R, typename... Args>
+class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
+  using F = R(Args...);
+
+ public:
+  using Result = R;
+  using ArgumentTuple = std::tuple<Args...>;
+  using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>;
+
+  FunctionMocker() = default;
+
+  // There is no generally useful and implementable semantics of
+  // copying a mock object, so copying a mock is usually a user error.
+  // Thus we disallow copying function mockers.  If the user really
+  // wants to copy a mock object, they should implement their own copy
+  // operation, for example:
+  //
+  //   class MockFoo : public Foo {
+  //    public:
+  //     // Defines a copy constructor explicitly.
+  //     MockFoo(const MockFoo& src) {}
+  //     ...
+  //   };
+  FunctionMocker(const FunctionMocker&) = delete;
+  FunctionMocker& operator=(const FunctionMocker&) = delete;
+
+  // The destructor verifies that all expectations on this mock
+  // function have been satisfied.  If not, it will report Google Test
+  // non-fatal failures for the violations.
+  ~FunctionMocker() override GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    MutexLock l(&g_gmock_mutex);
+    VerifyAndClearExpectationsLocked();
+    Mock::UnregisterLocked(this);
+    ClearDefaultActionsLocked();
+  }
+
+  // Returns the ON_CALL spec that matches this mock function with the
+  // given arguments; returns NULL if no matching ON_CALL is found.
+  // L = *
+  const OnCallSpec<F>* FindOnCallSpec(const ArgumentTuple& args) const {
+    for (UntypedOnCallSpecs::const_reverse_iterator it =
+             untyped_on_call_specs_.rbegin();
+         it != untyped_on_call_specs_.rend(); ++it) {
+      const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it);
+      if (spec->Matches(args)) return spec;
+    }
+
+    return nullptr;
+  }
+
+  // Performs the default action of this mock function on the given
+  // arguments and returns the result. Asserts (or throws if
+  // exceptions are enabled) with a helpful call description if there
+  // is no valid return value. This method doesn't depend on the
+  // mutable state of this object, and thus can be called concurrently
+  // without locking.
+  // L = *
+  Result PerformDefaultAction(ArgumentTuple&& args,
+                              const std::string& call_description) const {
+    const OnCallSpec<F>* const spec = this->FindOnCallSpec(args);
+    if (spec != nullptr) {
+      return spec->GetAction().Perform(std::move(args));
+    }
+    const std::string message =
+        call_description +
+        "\n    The mock function has no default action "
+        "set, and its return type has no default value set.";
+#if GTEST_HAS_EXCEPTIONS
+    if (!DefaultValue<Result>::Exists()) {
+      throw std::runtime_error(message);
+    }
+#else
+    Assert(DefaultValue<Result>::Exists(), "", -1, message);
+#endif
+    return DefaultValue<Result>::Get();
+  }
+
+  // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
+  // clears the ON_CALL()s set on this mock function.
+  void ClearDefaultActionsLocked() override
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+
+    // Deleting our default actions may trigger other mock objects to be
+    // deleted, for example if an action contains a reference counted smart
+    // pointer to that mock object, and that is the last reference. So if we
+    // delete our actions within the context of the global mutex we may deadlock
+    // when this method is called again. Instead, make a copy of the set of
+    // actions to delete, clear our set within the mutex, and then delete the
+    // actions outside of the mutex.
+    UntypedOnCallSpecs specs_to_delete;
+    untyped_on_call_specs_.swap(specs_to_delete);
+
+    g_gmock_mutex.Unlock();
+    for (UntypedOnCallSpecs::const_iterator it = specs_to_delete.begin();
+         it != specs_to_delete.end(); ++it) {
+      delete static_cast<const OnCallSpec<F>*>(*it);
+    }
+
+    // Lock the mutex again, since the caller expects it to be locked when we
+    // return.
+    g_gmock_mutex.Lock();
+  }
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.
+  Result Invoke(Args... args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    return InvokeWith(ArgumentTuple(std::forward<Args>(args)...));
+  }
+
+  MockSpec<F> With(Matcher<Args>... m) {
+    return MockSpec<F>(this, ::std::make_tuple(std::move(m)...));
+  }
+
+ protected:
+  template <typename Function>
+  friend class MockSpec;
+
+  // Adds and returns a default action spec for this mock function.
+  OnCallSpec<F>& AddNewOnCallSpec(const char* file, int line,
+                                  const ArgumentMatcherTuple& m)
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m);
+    untyped_on_call_specs_.push_back(on_call_spec);
+    return *on_call_spec;
+  }
+
+  // Adds and returns an expectation spec for this mock function.
+  TypedExpectation<F>& AddNewExpectation(const char* file, int line,
+                                         const std::string& source_text,
+                                         const ArgumentMatcherTuple& m)
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    TypedExpectation<F>* const expectation =
+        new TypedExpectation<F>(this, file, line, source_text, m);
+    const std::shared_ptr<ExpectationBase> untyped_expectation(expectation);
+    // See the definition of untyped_expectations_ for why access to
+    // it is unprotected here.
+    untyped_expectations_.push_back(untyped_expectation);
+
+    // Adds this expectation into the implicit sequence if there is one.
+    Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
+    if (implicit_sequence != nullptr) {
+      implicit_sequence->AddExpectation(Expectation(untyped_expectation));
+    }
+
+    return *expectation;
+  }
+
+ private:
+  template <typename Func>
+  friend class TypedExpectation;
+
+  // Some utilities needed for implementing UntypedInvokeWith().
+
+  // Describes what default action will be performed for the given
+  // arguments.
+  // L = *
+  void DescribeDefaultActionTo(const ArgumentTuple& args,
+                               ::std::ostream* os) const {
+    const OnCallSpec<F>* const spec = FindOnCallSpec(args);
+
+    if (spec == nullptr) {
+      *os << (std::is_void<Result>::value ? "returning directly.\n"
+                                          : "returning default value.\n");
+    } else {
+      *os << "taking default action specified at:\n"
+          << FormatFileLocation(spec->file(), spec->line()) << "\n";
+    }
+  }
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                        ::std::ostream* os) const override
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    *os << "Uninteresting mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    *os << "    Function call: " << Name();
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  //
+  // Critical section: We must find the matching expectation and the
+  // corresponding action that needs to be taken in an ATOMIC
+  // transaction.  Otherwise another thread may call this mock
+  // method in the middle and mess up the state.
+  //
+  // However, performing the action has to be left out of the critical
+  // section.  The reason is that we have no control on what the
+  // action does (it can invoke an arbitrary user function or even a
+  // mock function) and excessive locking could cause a dead lock.
+  const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args, const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) override
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    MutexLock l(&g_gmock_mutex);
+    TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
+    if (exp == nullptr) {  // A match wasn't found.
+      this->FormatUnexpectedCallMessageLocked(args, what, why);
+      return nullptr;
+    }
+
+    // This line must be done before calling GetActionForArguments(),
+    // which will increment the call count for *exp and thus affect
+    // its saturation status.
+    *is_excessive = exp->IsSaturated();
+    const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
+    if (action != nullptr && action->IsDoDefault())
+      action = nullptr;  // Normalize "do default" to NULL.
+    *untyped_action = action;
+    return exp;
+  }
+
+  // Prints the given function arguments to the ostream.
+  void UntypedPrintArgs(const void* untyped_args,
+                        ::std::ostream* os) const override {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the arguments, or NULL if no
+  // expectation matches them.
+  TypedExpectation<F>* FindMatchingExpectationLocked(const ArgumentTuple& args)
+      const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    // See the definition of untyped_expectations_ for why access to
+    // it is unprotected here.
+    for (typename UntypedExpectations::const_reverse_iterator it =
+             untyped_expectations_.rbegin();
+         it != untyped_expectations_.rend(); ++it) {
+      TypedExpectation<F>* const exp =
+          static_cast<TypedExpectation<F>*>(it->get());
+      if (exp->ShouldHandleArguments(args)) {
+        return exp;
+      }
+    }
+    return nullptr;
+  }
+
+  // Returns a message that the arguments don't match any expectation.
+  void FormatUnexpectedCallMessageLocked(const ArgumentTuple& args,
+                                         ::std::ostream* os,
+                                         ::std::ostream* why) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    *os << "\nUnexpected mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    PrintTriedExpectationsLocked(args, why);
+  }
+
+  // Prints a list of expectations that have been tried against the
+  // current mock function call.
+  void PrintTriedExpectationsLocked(const ArgumentTuple& args,
+                                    ::std::ostream* why) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    const size_t count = untyped_expectations_.size();
+    *why << "Google Mock tried the following " << count << " "
+         << (count == 1 ? "expectation, but it didn't match"
+                        : "expectations, but none matched")
+         << ":\n";
+    for (size_t i = 0; i < count; i++) {
+      TypedExpectation<F>* const expectation =
+          static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
+      *why << "\n";
+      expectation->DescribeLocationTo(why);
+      if (count > 1) {
+        *why << "tried expectation #" << i << ": ";
+      }
+      *why << expectation->source_text() << "...\n";
+      expectation->ExplainMatchResultTo(args, why);
+      expectation->DescribeCallCountTo(why);
+    }
+  }
+
+  // Performs the given action (or the default if it's null) with the given
+  // arguments and returns the action's result.
+  // L = *
+  R PerformAction(const void* untyped_action, ArgumentTuple&& args,
+                  const std::string& call_description) const {
+    if (untyped_action == nullptr) {
+      return PerformDefaultAction(std::move(args), call_description);
+    }
+
+    // Make a copy of the action before performing it, in case the
+    // action deletes the mock object (and thus deletes itself).
+    const Action<F> action = *static_cast<const Action<F>*>(untyped_action);
+    return action.Perform(std::move(args));
+  }
+
+  // Is it possible to store an object of the supplied type in a local variable
+  // for the sake of printing it, then return it on to the caller?
+  template <typename T>
+  using can_print_result = internal::conjunction<
+      // void can't be stored as an object (and we also don't need to print it).
+      internal::negation<std::is_void<T>>,
+      // Non-moveable types can't be returned on to the user, so there's no way
+      // for us to intercept and print them.
+      std::is_move_constructible<T>>;
+
+  // Perform the supplied action, printing the result to os.
+  template <typename T = R,
+            typename std::enable_if<can_print_result<T>::value, int>::type = 0>
+  R PerformActionAndPrintResult(const void* const untyped_action,
+                                ArgumentTuple&& args,
+                                const std::string& call_description,
+                                std::ostream& os) {
+    R result = PerformAction(untyped_action, std::move(args), call_description);
+
+    PrintAsActionResult(result, os);
+    return std::forward<R>(result);
+  }
+
+  // An overload for when it's not possible to print the result. In this case we
+  // simply perform the action.
+  template <typename T = R,
+            typename std::enable_if<
+                internal::negation<can_print_result<T>>::value, int>::type = 0>
+  R PerformActionAndPrintResult(const void* const untyped_action,
+                                ArgumentTuple&& args,
+                                const std::string& call_description,
+                                std::ostream&) {
+    return PerformAction(untyped_action, std::move(args), call_description);
+  }
+
+  // Returns the result of invoking this mock function with the given
+  // arguments. This function can be safely called from multiple
+  // threads concurrently.
+  R InvokeWith(ArgumentTuple&& args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+};  // class FunctionMocker
+
+// Calculates the result of invoking this mock function with the given
+// arguments, prints it, and returns it.
+template <typename R, typename... Args>
+R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  // See the definition of untyped_expectations_ for why access to it
+  // is unprotected here.
+  if (untyped_expectations_.size() == 0) {
+    // No expectation is set on this mock method - we have an
+    // uninteresting call.
+
+    // We must get Google Mock's reaction on uninteresting calls
+    // made on this mock object BEFORE performing the action,
+    // because the action may DELETE the mock object and make the
+    // following expression meaningless.
+    const CallReaction reaction =
+        Mock::GetReactionOnUninterestingCalls(MockObject());
+
+    // True if and only if we need to print this call's arguments and return
+    // value.  This definition must be kept in sync with
+    // the behavior of ReportUninterestingCall().
+    const bool need_to_report_uninteresting_call =
+        // If the user allows this uninteresting call, we print it
+        // only when they want informational messages.
+        reaction == kAllow ? LogIsVisible(kInfo) :
+                           // If the user wants this to be a warning, we print
+                           // it only when they want to see warnings.
+            reaction == kWarn
+            ? LogIsVisible(kWarning)
+            :
+            // Otherwise, the user wants this to be an error, and we
+            // should always print detailed information in the error.
+            true;
+
+    if (!need_to_report_uninteresting_call) {
+      // Perform the action without printing the call information.
+      return this->PerformDefaultAction(
+          std::move(args), "Function call: " + std::string(Name()));
+    }
+
+    // Warns about the uninteresting call.
+    ::std::stringstream ss;
+    this->UntypedDescribeUninterestingCall(&args, &ss);
+
+    // Perform the action, print the result, and then report the uninteresting
+    // call.
+    //
+    // We use RAII to do the latter in case R is void or a non-moveable type. In
+    // either case we can't assign it to a local variable.
+    //
+    // Note that std::bind() is essential here.
+    // We *don't* use any local callback types (like lambdas).
+    // Doing so slows down compilation dramatically because the *constructor* of
+    // std::function<T> is re-instantiated with different template
+    // parameters each time.
+    const UninterestingCallCleanupHandler report_uninteresting_call = {reaction,
+                                                                       ss};
+
+    return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss);
+  }
+
+  bool is_excessive = false;
+  ::std::stringstream ss;
+  ::std::stringstream why;
+  ::std::stringstream loc;
+  const void* untyped_action = nullptr;
+
+  // The UntypedFindMatchingExpectation() function acquires and
+  // releases g_gmock_mutex.
+
+  const ExpectationBase* const untyped_expectation =
+      this->UntypedFindMatchingExpectation(&args, &untyped_action,
+                                           &is_excessive, &ss, &why);
+  const bool found = untyped_expectation != nullptr;
+
+  // True if and only if we need to print the call's arguments
+  // and return value.
+  // This definition must be kept in sync with the uses of Expect()
+  // and Log() in this function.
+  const bool need_to_report_call =
+      !found || is_excessive || LogIsVisible(kInfo);
+  if (!need_to_report_call) {
+    // Perform the action without printing the call information.
+    return PerformAction(untyped_action, std::move(args), "");
+  }
+
+  ss << "    Function call: " << Name();
+  this->UntypedPrintArgs(&args, &ss);
+
+  // In case the action deletes a piece of the expectation, we
+  // generate the message beforehand.
+  if (found && !is_excessive) {
+    untyped_expectation->DescribeLocationTo(&loc);
+  }
+
+  // Perform the action, print the result, and then fail or log in whatever way
+  // is appropriate.
+  //
+  // We use RAII to do the latter in case R is void or a non-moveable type. In
+  // either case we can't assign it to a local variable.
+  //
+  // Note that we *don't* use any local callback types (like lambdas) here.
+  // Doing so slows down compilation dramatically because the *constructor* of
+  // std::function<T> is re-instantiated with different template
+  // parameters each time.
+  const FailureCleanupHandler handle_failures = {
+      ss, why, loc, untyped_expectation, found, is_excessive};
+
+  return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
+                                     ss);
+}
+
+}  // namespace internal
+
+namespace internal {
+
+template <typename F>
+class MockFunction;
+
+template <typename R, typename... Args>
+class MockFunction<R(Args...)> {
+ public:
+  MockFunction(const MockFunction&) = delete;
+  MockFunction& operator=(const MockFunction&) = delete;
+
+  std::function<R(Args...)> AsStdFunction() {
+    return [this](Args... args) -> R {
+      return this->Call(std::forward<Args>(args)...);
+    };
+  }
+
+  // Implementation detail: the expansion of the MOCK_METHOD macro.
+  R Call(Args... args) {
+    mock_.SetOwnerAndName(this, "Call");
+    return mock_.Invoke(std::forward<Args>(args)...);
+  }
+
+  MockSpec<R(Args...)> gmock_Call(Matcher<Args>... m) {
+    mock_.RegisterOwner(this);
+    return mock_.With(std::move(m)...);
+  }
+
+  MockSpec<R(Args...)> gmock_Call(const WithoutMatchers&, R (*)(Args...)) {
+    return this->gmock_Call(::testing::A<Args>()...);
+  }
+
+ protected:
+  MockFunction() = default;
+  ~MockFunction() = default;
+
+ private:
+  FunctionMocker<R(Args...)> mock_;
+};
+
+/*
+The SignatureOf<F> struct is a meta-function returning function signature
+corresponding to the provided F argument.
+
+It makes use of MockFunction easier by allowing it to accept more F arguments
+than just function signatures.
+
+Specializations provided here cover a signature type itself and any template
+that can be parameterized with a signature, including std::function and
+boost::function.
+*/
+
+template <typename F, typename = void>
+struct SignatureOf;
+
+template <typename R, typename... Args>
+struct SignatureOf<R(Args...)> {
+  using type = R(Args...);
+};
+
+template <template <typename> class C, typename F>
+struct SignatureOf<C<F>,
+                   typename std::enable_if<std::is_function<F>::value>::type>
+    : SignatureOf<F> {};
+
+template <typename F>
+using SignatureOfT = typename SignatureOf<F>::type;
+
+}  // namespace internal
+
+// A MockFunction<F> type has one mock method whose type is
+// internal::SignatureOfT<F>.  It is useful when you just want your
+// test code to emit some messages and have Google Mock verify the
+// right messages are sent (and perhaps at the right times).  For
+// example, if you are exercising code:
+//
+//   Foo(1);
+//   Foo(2);
+//   Foo(3);
+//
+// and want to verify that Foo(1) and Foo(3) both invoke
+// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
+//
+// TEST(FooTest, InvokesBarCorrectly) {
+//   MyMock mock;
+//   MockFunction<void(string check_point_name)> check;
+//   {
+//     InSequence s;
+//
+//     EXPECT_CALL(mock, Bar("a"));
+//     EXPECT_CALL(check, Call("1"));
+//     EXPECT_CALL(check, Call("2"));
+//     EXPECT_CALL(mock, Bar("a"));
+//   }
+//   Foo(1);
+//   check.Call("1");
+//   Foo(2);
+//   check.Call("2");
+//   Foo(3);
+// }
+//
+// The expectation spec says that the first Bar("a") must happen
+// before check point "1", the second Bar("a") must happen after check
+// point "2", and nothing should happen between the two check
+// points. The explicit check points make it easy to tell which
+// Bar("a") is called by which call to Foo().
+//
+// MockFunction<F> can also be used to exercise code that accepts
+// std::function<internal::SignatureOfT<F>> callbacks. To do so, use
+// AsStdFunction() method to create std::function proxy forwarding to
+// original object's Call. Example:
+//
+// TEST(FooTest, RunsCallbackWithBarArgument) {
+//   MockFunction<int(string)> callback;
+//   EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
+//   Foo(callback.AsStdFunction());
+// }
+//
+// The internal::SignatureOfT<F> indirection allows to use other types
+// than just function signature type. This is typically useful when
+// providing a mock for a predefined std::function type. Example:
+//
+// using FilterPredicate = std::function<bool(string)>;
+// void MyFilterAlgorithm(FilterPredicate predicate);
+//
+// TEST(FooTest, FilterPredicateAlwaysAccepts) {
+//   MockFunction<FilterPredicate> predicateMock;
+//   EXPECT_CALL(predicateMock, Call(_)).WillRepeatedly(Return(true));
+//   MyFilterAlgorithm(predicateMock.AsStdFunction());
+// }
+template <typename F>
+class MockFunction : public internal::MockFunction<internal::SignatureOfT<F>> {
+  using Base = internal::MockFunction<internal::SignatureOfT<F>>;
+
+ public:
+  using Base::Base;
+};
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the MockSpec class template is
+// meant to be defined in the ::testing namespace.  The following line
+// is just a trick for working around a bug in MSVC 8.0, which cannot
+// handle it if we define MockSpec in ::testing.
+using internal::MockSpec;
+
+// Const(x) is a convenient function for obtaining a const reference
+// to x.  This is useful for setting expectations on an overloaded
+// const mock method, e.g.
+//
+//   class MockFoo : public FooInterface {
+//    public:
+//     MOCK_METHOD0(Bar, int());
+//     MOCK_CONST_METHOD0(Bar, int&());
+//   };
+//
+//   MockFoo foo;
+//   // Expects a call to non-const MockFoo::Bar().
+//   EXPECT_CALL(foo, Bar());
+//   // Expects a call to const MockFoo::Bar().
+//   EXPECT_CALL(Const(foo), Bar());
+template <typename T>
+inline const T& Const(const T& x) {
+  return x;
+}
+
+// Constructs an Expectation object that references and co-owns exp.
+inline Expectation::Expectation(internal::ExpectationBase& exp)  // NOLINT
+    : expectation_base_(exp.GetHandle().expectation_base()) {}
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// Implementation for ON_CALL and EXPECT_CALL macros. A separate macro is
+// required to avoid compile errors when the name of the method used in call is
+// a result of macro expansion. See CompilesWithMethodNameExpandedFromMacro
+// tests in internal/gmock-spec-builders_test.cc for more details.
+//
+// This macro supports statements both with and without parameter matchers. If
+// the parameter list is omitted, gMock will accept any parameters, which allows
+// tests to be written that don't need to encode the number of method
+// parameter. This technique may only be used for non-overloaded methods.
+//
+//   // These are the same:
+//   ON_CALL(mock, NoArgsMethod()).WillByDefault(...);
+//   ON_CALL(mock, NoArgsMethod).WillByDefault(...);
+//
+//   // As are these:
+//   ON_CALL(mock, TwoArgsMethod(_, _)).WillByDefault(...);
+//   ON_CALL(mock, TwoArgsMethod).WillByDefault(...);
+//
+//   // Can also specify args if you want, of course:
+//   ON_CALL(mock, TwoArgsMethod(_, 45)).WillByDefault(...);
+//
+//   // Overloads work as long as you specify parameters:
+//   ON_CALL(mock, OverloadedMethod(_)).WillByDefault(...);
+//   ON_CALL(mock, OverloadedMethod(_, _)).WillByDefault(...);
+//
+//   // Oops! Which overload did you want?
+//   ON_CALL(mock, OverloadedMethod).WillByDefault(...);
+//     => ERROR: call to member function 'gmock_OverloadedMethod' is ambiguous
+//
+// How this works: The mock class uses two overloads of the gmock_Method
+// expectation setter method plus an operator() overload on the MockSpec object.
+// In the matcher list form, the macro expands to:
+//
+//   // This statement:
+//   ON_CALL(mock, TwoArgsMethod(_, 45))...
+//
+//   // ...expands to:
+//   mock.gmock_TwoArgsMethod(_, 45)(WithoutMatchers(), nullptr)...
+//   |-------------v---------------||------------v-------------|
+//       invokes first overload        swallowed by operator()
+//
+//   // ...which is essentially:
+//   mock.gmock_TwoArgsMethod(_, 45)...
+//
+// Whereas the form without a matcher list:
+//
+//   // This statement:
+//   ON_CALL(mock, TwoArgsMethod)...
+//
+//   // ...expands to:
+//   mock.gmock_TwoArgsMethod(WithoutMatchers(), nullptr)...
+//   |-----------------------v--------------------------|
+//                 invokes second overload
+//
+//   // ...which is essentially:
+//   mock.gmock_TwoArgsMethod(_, _)...
+//
+// The WithoutMatchers() argument is used to disambiguate overloads and to
+// block the caller from accidentally invoking the second overload directly. The
+// second argument is an internal type derived from the method signature. The
+// failure to disambiguate two overloads of this method in the ON_CALL statement
+// is how we block callers from setting expectations on overloaded methods.
+#define GMOCK_ON_CALL_IMPL_(mock_expr, Setter, call)                    \
+  ((mock_expr).gmock_##call)(::testing::internal::GetWithoutMatchers(), \
+                             nullptr)                                   \
+      .Setter(__FILE__, __LINE__, #mock_expr, #call)
+
+#define ON_CALL(obj, call) \
+  GMOCK_ON_CALL_IMPL_(obj, InternalDefaultActionSetAt, call)
+
+#define EXPECT_CALL(obj, call) \
+  GMOCK_ON_CALL_IMPL_(obj, InternalExpectedAt, call)
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/gmock.h b/3rd-party/googletest/googlemock/include/gmock/gmock.h
new file mode 100644
index 0000000..c78fb8e
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/gmock.h
@@ -0,0 +1,97 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This is the main header file a user should include.
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_H_
+
+// This file implements the following syntax:
+//
+//   ON_CALL(mock_object, Method(...))
+//     .With(...) ?
+//     .WillByDefault(...);
+//
+// where With() is optional and WillByDefault() must appear exactly
+// once.
+//
+//   EXPECT_CALL(mock_object, Method(...))
+//     .With(...) ?
+//     .Times(...) ?
+//     .InSequence(...) *
+//     .WillOnce(...) *
+//     .WillRepeatedly(...) ?
+//     .RetiresOnSaturation() ? ;
+//
+// where all clauses are optional and WillOnce() can be repeated.
+
+#include "gmock/gmock-actions.h"  // IWYU pragma: export
+#include "gmock/gmock-cardinalities.h"  // IWYU pragma: export
+#include "gmock/gmock-function-mocker.h"  // IWYU pragma: export
+#include "gmock/gmock-matchers.h"  // IWYU pragma: export
+#include "gmock/gmock-more-actions.h"  // IWYU pragma: export
+#include "gmock/gmock-more-matchers.h"  // IWYU pragma: export
+#include "gmock/gmock-nice-strict.h"  // IWYU pragma: export
+#include "gmock/gmock-spec-builders.h"  // IWYU pragma: export
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+
+// Declares Google Mock flags that we want a user to use programmatically.
+GMOCK_DECLARE_bool_(catch_leaked_mocks);
+GMOCK_DECLARE_string_(verbose);
+GMOCK_DECLARE_int32_(default_mock_behavior);
+
+namespace testing {
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses the command line for the flags
+// that Google Mock recognizes.  Whenever a Google Mock flag is seen,
+// it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+GTEST_API_ void InitGoogleMock(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv);
+
+// This overloaded version can be used on Arduino/embedded platforms where
+// there is no argc/argv.
+GTEST_API_ void InitGoogleMock();
+
+}  // namespace testing
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/custom/README.md b/3rd-party/googletest/googlemock/include/gmock/internal/custom/README.md
new file mode 100644
index 0000000..9c4874f
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/custom/README.md
@@ -0,0 +1,18 @@
+# Customization Points
+
+The custom directory is an injection point for custom user configurations.
+
+## Header `gmock-port.h`
+
+The following macros can be defined:
+
+### Flag related macros:
+
+*   `GMOCK_DECLARE_bool_(name)`
+*   `GMOCK_DECLARE_int32_(name)`
+*   `GMOCK_DECLARE_string_(name)`
+*   `GMOCK_DEFINE_bool_(name, default_val, doc)`
+*   `GMOCK_DEFINE_int32_(name, default_val, doc)`
+*   `GMOCK_DEFINE_string_(name, default_val, doc)`
+*   `GMOCK_FLAG_GET(flag_name)`
+*   `GMOCK_FLAG_SET(flag_name, value)`
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h b/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h
new file mode 100644
index 0000000..bbcad31
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h
@@ -0,0 +1,7 @@
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h b/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h
new file mode 100644
index 0000000..bb7dcba
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h
@@ -0,0 +1,37 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Injection point for custom user configurations. See README for details
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-port.h b/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-port.h
new file mode 100644
index 0000000..f055f75
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/custom/gmock-port.h
@@ -0,0 +1,40 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h b/3rd-party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
new file mode 100644
index 0000000..b7685f5
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -0,0 +1,489 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+
+#include <stdio.h>
+
+#include <ostream>  // NOLINT
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+template <typename>
+class Matcher;
+
+namespace internal {
+
+// Silence MSVC C4100 (unreferenced formal parameter) and
+// C4805('==': unsafe mix of type 'const int' and type 'const bool')
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100 4805)
+
+// Joins a vector of strings as if they are fields of a tuple; returns
+// the joined string.
+GTEST_API_ std::string JoinAsKeyValueTuple(
+    const std::vector<const char*>& names, const Strings& values);
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name);
+
+// GetRawPointer(p) returns the raw pointer underlying p when p is a
+// smart pointer, or returns p itself when p is already a raw pointer.
+// The following default implementation is for the smart pointer case.
+template <typename Pointer>
+inline const typename Pointer::element_type* GetRawPointer(const Pointer& p) {
+  return p.get();
+}
+// This overload version is for std::reference_wrapper, which does not work with
+// the overload above, as it does not have an `element_type`.
+template <typename Element>
+inline const Element* GetRawPointer(const std::reference_wrapper<Element>& r) {
+  return &r.get();
+}
+
+// This overloaded version is for the raw pointer case.
+template <typename Element>
+inline Element* GetRawPointer(Element* p) {
+  return p;
+}
+
+// Default definitions for all compilers.
+// NOTE: If you implement support for other compilers, make sure to avoid
+// unexpected overlaps.
+// (e.g., Clang also processes #pragma GCC, and clang-cl also handles _MSC_VER.)
+#define GMOCK_INTERNAL_WARNING_PUSH()
+#define GMOCK_INTERNAL_WARNING_CLANG(Level, Name)
+#define GMOCK_INTERNAL_WARNING_POP()
+
+#if defined(__clang__)
+#undef GMOCK_INTERNAL_WARNING_PUSH
+#define GMOCK_INTERNAL_WARNING_PUSH() _Pragma("clang diagnostic push")
+#undef GMOCK_INTERNAL_WARNING_CLANG
+#define GMOCK_INTERNAL_WARNING_CLANG(Level, Warning) \
+  _Pragma(GMOCK_PP_INTERNAL_STRINGIZE(clang diagnostic Level Warning))
+#undef GMOCK_INTERNAL_WARNING_POP
+#define GMOCK_INTERNAL_WARNING_POP() _Pragma("clang diagnostic pop")
+#endif
+
+// MSVC treats wchar_t as a native type usually, but treats it as the
+// same as unsigned short when the compiler option /Zc:wchar_t- is
+// specified.  It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
+// is a native type.
+#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)
+// wchar_t is a typedef.
+#else
+#define GMOCK_WCHAR_T_IS_NATIVE_ 1
+#endif
+
+// In what follows, we use the term "kind" to indicate whether a type
+// is bool, an integer type (excluding bool), a floating-point type,
+// or none of them.  This categorization is useful for determining
+// when a matcher argument type can be safely converted to another
+// type in the implementation of SafeMatcherCast.
+enum TypeKind { kBool, kInteger, kFloatingPoint, kOther };
+
+// KindOf<T>::value is the kind of type T.
+template <typename T>
+struct KindOf {
+  enum { value = kOther };  // The default kind.
+};
+
+// This macro declares that the kind of 'type' is 'kind'.
+#define GMOCK_DECLARE_KIND_(type, kind) \
+  template <>                           \
+  struct KindOf<type> {                 \
+    enum { value = kind };              \
+  }
+
+GMOCK_DECLARE_KIND_(bool, kBool);
+
+// All standard integer types.
+GMOCK_DECLARE_KIND_(char, kInteger);
+GMOCK_DECLARE_KIND_(signed char, kInteger);
+GMOCK_DECLARE_KIND_(unsigned char, kInteger);
+GMOCK_DECLARE_KIND_(short, kInteger);           // NOLINT
+GMOCK_DECLARE_KIND_(unsigned short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(int, kInteger);
+GMOCK_DECLARE_KIND_(unsigned int, kInteger);
+GMOCK_DECLARE_KIND_(long, kInteger);                // NOLINT
+GMOCK_DECLARE_KIND_(unsigned long, kInteger);       // NOLINT
+GMOCK_DECLARE_KIND_(long long, kInteger);           // NOLINT
+GMOCK_DECLARE_KIND_(unsigned long long, kInteger);  // NOLINT
+
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DECLARE_KIND_(wchar_t, kInteger);
+#endif
+
+// All standard floating-point types.
+GMOCK_DECLARE_KIND_(float, kFloatingPoint);
+GMOCK_DECLARE_KIND_(double, kFloatingPoint);
+GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
+
+#undef GMOCK_DECLARE_KIND_
+
+// Evaluates to the kind of 'type'.
+#define GMOCK_KIND_OF_(type)                   \
+  static_cast< ::testing::internal::TypeKind>( \
+      ::testing::internal::KindOf<type>::value)
+
+// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
+// is true if and only if arithmetic type From can be losslessly converted to
+// arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types, kFromKind is the kind of
+// From, and kToKind is the kind of To; the value is
+// implementation-defined when the above pre-condition is violated.
+template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
+using LosslessArithmeticConvertibleImpl = std::integral_constant<
+    bool,
+    // clang-format off
+      // Converting from bool is always lossless
+      (kFromKind == kBool) ? true
+      // Converting between any other type kinds will be lossy if the type
+      // kinds are not the same.
+    : (kFromKind != kToKind) ? false
+    : (kFromKind == kInteger &&
+       // Converting between integers of different widths is allowed so long
+       // as the conversion does not go from signed to unsigned.
+      (((sizeof(From) < sizeof(To)) &&
+        !(std::is_signed<From>::value && !std::is_signed<To>::value)) ||
+       // Converting between integers of the same width only requires the
+       // two types to have the same signedness.
+       ((sizeof(From) == sizeof(To)) &&
+        (std::is_signed<From>::value == std::is_signed<To>::value)))
+       ) ? true
+      // Floating point conversions are lossless if and only if `To` is at least
+      // as wide as `From`.
+    : (kFromKind == kFloatingPoint && (sizeof(From) <= sizeof(To))) ? true
+    : false
+    // clang-format on
+    >;
+
+// LosslessArithmeticConvertible<From, To>::value is true if and only if
+// arithmetic type From can be losslessly converted to arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types; the value is
+// implementation-defined when the above pre-condition is violated.
+template <typename From, typename To>
+using LosslessArithmeticConvertible =
+    LosslessArithmeticConvertibleImpl<GMOCK_KIND_OF_(From), From,
+                                      GMOCK_KIND_OF_(To), To>;
+
+// This interface knows how to report a Google Mock failure (either
+// non-fatal or fatal).
+class FailureReporterInterface {
+ public:
+  // The type of a failure (either non-fatal or fatal).
+  enum FailureType { kNonfatal, kFatal };
+
+  virtual ~FailureReporterInterface() = default;
+
+  // Reports a failure that occurred at the given source file location.
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const std::string& message) = 0;
+};
+
+// Returns the failure reporter used by Google Mock.
+GTEST_API_ FailureReporterInterface* GetFailureReporter();
+
+// Asserts that condition is true; aborts the process with the given
+// message if condition is false.  We cannot use LOG(FATAL) or CHECK()
+// as Google Mock might be used to mock the log sink itself.  We
+// inline this function to prevent it from showing up in the stack
+// trace.
+inline void Assert(bool condition, const char* file, int line,
+                   const std::string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::kFatal, file,
+                                        line, msg);
+  }
+}
+inline void Assert(bool condition, const char* file, int line) {
+  Assert(condition, file, line, "Assertion failed.");
+}
+
+// Verifies that condition is true; generates a non-fatal failure if
+// condition is false.
+inline void Expect(bool condition, const char* file, int line,
+                   const std::string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::kNonfatal,
+                                        file, line, msg);
+  }
+}
+inline void Expect(bool condition, const char* file, int line) {
+  Expect(condition, file, line, "Expectation failed.");
+}
+
+// Severity level of a log.
+enum LogSeverity { kInfo = 0, kWarning = 1 };
+
+// Valid values for the --gmock_verbose flag.
+
+// All logs (informational and warnings) are printed.
+const char kInfoVerbosity[] = "info";
+// Only warnings are printed.
+const char kWarningVerbosity[] = "warning";
+// No logs are printed.
+const char kErrorVerbosity[] = "error";
+
+// Returns true if and only if a log with the given severity is visible
+// according to the --gmock_verbose flag.
+GTEST_API_ bool LogIsVisible(LogSeverity severity);
+
+// Prints the given message to stdout if and only if 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+GTEST_API_ void Log(LogSeverity severity, const std::string& message,
+                    int stack_frames_to_skip);
+
+// A marker class that is used to resolve parameterless expectations to the
+// correct overload. This must not be instantiable, to prevent client code from
+// accidentally resolving to the overload; for example:
+//
+//    ON_CALL(mock, Method({}, nullptr))...
+//
+class WithoutMatchers {
+ private:
+  WithoutMatchers() {}
+  friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
+};
+
+// Internal use only: access the singleton instance of WithoutMatchers.
+GTEST_API_ WithoutMatchers GetWithoutMatchers();
+
+// Invalid<T>() is usable as an expression of type T, but will terminate
+// the program with an assertion failure if actually run.  This is useful
+// when a value of type T is needed for compilation, but the statement
+// will not really be executed (or we don't care if the statement
+// crashes).
+template <typename T>
+inline T Invalid() {
+  Assert(/*condition=*/false, /*file=*/"", /*line=*/-1,
+         "Internal error: attempt to return invalid value");
+#if defined(__GNUC__) || defined(__clang__)
+  __builtin_unreachable();
+#elif defined(_MSC_VER)
+  __assume(0);
+#else
+  return Invalid<T>();
+#endif
+}
+
+// Given a raw type (i.e. having no top-level reference or const
+// modifier) RawContainer that's either an STL-style container or a
+// native array, class StlContainerView<RawContainer> has the
+// following members:
+//
+//   - type is a type that provides an STL-style container view to
+//     (i.e. implements the STL container concept for) RawContainer;
+//   - const_reference is a type that provides a reference to a const
+//     RawContainer;
+//   - ConstReference(raw_container) returns a const reference to an STL-style
+//     container view to raw_container, which is a RawContainer.
+//   - Copy(raw_container) returns an STL-style container view of a
+//     copy of raw_container, which is a RawContainer.
+//
+// This generic version is used when RawContainer itself is already an
+// STL-style container.
+template <class RawContainer>
+class StlContainerView {
+ public:
+  typedef RawContainer type;
+  typedef const type& const_reference;
+
+  static const_reference ConstReference(const RawContainer& container) {
+    static_assert(!std::is_const<RawContainer>::value,
+                  "RawContainer type must not be const");
+    return container;
+  }
+  static type Copy(const RawContainer& container) { return container; }
+};
+
+// This specialization is used when RawContainer is a native array type.
+template <typename Element, size_t N>
+class StlContainerView<Element[N]> {
+ public:
+  typedef typename std::remove_const<Element>::type RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  // NativeArray<T> can represent a native array either by value or by
+  // reference (selected by a constructor argument), so 'const type'
+  // can be used to reference a const native array.  We cannot
+  // 'typedef const type& const_reference' here, as that would mean
+  // ConstReference() has to return a reference to a local variable.
+  typedef const type const_reference;
+
+  static const_reference ConstReference(const Element (&array)[N]) {
+    static_assert(std::is_same<Element, RawElement>::value,
+                  "Element type must not be const");
+    return type(array, N, RelationToSourceReference());
+  }
+  static type Copy(const Element (&array)[N]) {
+    return type(array, N, RelationToSourceCopy());
+  }
+};
+
+// This specialization is used when RawContainer is a native array
+// represented as a (pointer, size) tuple.
+template <typename ElementPointer, typename Size>
+class StlContainerView< ::std::tuple<ElementPointer, Size> > {
+ public:
+  typedef typename std::remove_const<
+      typename std::pointer_traits<ElementPointer>::element_type>::type
+      RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  typedef const type const_reference;
+
+  static const_reference ConstReference(
+      const ::std::tuple<ElementPointer, Size>& array) {
+    return type(std::get<0>(array), std::get<1>(array),
+                RelationToSourceReference());
+  }
+  static type Copy(const ::std::tuple<ElementPointer, Size>& array) {
+    return type(std::get<0>(array), std::get<1>(array), RelationToSourceCopy());
+  }
+};
+
+// The following specialization prevents the user from instantiating
+// StlContainer with a reference type.
+template <typename T>
+class StlContainerView<T&>;
+
+// A type transform to remove constness from the first part of a pair.
+// Pairs like that are used as the value_type of associative containers,
+// and this transform produces a similar but assignable pair.
+template <typename T>
+struct RemoveConstFromKey {
+  typedef T type;
+};
+
+// Partially specialized to remove constness from std::pair<const K, V>.
+template <typename K, typename V>
+struct RemoveConstFromKey<std::pair<const K, V> > {
+  typedef std::pair<K, V> type;
+};
+
+// Emit an assertion failure due to incorrect DoDefault() usage. Out-of-lined to
+// reduce code size.
+GTEST_API_ void IllegalDoDefault(const char* file, int line);
+
+template <typename F, typename Tuple, size_t... Idx>
+auto ApplyImpl(F&& f, Tuple&& args, std::index_sequence<Idx...>)
+    -> decltype(std::forward<F>(f)(
+        std::get<Idx>(std::forward<Tuple>(args))...)) {
+  return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
+}
+
+// Apply the function to a tuple of arguments.
+template <typename F, typename Tuple>
+auto Apply(F&& f, Tuple&& args)
+    -> decltype(ApplyImpl(
+        std::forward<F>(f), std::forward<Tuple>(args),
+        std::make_index_sequence<std::tuple_size<
+            typename std::remove_reference<Tuple>::type>::value>())) {
+  return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
+                   std::make_index_sequence<std::tuple_size<
+                       typename std::remove_reference<Tuple>::type>::value>());
+}
+
+// Template struct Function<F>, where F must be a function type, contains
+// the following typedefs:
+//
+//   Result:               the function's return type.
+//   Arg<N>:               the type of the N-th argument, where N starts with 0.
+//   ArgumentTuple:        the tuple type consisting of all parameters of F.
+//   ArgumentMatcherTuple: the tuple type consisting of Matchers for all
+//                         parameters of F.
+//   MakeResultVoid:       the function type obtained by substituting void
+//                         for the return type of F.
+//   MakeResultIgnoredValue:
+//                         the function type obtained by substituting Something
+//                         for the return type of F.
+template <typename T>
+struct Function;
+
+template <typename R, typename... Args>
+struct Function<R(Args...)> {
+  using Result = R;
+  static constexpr size_t ArgumentCount = sizeof...(Args);
+  template <size_t I>
+  using Arg = ElemFromList<I, Args...>;
+  using ArgumentTuple = std::tuple<Args...>;
+  using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>;
+  using MakeResultVoid = void(Args...);
+  using MakeResultIgnoredValue = IgnoredValue(Args...);
+};
+
+#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+template <typename R, typename... Args>
+constexpr size_t Function<R(Args...)>::ArgumentCount;
+#endif
+
+// Workaround for MSVC error C2039: 'type': is not a member of 'std'
+// when std::tuple_element is used.
+// See: https://github.com/google/googletest/issues/3931
+// Can be replaced with std::tuple_element_t in C++14.
+template <size_t I, typename T>
+using TupleElement = typename std::tuple_element<I, T>::type;
+
+bool Base64Unescape(const std::string& encoded, std::string* decoded);
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100 4805
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/gmock-port.h b/3rd-party/googletest/googlemock/include/gmock/internal/gmock-port.h
new file mode 100644
index 0000000..42d36d2
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/gmock-port.h
@@ -0,0 +1,140 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Low-level types and utilities for porting Google Mock to various
+// platforms.  All macros ending with _ and symbols defined in an
+// internal namespace are subject to change without notice.  Code
+// outside Google Mock MUST NOT USE THEM DIRECTLY.  Macros that don't
+// end with _ are part of Google Mock's public API and can be used by
+// code outside Google Mock.
+
+// IWYU pragma: private, include "gmock/gmock.h"
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <cstdint>
+#include <iostream>
+
+// Most of the utilities needed for porting Google Mock are also
+// required for Google Test and are defined in gtest-port.h.
+//
+// Note to maintainers: to reduce code duplication, prefer adding
+// portability utilities to Google Test's gtest-port.h instead of
+// here, as Google Mock depends on Google Test.  Only add a utility
+// here if it's truly specific to Google Mock.
+
+#include "gmock/internal/custom/gmock-port.h"
+#include "gtest/internal/gtest-port.h"
+
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#endif
+
+// For MS Visual C++, check the compiler version. At least VS 2015 is
+// required to compile Google Mock.
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#error "At least Visual C++ 2015 (14.0) is required to compile Google Mock."
+#endif
+
+// Macro for referencing flags.  This is public as we want the user to
+// use this syntax to reference Google Mock flags.
+#define GMOCK_FLAG_NAME_(name) gmock_##name
+#define GMOCK_FLAG(name) FLAGS_gmock_##name
+
+// Pick a command line flags implementation.
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+
+// Macros for defining flags.
+#define GMOCK_DEFINE_bool_(name, default_val, doc) \
+  ABSL_FLAG(bool, GMOCK_FLAG_NAME_(name), default_val, doc)
+#define GMOCK_DEFINE_int32_(name, default_val, doc) \
+  ABSL_FLAG(int32_t, GMOCK_FLAG_NAME_(name), default_val, doc)
+#define GMOCK_DEFINE_string_(name, default_val, doc) \
+  ABSL_FLAG(std::string, GMOCK_FLAG_NAME_(name), default_val, doc)
+
+// Macros for declaring flags.
+#define GMOCK_DECLARE_bool_(name) \
+  ABSL_DECLARE_FLAG(bool, GMOCK_FLAG_NAME_(name))
+#define GMOCK_DECLARE_int32_(name) \
+  ABSL_DECLARE_FLAG(int32_t, GMOCK_FLAG_NAME_(name))
+#define GMOCK_DECLARE_string_(name) \
+  ABSL_DECLARE_FLAG(std::string, GMOCK_FLAG_NAME_(name))
+
+#define GMOCK_FLAG_GET(name) ::absl::GetFlag(GMOCK_FLAG(name))
+#define GMOCK_FLAG_SET(name, value) \
+  (void)(::absl::SetFlag(&GMOCK_FLAG(name), value))
+
+#else  // defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+
+// Macros for defining flags.
+#define GMOCK_DEFINE_bool_(name, default_val, doc)  \
+  namespace testing {                               \
+  GTEST_API_ bool GMOCK_FLAG(name) = (default_val); \
+  }                                                 \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GMOCK_DEFINE_int32_(name, default_val, doc)    \
+  namespace testing {                                  \
+  GTEST_API_ int32_t GMOCK_FLAG(name) = (default_val); \
+  }                                                    \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GMOCK_DEFINE_string_(name, default_val, doc)         \
+  namespace testing {                                        \
+  GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val); \
+  }                                                          \
+  static_assert(true, "no-op to require trailing semicolon")
+
+// Macros for declaring flags.
+#define GMOCK_DECLARE_bool_(name)          \
+  namespace testing {                      \
+  GTEST_API_ extern bool GMOCK_FLAG(name); \
+  }                                        \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GMOCK_DECLARE_int32_(name)            \
+  namespace testing {                         \
+  GTEST_API_ extern int32_t GMOCK_FLAG(name); \
+  }                                           \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GMOCK_DECLARE_string_(name)                 \
+  namespace testing {                               \
+  GTEST_API_ extern ::std::string GMOCK_FLAG(name); \
+  }                                                 \
+  static_assert(true, "no-op to require trailing semicolon")
+
+#define GMOCK_FLAG_GET(name) ::testing::GMOCK_FLAG(name)
+#define GMOCK_FLAG_SET(name, value) (void)(::testing::GMOCK_FLAG(name) = value)
+
+#endif  // defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
diff --git a/3rd-party/googletest/googlemock/include/gmock/internal/gmock-pp.h b/3rd-party/googletest/googlemock/include/gmock/internal/gmock-pp.h
new file mode 100644
index 0000000..94d61c0
--- /dev/null
+++ b/3rd-party/googletest/googlemock/include/gmock/internal/gmock-pp.h
@@ -0,0 +1,279 @@
+#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_
+#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_
+
+// Expands and concatenates the arguments. Constructed macros reevaluate.
+#define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2)
+
+// Expands and stringifies the only argument.
+#define GMOCK_PP_STRINGIZE(...) GMOCK_PP_INTERNAL_STRINGIZE(__VA_ARGS__)
+
+// Returns empty. Given a variadic number of arguments.
+#define GMOCK_PP_EMPTY(...)
+
+// Returns a comma. Given a variadic number of arguments.
+#define GMOCK_PP_COMMA(...) ,
+
+// Returns the only argument.
+#define GMOCK_PP_IDENTITY(_1) _1
+
+// Evaluates to the number of arguments after expansion.
+//
+//   #define PAIR x, y
+//
+//   GMOCK_PP_NARG() => 1
+//   GMOCK_PP_NARG(x) => 1
+//   GMOCK_PP_NARG(x, y) => 2
+//   GMOCK_PP_NARG(PAIR) => 2
+//
+// Requires: the number of arguments after expansion is at most 15.
+#define GMOCK_PP_NARG(...) \
+  GMOCK_PP_INTERNAL_16TH(  \
+      (__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+
+// Returns 1 if the expansion of arguments has an unprotected comma. Otherwise
+// returns 0. Requires no more than 15 unprotected commas.
+#define GMOCK_PP_HAS_COMMA(...) \
+  GMOCK_PP_INTERNAL_16TH(       \
+      (__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0))
+
+// Returns the first argument.
+#define GMOCK_PP_HEAD(...) GMOCK_PP_INTERNAL_HEAD((__VA_ARGS__, unusedArg))
+
+// Returns the tail. A variadic list of all arguments minus the first. Requires
+// at least one argument.
+#define GMOCK_PP_TAIL(...) GMOCK_PP_INTERNAL_TAIL((__VA_ARGS__))
+
+// Calls CAT(_Macro, NARG(__VA_ARGS__))(__VA_ARGS__)
+#define GMOCK_PP_VARIADIC_CALL(_Macro, ...) \
+  GMOCK_PP_IDENTITY(                        \
+      GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__))
+
+// If the arguments after expansion have no tokens, evaluates to `1`. Otherwise
+// evaluates to `0`.
+//
+// Requires: * the number of arguments after expansion is at most 15.
+//           * If the argument is a macro, it must be able to be called with one
+//             argument.
+//
+// Implementation details:
+//
+// There is one case when it generates a compile error: if the argument is macro
+// that cannot be called with one argument.
+//
+//   #define M(a, b)  // it doesn't matter what it expands to
+//
+//   // Expected: expands to `0`.
+//   // Actual: compile error.
+//   GMOCK_PP_IS_EMPTY(M)
+//
+// There are 4 cases tested:
+//
+// * __VA_ARGS__ possible expansion has no unparen'd commas. Expected 0.
+// * __VA_ARGS__ possible expansion is not enclosed in parenthesis. Expected 0.
+// * __VA_ARGS__ possible expansion is not a macro that ()-evaluates to a comma.
+//   Expected 0
+// * __VA_ARGS__ is empty, or has unparen'd commas, or is enclosed in
+//   parenthesis, or is a macro that ()-evaluates to comma. Expected 1.
+//
+// We trigger detection on '0001', i.e. on empty.
+#define GMOCK_PP_IS_EMPTY(...)                                               \
+  GMOCK_PP_INTERNAL_IS_EMPTY(GMOCK_PP_HAS_COMMA(__VA_ARGS__),                \
+                             GMOCK_PP_HAS_COMMA(GMOCK_PP_COMMA __VA_ARGS__), \
+                             GMOCK_PP_HAS_COMMA(__VA_ARGS__()),              \
+                             GMOCK_PP_HAS_COMMA(GMOCK_PP_COMMA __VA_ARGS__()))
+
+// Evaluates to _Then if _Cond is 1 and _Else if _Cond is 0.
+#define GMOCK_PP_IF(_Cond, _Then, _Else) \
+  GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IF_, _Cond)(_Then, _Else)
+
+// Similar to GMOCK_PP_IF but takes _Then and _Else in parentheses.
+//
+// GMOCK_PP_GENERIC_IF(1, (a, b, c), (d, e, f)) => a, b, c
+// GMOCK_PP_GENERIC_IF(0, (a, b, c), (d, e, f)) => d, e, f
+//
+#define GMOCK_PP_GENERIC_IF(_Cond, _Then, _Else) \
+  GMOCK_PP_REMOVE_PARENS(GMOCK_PP_IF(_Cond, _Then, _Else))
+
+// Evaluates to the number of arguments after expansion. Identifies 'empty' as
+// 0.
+//
+//   #define PAIR x, y
+//
+//   GMOCK_PP_NARG0() => 0
+//   GMOCK_PP_NARG0(x) => 1
+//   GMOCK_PP_NARG0(x, y) => 2
+//   GMOCK_PP_NARG0(PAIR) => 2
+//
+// Requires: * the number of arguments after expansion is at most 15.
+//           * If the argument is a macro, it must be able to be called with one
+//             argument.
+#define GMOCK_PP_NARG0(...) \
+  GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(__VA_ARGS__), 0, GMOCK_PP_NARG(__VA_ARGS__))
+
+// Expands to 1 if the first argument starts with something in parentheses,
+// otherwise to 0.
+#define GMOCK_PP_IS_BEGIN_PARENS(...)                              \
+  GMOCK_PP_HEAD(GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_, \
+                             GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C __VA_ARGS__))
+
+// Expands to 1 is there is only one argument and it is enclosed in parentheses.
+#define GMOCK_PP_IS_ENCLOSED_PARENS(...)             \
+  GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(__VA_ARGS__), \
+              GMOCK_PP_IS_EMPTY(GMOCK_PP_EMPTY __VA_ARGS__), 0)
+
+// Remove the parens, requires GMOCK_PP_IS_ENCLOSED_PARENS(args) => 1.
+#define GMOCK_PP_REMOVE_PARENS(...) GMOCK_PP_INTERNAL_REMOVE_PARENS __VA_ARGS__
+
+// Expands to _Macro(0, _Data, e1) _Macro(1, _Data, e2) ... _Macro(K -1, _Data,
+// eK) as many of GMOCK_INTERNAL_NARG0 _Tuple.
+// Requires: * |_Macro| can be called with 3 arguments.
+//           * |_Tuple| expansion has no more than 15 elements.
+#define GMOCK_PP_FOR_EACH(_Macro, _Data, _Tuple)                        \
+  GMOCK_PP_CAT(GMOCK_PP_INTERNAL_FOR_EACH_IMPL_, GMOCK_PP_NARG0 _Tuple) \
+  (0, _Macro, _Data, _Tuple)
+
+// Expands to _Macro(0, _Data, ) _Macro(1, _Data, ) ... _Macro(K - 1, _Data, )
+// Empty if _K = 0.
+// Requires: * |_Macro| can be called with 3 arguments.
+//           * |_K| literal between 0 and 15
+#define GMOCK_PP_REPEAT(_Macro, _Data, _N)           \
+  GMOCK_PP_CAT(GMOCK_PP_INTERNAL_FOR_EACH_IMPL_, _N) \
+  (0, _Macro, _Data, GMOCK_PP_INTENRAL_EMPTY_TUPLE)
+
+// Increments the argument, requires the argument to be between 0 and 15.
+#define GMOCK_PP_INC(_i) GMOCK_PP_CAT(GMOCK_PP_INTERNAL_INC_, _i)
+
+// Returns comma if _i != 0. Requires _i to be between 0 and 15.
+#define GMOCK_PP_COMMA_IF(_i) GMOCK_PP_CAT(GMOCK_PP_INTERNAL_COMMA_IF_, _i)
+
+// Internal details follow. Do not use any of these symbols outside of this
+// file or we will break your code.
+#define GMOCK_PP_INTENRAL_EMPTY_TUPLE (, , , , , , , , , , , , , , , )
+#define GMOCK_PP_INTERNAL_CAT(_1, _2) _1##_2
+#define GMOCK_PP_INTERNAL_STRINGIZE(...) #__VA_ARGS__
+#define GMOCK_PP_INTERNAL_CAT_5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5
+#define GMOCK_PP_INTERNAL_IS_EMPTY(_1, _2, _3, _4)                             \
+  GMOCK_PP_HAS_COMMA(GMOCK_PP_INTERNAL_CAT_5(GMOCK_PP_INTERNAL_IS_EMPTY_CASE_, \
+                                             _1, _2, _3, _4))
+#define GMOCK_PP_INTERNAL_IS_EMPTY_CASE_0001 ,
+#define GMOCK_PP_INTERNAL_IF_1(_Then, _Else) _Then
+#define GMOCK_PP_INTERNAL_IF_0(_Then, _Else) _Else
+
+// Because of MSVC treating a token with a comma in it as a single token when
+// passed to another macro, we need to force it to evaluate it as multiple
+// tokens. We do that by using a "IDENTITY(MACRO PARENTHESIZED_ARGS)" macro. We
+// define one per possible macro that relies on this behavior. Note "_Args" must
+// be parenthesized.
+#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \
+                                        _10, _11, _12, _13, _14, _15, _16,  \
+                                        ...)                                \
+  _16
+#define GMOCK_PP_INTERNAL_16TH(_Args) \
+  GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_16TH _Args)
+#define GMOCK_PP_INTERNAL_INTERNAL_HEAD(_1, ...) _1
+#define GMOCK_PP_INTERNAL_HEAD(_Args) \
+  GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_HEAD _Args)
+#define GMOCK_PP_INTERNAL_INTERNAL_TAIL(_1, ...) __VA_ARGS__
+#define GMOCK_PP_INTERNAL_TAIL(_Args) \
+  GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_TAIL _Args)
+
+#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C(...) 1 _
+#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_1 1,
+#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C \
+  0,
+#define GMOCK_PP_INTERNAL_REMOVE_PARENS(...) __VA_ARGS__
+#define GMOCK_PP_INTERNAL_INC_0 1
+#define GMOCK_PP_INTERNAL_INC_1 2
+#define GMOCK_PP_INTERNAL_INC_2 3
+#define GMOCK_PP_INTERNAL_INC_3 4
+#define GMOCK_PP_INTERNAL_INC_4 5
+#define GMOCK_PP_INTERNAL_INC_5 6
+#define GMOCK_PP_INTERNAL_INC_6 7
+#define GMOCK_PP_INTERNAL_INC_7 8
+#define GMOCK_PP_INTERNAL_INC_8 9
+#define GMOCK_PP_INTERNAL_INC_9 10
+#define GMOCK_PP_INTERNAL_INC_10 11
+#define GMOCK_PP_INTERNAL_INC_11 12
+#define GMOCK_PP_INTERNAL_INC_12 13
+#define GMOCK_PP_INTERNAL_INC_13 14
+#define GMOCK_PP_INTERNAL_INC_14 15
+#define GMOCK_PP_INTERNAL_INC_15 16
+#define GMOCK_PP_INTERNAL_COMMA_IF_0
+#define GMOCK_PP_INTERNAL_COMMA_IF_1 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_2 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_3 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_4 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_5 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_6 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_7 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_8 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_9 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_10 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_11 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_12 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_13 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_14 ,
+#define GMOCK_PP_INTERNAL_COMMA_IF_15 ,
+#define GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, _element) \
+  _Macro(_i, _Data, _element)
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_0(_i, _Macro, _Data, _Tuple)
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_1(_i, _Macro, _Data, _Tuple) \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple)
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_2(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_1(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_3(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_2(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_4(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_3(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_5(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_4(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_6(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_5(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_7(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_6(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_8(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_7(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_9(_i, _Macro, _Data, _Tuple)    \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_8(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_10(_i, _Macro, _Data, _Tuple)   \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_9(GMOCK_PP_INC(_i), _Macro, _Data,    \
+                                    (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_11(_i, _Macro, _Data, _Tuple)   \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_10(GMOCK_PP_INC(_i), _Macro, _Data,   \
+                                     (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_12(_i, _Macro, _Data, _Tuple)   \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_11(GMOCK_PP_INC(_i), _Macro, _Data,   \
+                                     (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_13(_i, _Macro, _Data, _Tuple)   \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_12(GMOCK_PP_INC(_i), _Macro, _Data,   \
+                                     (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_14(_i, _Macro, _Data, _Tuple)   \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_13(GMOCK_PP_INC(_i), _Macro, _Data,   \
+                                     (GMOCK_PP_TAIL _Tuple))
+#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_15(_i, _Macro, _Data, _Tuple)   \
+  GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
+  GMOCK_PP_INTERNAL_FOR_EACH_IMPL_14(GMOCK_PP_INC(_i), _Macro, _Data,   \
+                                     (GMOCK_PP_TAIL _Tuple))
+
+#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_
diff --git a/3rd-party/googletest/googlemock/src/gmock-all.cc b/3rd-party/googletest/googlemock/src/gmock-all.cc
new file mode 100644
index 0000000..e43c9b7
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock-all.cc
@@ -0,0 +1,46 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Google C++ Mocking Framework (Google Mock)
+//
+// This file #includes all Google Mock implementation .cc files.  The
+// purpose is to allow a user to build Google Mock by compiling this
+// file alone.
+
+// This line ensures that gmock.h can be compiled on its own, even
+// when it's fused.
+#include "gmock/gmock.h"
+
+// The following lines pull in the real gmock *.cc files.
+#include "src/gmock-cardinalities.cc"
+#include "src/gmock-internal-utils.cc"
+#include "src/gmock-matchers.cc"
+#include "src/gmock-spec-builders.cc"
+#include "src/gmock.cc"
diff --git a/3rd-party/googletest/googlemock/src/gmock-cardinalities.cc b/3rd-party/googletest/googlemock/src/gmock-cardinalities.cc
new file mode 100644
index 0000000..a7283aa
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock-cardinalities.cc
@@ -0,0 +1,155 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements cardinalities.
+
+#include "gmock/gmock-cardinalities.h"
+
+#include <limits.h>
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+namespace {
+
+// Implements the Between(m, n) cardinality.
+class BetweenCardinalityImpl : public CardinalityInterface {
+ public:
+  BetweenCardinalityImpl(int min, int max)
+      : min_(min >= 0 ? min : 0), max_(max >= min_ ? max : min_) {
+    std::stringstream ss;
+    if (min < 0) {
+      ss << "The invocation lower bound must be >= 0, " << "but is actually "
+         << min << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (max < 0) {
+      ss << "The invocation upper bound must be >= 0, " << "but is actually "
+         << max << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (min > max) {
+      ss << "The invocation upper bound (" << max
+         << ") must be >= the invocation lower bound (" << min << ").";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    }
+  }
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  int ConservativeLowerBound() const override { return min_; }
+  int ConservativeUpperBound() const override { return max_; }
+
+  bool IsSatisfiedByCallCount(int call_count) const override {
+    return min_ <= call_count && call_count <= max_;
+  }
+
+  bool IsSaturatedByCallCount(int call_count) const override {
+    return call_count >= max_;
+  }
+
+  void DescribeTo(::std::ostream* os) const override;
+
+ private:
+  const int min_;
+  const int max_;
+
+  BetweenCardinalityImpl(const BetweenCardinalityImpl&) = delete;
+  BetweenCardinalityImpl& operator=(const BetweenCardinalityImpl&) = delete;
+};
+
+// Formats "n times" in a human-friendly way.
+inline std::string FormatTimes(int n) {
+  if (n == 1) {
+    return "once";
+  } else if (n == 2) {
+    return "twice";
+  } else {
+    std::stringstream ss;
+    ss << n << " times";
+    return ss.str();
+  }
+}
+
+// Describes the Between(m, n) cardinality in human-friendly text.
+void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
+  if (min_ == 0) {
+    if (max_ == 0) {
+      *os << "never called";
+    } else if (max_ == INT_MAX) {
+      *os << "called any number of times";
+    } else {
+      *os << "called at most " << FormatTimes(max_);
+    }
+  } else if (min_ == max_) {
+    *os << "called " << FormatTimes(min_);
+  } else if (max_ == INT_MAX) {
+    *os << "called at least " << FormatTimes(min_);
+  } else {
+    // 0 < min_ < max_ < INT_MAX
+    *os << "called between " << min_ << " and " << max_ << " times";
+  }
+}
+
+}  // Unnamed namespace
+
+// Describes the given call count to an ostream.
+void Cardinality::DescribeActualCallCountTo(int actual_call_count,
+                                            ::std::ostream* os) {
+  if (actual_call_count > 0) {
+    *os << "called " << FormatTimes(actual_call_count);
+  } else {
+    *os << "never called";
+  }
+}
+
+// Creates a cardinality that allows at least n calls.
+GTEST_API_ Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
+
+// Creates a cardinality that allows at most n calls.
+GTEST_API_ Cardinality AtMost(int n) { return Between(0, n); }
+
+// Creates a cardinality that allows any number of calls.
+GTEST_API_ Cardinality AnyNumber() { return AtLeast(0); }
+
+// Creates a cardinality that allows between min and max calls.
+GTEST_API_ Cardinality Between(int min, int max) {
+  return Cardinality(new BetweenCardinalityImpl(min, max));
+}
+
+// Creates a cardinality that allows exactly n calls.
+GTEST_API_ Cardinality Exactly(int n) { return Between(n, n); }
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/src/gmock-internal-utils.cc b/3rd-party/googletest/googlemock/src/gmock-internal-utils.cc
new file mode 100644
index 0000000..96c7e30
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock-internal-utils.cc
@@ -0,0 +1,258 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#include "gmock/internal/gmock-internal-utils.h"
+
+#include <ctype.h>
+
+#include <array>
+#include <cctype>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <ostream>  // NOLINT
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Joins a vector of strings as if they are fields of a tuple; returns
+// the joined string.
+GTEST_API_ std::string JoinAsKeyValueTuple(
+    const std::vector<const char*>& names, const Strings& values) {
+  GTEST_CHECK_(names.size() == values.size());
+  if (values.empty()) {
+    return "";
+  }
+  const auto build_one = [&](const size_t i) {
+    return std::string(names[i]) + ": " + values[i];
+  };
+  std::string result = "(" + build_one(0);
+  for (size_t i = 1; i < values.size(); i++) {
+    result += ", ";
+    result += build_one(i);
+  }
+  result += ")";
+  return result;
+}
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name) {
+  std::string result;
+  char prev_char = '\0';
+  for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
+    // We don't care about the current locale as the input is
+    // guaranteed to be a valid C++ identifier name.
+    const bool starts_new_word = IsUpper(*p) ||
+                                 (!IsAlpha(prev_char) && IsLower(*p)) ||
+                                 (!IsDigit(prev_char) && IsDigit(*p));
+
+    if (IsAlNum(*p)) {
+      if (starts_new_word && !result.empty()) result += ' ';
+      result += ToLower(*p);
+    }
+  }
+  return result;
+}
+
+// This class reports Google Mock failures as Google Test failures.  A
+// user can define another class in a similar fashion if they intend to
+// use Google Mock with a testing framework other than Google Test.
+class GoogleTestFailureReporter : public FailureReporterInterface {
+ public:
+  void ReportFailure(FailureType type, const char* file, int line,
+                     const std::string& message) override {
+    AssertHelper(type == kFatal ? TestPartResult::kFatalFailure
+                                : TestPartResult::kNonFatalFailure,
+                 file, line, message.c_str()) = Message();
+    if (type == kFatal) {
+      posix::Abort();
+    }
+  }
+};
+
+// Returns the global failure reporter.  Will create a
+// GoogleTestFailureReporter and return it the first time called.
+GTEST_API_ FailureReporterInterface* GetFailureReporter() {
+  // Points to the global failure reporter used by Google Mock.  gcc
+  // guarantees that the following use of failure_reporter is
+  // thread-safe.  We may need to add additional synchronization to
+  // protect failure_reporter if we port Google Mock to other
+  // compilers.
+  static FailureReporterInterface* const failure_reporter =
+      new GoogleTestFailureReporter();
+  return failure_reporter;
+}
+
+// Protects global resources (stdout in particular) used by Log().
+static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
+
+// Returns true if and only if a log with the given severity is visible
+// according to the --gmock_verbose flag.
+GTEST_API_ bool LogIsVisible(LogSeverity severity) {
+  if (GMOCK_FLAG_GET(verbose) == kInfoVerbosity) {
+    // Always show the log if --gmock_verbose=info.
+    return true;
+  } else if (GMOCK_FLAG_GET(verbose) == kErrorVerbosity) {
+    // Always hide it if --gmock_verbose=error.
+    return false;
+  } else {
+    // If --gmock_verbose is neither "info" nor "error", we treat it
+    // as "warning" (its default value).
+    return severity == kWarning;
+  }
+}
+
+// Prints the given message to stdout if and only if 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+GTEST_API_ void Log(LogSeverity severity, const std::string& message,
+                    int stack_frames_to_skip) {
+  if (!LogIsVisible(severity)) return;
+
+  // Ensures that logs from different threads don't interleave.
+  MutexLock l(&g_log_mutex);
+
+  if (severity == kWarning) {
+    // Prints a GMOCK WARNING marker to make the warnings easily searchable.
+    std::cout << "\nGMOCK WARNING:";
+  }
+  // Pre-pends a new-line to message if it doesn't start with one.
+  if (message.empty() || message[0] != '\n') {
+    std::cout << "\n";
+  }
+  std::cout << message;
+  if (stack_frames_to_skip >= 0) {
+#ifdef NDEBUG
+    // In opt mode, we have to be conservative and skip no stack frame.
+    const int actual_to_skip = 0;
+#else
+    // In dbg mode, we can do what the caller tell us to do (plus one
+    // for skipping this function's stack frame).
+    const int actual_to_skip = stack_frames_to_skip + 1;
+#endif  // NDEBUG
+
+    // Appends a new-line to message if it doesn't end with one.
+    if (!message.empty() && *message.rbegin() != '\n') {
+      std::cout << "\n";
+    }
+    std::cout << "Stack trace:\n"
+              << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+                     actual_to_skip);
+  }
+  std::cout << ::std::flush;
+}
+
+GTEST_API_ WithoutMatchers GetWithoutMatchers() { return WithoutMatchers(); }
+
+GTEST_API_ void IllegalDoDefault(const char* file, int line) {
+  internal::Assert(
+      false, file, line,
+      "You are using DoDefault() inside a composite action like "
+      "DoAll() or WithArgs().  This is not supported for technical "
+      "reasons.  Please instead spell out the default action, or "
+      "assign the default action to an Action variable and use "
+      "the variable in various places.");
+}
+
+constexpr char UndoWebSafeEncoding(char c) {
+  return c == '-' ? '+' : c == '_' ? '/' : c;
+}
+
+constexpr char UnBase64Impl(char c, const char* const base64, char carry) {
+  return *base64 == 0 ? static_cast<char>(65)
+         : *base64 == c
+             ? carry
+             : UnBase64Impl(c, base64 + 1, static_cast<char>(carry + 1));
+}
+
+template <size_t... I>
+constexpr std::array<char, 256> UnBase64Impl(std::index_sequence<I...>,
+                                             const char* const base64) {
+  return {
+      {UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}};
+}
+
+constexpr std::array<char, 256> UnBase64(const char* const base64) {
+  return UnBase64Impl(std::make_index_sequence<256>{}, base64);
+}
+
+static constexpr char kBase64[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static constexpr std::array<char, 256> kUnBase64 = UnBase64(kBase64);
+
+bool Base64Unescape(const std::string& encoded, std::string* decoded) {
+  decoded->clear();
+  size_t encoded_len = encoded.size();
+  decoded->reserve(3 * (encoded_len / 4) + (encoded_len % 4));
+  int bit_pos = 0;
+  char dst = 0;
+  for (int src : encoded) {
+    if (std::isspace(src) || src == '=') {
+      continue;
+    }
+    char src_bin = kUnBase64[static_cast<size_t>(src)];
+    if (src_bin >= 64) {
+      decoded->clear();
+      return false;
+    }
+    if (bit_pos == 0) {
+      dst |= static_cast<char>(src_bin << 2);
+      bit_pos = 6;
+    } else {
+      dst |= static_cast<char>(src_bin >> (bit_pos - 2));
+      decoded->push_back(dst);
+      dst = static_cast<char>(src_bin << (10 - bit_pos));
+      bit_pos = (bit_pos + 6) % 8;
+    }
+  }
+  return true;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/src/gmock-matchers.cc b/3rd-party/googletest/googlemock/src/gmock-matchers.cc
new file mode 100644
index 0000000..277add6
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock-matchers.cc
@@ -0,0 +1,478 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements Matcher<const string&>, Matcher<string>, and
+// utilities for defining matchers.
+
+#include "gmock/gmock-matchers.h"
+
+#include <string.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace testing {
+namespace internal {
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+GTEST_API_ std::string FormatMatcherDescription(
+    bool negation, const char* matcher_name,
+    const std::vector<const char*>& param_names, const Strings& param_values) {
+  std::string result = ConvertIdentifierNameToWords(matcher_name);
+  if (!param_values.empty()) {
+    result += " " + JoinAsKeyValueTuple(param_names, param_values);
+  }
+  return negation ? "not (" + result + ")" : result;
+}
+
+// FindMaxBipartiteMatching and its helper class.
+//
+// Uses the well-known Ford-Fulkerson max flow method to find a maximum
+// bipartite matching. Flow is considered to be from left to right.
+// There is an implicit source node that is connected to all of the left
+// nodes, and an implicit sink node that is connected to all of the
+// right nodes. All edges have unit capacity.
+//
+// Neither the flow graph nor the residual flow graph are represented
+// explicitly. Instead, they are implied by the information in 'graph' and
+// a vector<int> called 'left_' whose elements are initialized to the
+// value kUnused. This represents the initial state of the algorithm,
+// where the flow graph is empty, and the residual flow graph has the
+// following edges:
+//   - An edge from source to each left_ node
+//   - An edge from each right_ node to sink
+//   - An edge from each left_ node to each right_ node, if the
+//     corresponding edge exists in 'graph'.
+//
+// When the TryAugment() method adds a flow, it sets left_[l] = r for some
+// nodes l and r. This induces the following changes:
+//   - The edges (source, l), (l, r), and (r, sink) are added to the
+//     flow graph.
+//   - The same three edges are removed from the residual flow graph.
+//   - The reverse edges (l, source), (r, l), and (sink, r) are added
+//     to the residual flow graph, which is a directional graph
+//     representing unused flow capacity.
+//
+// When the method augments a flow (moving left_[l] from some r1 to some
+// other r2), this can be thought of as "undoing" the above steps with
+// respect to r1 and "redoing" them with respect to r2.
+//
+// It bears repeating that the flow graph and residual flow graph are
+// never represented explicitly, but can be derived by looking at the
+// information in 'graph' and in left_.
+//
+// As an optimization, there is a second vector<int> called right_ which
+// does not provide any new information. Instead, it enables more
+// efficient queries about edges entering or leaving the right-side nodes
+// of the flow or residual flow graphs. The following invariants are
+// maintained:
+//
+// left[l] == kUnused or right[left[l]] == l
+// right[r] == kUnused or left[right[r]] == r
+//
+// . [ source ]                                        .
+// .   |||                                             .
+// .   |||                                             .
+// .   ||\--> left[0]=1  ---\    right[0]=-1 ----\     .
+// .   ||                   |                    |     .
+// .   |\---> left[1]=-1    \--> right[1]=0  ---\|     .
+// .   |                                        ||     .
+// .   \----> left[2]=2  ------> right[2]=2  --\||     .
+// .                                           |||     .
+// .         elements           matchers       vvv     .
+// .                                         [ sink ]  .
+//
+// See Also:
+//   [1] Cormen, et al (2001). "Section 26.2: The Ford-Fulkerson method".
+//       "Introduction to Algorithms (Second ed.)", pp. 651-664.
+//   [2] "Ford-Fulkerson algorithm", Wikipedia,
+//       'https://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm'
+class MaxBipartiteMatchState {
+ public:
+  explicit MaxBipartiteMatchState(const MatchMatrix& graph)
+      : graph_(&graph),
+        left_(graph_->LhsSize(), kUnused),
+        right_(graph_->RhsSize(), kUnused) {}
+
+  // Returns the edges of a maximal match, each in the form {left, right}.
+  ElementMatcherPairs Compute() {
+    // 'seen' is used for path finding { 0: unseen, 1: seen }.
+    ::std::vector<char> seen;
+    // Searches the residual flow graph for a path from each left node to
+    // the sink in the residual flow graph, and if one is found, add flow
+    // to the graph. It's okay to search through the left nodes once. The
+    // edge from the implicit source node to each previously-visited left
+    // node will have flow if that left node has any path to the sink
+    // whatsoever. Subsequent augmentations can only add flow to the
+    // network, and cannot take away that previous flow unit from the source.
+    // Since the source-to-left edge can only carry one flow unit (or,
+    // each element can be matched to only one matcher), there is no need
+    // to visit the left nodes more than once looking for augmented paths.
+    // The flow is known to be possible or impossible by looking at the
+    // node once.
+    for (size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) {
+      // Reset the path-marking vector and try to find a path from
+      // source to sink starting at the left_[ilhs] node.
+      GTEST_CHECK_(left_[ilhs] == kUnused)
+          << "ilhs: " << ilhs << ", left_[ilhs]: " << left_[ilhs];
+      // 'seen' initialized to 'graph_->RhsSize()' copies of 0.
+      seen.assign(graph_->RhsSize(), 0);
+      TryAugment(ilhs, &seen);
+    }
+    ElementMatcherPairs result;
+    for (size_t ilhs = 0; ilhs < left_.size(); ++ilhs) {
+      size_t irhs = left_[ilhs];
+      if (irhs == kUnused) continue;
+      result.push_back(ElementMatcherPair(ilhs, irhs));
+    }
+    return result;
+  }
+
+ private:
+  static const size_t kUnused = static_cast<size_t>(-1);
+
+  // Perform a depth-first search from left node ilhs to the sink.  If a
+  // path is found, flow is added to the network by linking the left and
+  // right vector elements corresponding each segment of the path.
+  // Returns true if a path to sink was found, which means that a unit of
+  // flow was added to the network. The 'seen' vector elements correspond
+  // to right nodes and are marked to eliminate cycles from the search.
+  //
+  // Left nodes will only be explored at most once because they
+  // are accessible from at most one right node in the residual flow
+  // graph.
+  //
+  // Note that left_[ilhs] is the only element of left_ that TryAugment will
+  // potentially transition from kUnused to another value. Any other
+  // left_ element holding kUnused before TryAugment will be holding it
+  // when TryAugment returns.
+  //
+  bool TryAugment(size_t ilhs, ::std::vector<char>* seen) {
+    for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
+      if ((*seen)[irhs]) continue;
+      if (!graph_->HasEdge(ilhs, irhs)) continue;
+      // There's an available edge from ilhs to irhs.
+      (*seen)[irhs] = 1;
+      // Next a search is performed to determine whether
+      // this edge is a dead end or leads to the sink.
+      //
+      // right_[irhs] == kUnused means that there is residual flow from
+      // right node irhs to the sink, so we can use that to finish this
+      // flow path and return success.
+      //
+      // Otherwise there is residual flow to some ilhs. We push flow
+      // along that path and call ourselves recursively to see if this
+      // ultimately leads to sink.
+      if (right_[irhs] == kUnused || TryAugment(right_[irhs], seen)) {
+        // Add flow from left_[ilhs] to right_[irhs].
+        left_[ilhs] = irhs;
+        right_[irhs] = ilhs;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  const MatchMatrix* graph_;  // not owned
+  // Each element of the left_ vector represents a left hand side node
+  // (i.e. an element) and each element of right_ is a right hand side
+  // node (i.e. a matcher). The values in the left_ vector indicate
+  // outflow from that node to a node on the right_ side. The values
+  // in the right_ indicate inflow, and specify which left_ node is
+  // feeding that right_ node, if any. For example, left_[3] == 1 means
+  // there's a flow from element #3 to matcher #1. Such a flow would also
+  // be redundantly represented in the right_ vector as right_[1] == 3.
+  // Elements of left_ and right_ are either kUnused or mutually
+  // referent. Mutually referent means that left_[right_[i]] = i and
+  // right_[left_[i]] = i.
+  ::std::vector<size_t> left_;
+  ::std::vector<size_t> right_;
+};
+
+const size_t MaxBipartiteMatchState::kUnused;
+
+GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g) {
+  return MaxBipartiteMatchState(g).Compute();
+}
+
+static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
+                                     ::std::ostream* stream) {
+  typedef ElementMatcherPairs::const_iterator Iter;
+  ::std::ostream& os = *stream;
+  os << "{";
+  const char* sep = "";
+  for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
+    os << sep << "\n  (" << "element #" << it->first << ", " << "matcher #"
+       << it->second << ")";
+    sep = ",";
+  }
+  os << "\n}";
+}
+
+bool MatchMatrix::NextGraph() {
+  for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
+    for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
+      char& b = matched_[SpaceIndex(ilhs, irhs)];
+      if (!b) {
+        b = 1;
+        return true;
+      }
+      b = 0;
+    }
+  }
+  return false;
+}
+
+void MatchMatrix::Randomize() {
+  for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
+    for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
+      char& b = matched_[SpaceIndex(ilhs, irhs)];
+      b = static_cast<char>(rand() & 1);  // NOLINT
+    }
+  }
+}
+
+std::string MatchMatrix::DebugString() const {
+  ::std::stringstream ss;
+  const char* sep = "";
+  for (size_t i = 0; i < LhsSize(); ++i) {
+    ss << sep;
+    for (size_t j = 0; j < RhsSize(); ++j) {
+      ss << HasEdge(i, j);
+    }
+    sep = ";";
+  }
+  return ss.str();
+}
+
+void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
+    ::std::ostream* os) const {
+  switch (match_flags()) {
+    case UnorderedMatcherRequire::ExactMatch:
+      if (matcher_describers_.empty()) {
+        *os << "is empty";
+        return;
+      }
+      if (matcher_describers_.size() == 1) {
+        *os << "has " << Elements(1) << " and that element ";
+        matcher_describers_[0]->DescribeTo(os);
+        return;
+      }
+      *os << "has " << Elements(matcher_describers_.size())
+          << " and there exists some permutation of elements such that:\n";
+      break;
+    case UnorderedMatcherRequire::Superset:
+      *os << "a surjection from elements to requirements exists such that:\n";
+      break;
+    case UnorderedMatcherRequire::Subset:
+      *os << "an injection from elements to requirements exists such that:\n";
+      break;
+  }
+
+  const char* sep = "";
+  for (size_t i = 0; i != matcher_describers_.size(); ++i) {
+    *os << sep;
+    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
+      *os << " - element #" << i << " ";
+    } else {
+      *os << " - an element ";
+    }
+    matcher_describers_[i]->DescribeTo(os);
+    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
+      sep = ", and\n";
+    } else {
+      sep = "\n";
+    }
+  }
+}
+
+void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
+    ::std::ostream* os) const {
+  switch (match_flags()) {
+    case UnorderedMatcherRequire::ExactMatch:
+      if (matcher_describers_.empty()) {
+        *os << "isn't empty";
+        return;
+      }
+      if (matcher_describers_.size() == 1) {
+        *os << "doesn't have " << Elements(1) << ", or has " << Elements(1)
+            << " that ";
+        matcher_describers_[0]->DescribeNegationTo(os);
+        return;
+      }
+      *os << "doesn't have " << Elements(matcher_describers_.size())
+          << ", or there exists no permutation of elements such that:\n";
+      break;
+    case UnorderedMatcherRequire::Superset:
+      *os << "no surjection from elements to requirements exists such that:\n";
+      break;
+    case UnorderedMatcherRequire::Subset:
+      *os << "no injection from elements to requirements exists such that:\n";
+      break;
+  }
+  const char* sep = "";
+  for (size_t i = 0; i != matcher_describers_.size(); ++i) {
+    *os << sep;
+    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
+      *os << " - element #" << i << " ";
+    } else {
+      *os << " - an element ";
+    }
+    matcher_describers_[i]->DescribeTo(os);
+    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
+      sep = ", and\n";
+    } else {
+      sep = "\n";
+    }
+  }
+}
+
+// Checks that all matchers match at least one element, and that all
+// elements match at least one matcher. This enables faster matching
+// and better error reporting.
+// Returns false, writing an explanation to 'listener', if and only
+// if the success criteria are not met.
+bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix(
+    const ::std::vector<std::string>& element_printouts,
+    const MatchMatrix& matrix, MatchResultListener* listener) const {
+  if (matrix.LhsSize() == 0 && matrix.RhsSize() == 0) {
+    return true;
+  }
+
+  const bool is_exact_match_with_size_discrepency =
+      match_flags() == UnorderedMatcherRequire::ExactMatch &&
+      matrix.LhsSize() != matrix.RhsSize();
+  if (is_exact_match_with_size_discrepency) {
+    // The element count doesn't match.  If the container is empty,
+    // there's no need to explain anything as Google Mock already
+    // prints the empty container. Otherwise we just need to show
+    // how many elements there actually are.
+    if (matrix.LhsSize() != 0 && listener->IsInterested()) {
+      *listener << "which has " << Elements(matrix.LhsSize()) << "\n";
+    }
+  }
+
+  bool result = !is_exact_match_with_size_discrepency;
+  ::std::vector<char> element_matched(matrix.LhsSize(), 0);
+  ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
+
+  for (size_t ilhs = 0; ilhs < matrix.LhsSize(); ilhs++) {
+    for (size_t irhs = 0; irhs < matrix.RhsSize(); irhs++) {
+      char matched = matrix.HasEdge(ilhs, irhs);
+      element_matched[ilhs] |= matched;
+      matcher_matched[irhs] |= matched;
+    }
+  }
+
+  if (match_flags() & UnorderedMatcherRequire::Superset) {
+    const char* sep =
+        "where the following matchers don't match any elements:\n";
+    for (size_t mi = 0; mi < matcher_matched.size(); ++mi) {
+      if (matcher_matched[mi]) continue;
+      result = false;
+      if (listener->IsInterested()) {
+        *listener << sep << "matcher #" << mi << ": ";
+        matcher_describers_[mi]->DescribeTo(listener->stream());
+        sep = ",\n";
+      }
+    }
+  }
+
+  if (match_flags() & UnorderedMatcherRequire::Subset) {
+    const char* sep =
+        "where the following elements don't match any matchers:\n";
+    const char* outer_sep = "";
+    if (!result) {
+      outer_sep = "\nand ";
+    }
+    for (size_t ei = 0; ei < element_matched.size(); ++ei) {
+      if (element_matched[ei]) continue;
+      result = false;
+      if (listener->IsInterested()) {
+        *listener << outer_sep << sep << "element #" << ei << ": "
+                  << element_printouts[ei];
+        sep = ",\n";
+        outer_sep = "";
+      }
+    }
+  }
+  return result;
+}
+
+bool UnorderedElementsAreMatcherImplBase::FindPairing(
+    const MatchMatrix& matrix, MatchResultListener* listener) const {
+  ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
+
+  size_t max_flow = matches.size();
+  if ((match_flags() & UnorderedMatcherRequire::Superset) &&
+      max_flow < matrix.RhsSize()) {
+    if (listener->IsInterested()) {
+      *listener << "where no permutation of the elements can satisfy all "
+                   "matchers, and the closest match is "
+                << max_flow << " of " << matrix.RhsSize()
+                << " matchers with the pairings:\n";
+      LogElementMatcherPairVec(matches, listener->stream());
+    }
+    return false;
+  }
+  if ((match_flags() & UnorderedMatcherRequire::Subset) &&
+      max_flow < matrix.LhsSize()) {
+    if (listener->IsInterested()) {
+      *listener
+          << "where not all elements can be matched, and the closest match is "
+          << max_flow << " of " << matrix.RhsSize()
+          << " matchers with the pairings:\n";
+      LogElementMatcherPairVec(matches, listener->stream());
+    }
+    return false;
+  }
+
+  if (matches.size() > 1) {
+    if (listener->IsInterested()) {
+      const char* sep = "where:\n";
+      for (size_t mi = 0; mi < matches.size(); ++mi) {
+        *listener << sep << " - element #" << matches[mi].first
+                  << " is matched by matcher #" << matches[mi].second;
+        sep = ",\n";
+      }
+    }
+  }
+  return true;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/src/gmock-spec-builders.cc b/3rd-party/googletest/googlemock/src/gmock-spec-builders.cc
new file mode 100644
index 0000000..ffdf03d
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock-spec-builders.cc
@@ -0,0 +1,792 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the spec builder syntax (ON_CALL and
+// EXPECT_CALL).
+
+#include "gmock/gmock-spec-builders.h"
+
+#include <stdlib.h>
+
+#include <iostream>  // NOLINT
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+#if defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_LINUX) || defined(GTEST_OS_MAC)
+#include <unistd.h>  // NOLINT
+#endif
+#ifdef GTEST_OS_QURT
+#include <qurt_event.h>
+#endif
+
+// Silence C4800 (C4800: 'int *const ': forcing value
+// to bool 'true' or 'false') for MSVC 15
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800)
+#endif
+
+namespace testing {
+namespace internal {
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Logs a message including file and line number information.
+GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity,
+                                const char* file, int line,
+                                const std::string& message) {
+  ::std::ostringstream s;
+  s << internal::FormatFileLocation(file, line) << " " << message
+    << ::std::endl;
+  Log(severity, s.str(), 0);
+}
+
+// Constructs an ExpectationBase object.
+ExpectationBase::ExpectationBase(const char* a_file, int a_line,
+                                 const std::string& a_source_text)
+    : file_(a_file),
+      line_(a_line),
+      source_text_(a_source_text),
+      cardinality_specified_(false),
+      cardinality_(Exactly(1)),
+      call_count_(0),
+      retired_(false),
+      extra_matcher_specified_(false),
+      repeated_action_specified_(false),
+      retires_on_saturation_(false),
+      last_clause_(kNone),
+      action_count_checked_(false) {}
+
+// Destructs an ExpectationBase object.
+ExpectationBase::~ExpectationBase() = default;
+
+// Explicitly specifies the cardinality of this expectation.  Used by
+// the subclasses to implement the .Times() clause.
+void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
+  cardinality_specified_ = true;
+  cardinality_ = a_cardinality;
+}
+
+// Retires all pre-requisites of this expectation.
+void ExpectationBase::RetireAllPreRequisites()
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  if (is_retired()) {
+    // We can take this short-cut as we never retire an expectation
+    // until we have retired all its pre-requisites.
+    return;
+  }
+
+  ::std::vector<ExpectationBase*> expectations(1, this);
+  while (!expectations.empty()) {
+    ExpectationBase* exp = expectations.back();
+    expectations.pop_back();
+
+    for (ExpectationSet::const_iterator it =
+             exp->immediate_prerequisites_.begin();
+         it != exp->immediate_prerequisites_.end(); ++it) {
+      ExpectationBase* next = it->expectation_base().get();
+      if (!next->is_retired()) {
+        next->Retire();
+        expectations.push_back(next);
+      }
+    }
+  }
+}
+
+// Returns true if and only if all pre-requisites of this expectation
+// have been satisfied.
+bool ExpectationBase::AllPrerequisitesAreSatisfied() const
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+  ::std::vector<const ExpectationBase*> expectations(1, this);
+  while (!expectations.empty()) {
+    const ExpectationBase* exp = expectations.back();
+    expectations.pop_back();
+
+    for (ExpectationSet::const_iterator it =
+             exp->immediate_prerequisites_.begin();
+         it != exp->immediate_prerequisites_.end(); ++it) {
+      const ExpectationBase* next = it->expectation_base().get();
+      if (!next->IsSatisfied()) return false;
+      expectations.push_back(next);
+    }
+  }
+  return true;
+}
+
+// Adds unsatisfied pre-requisites of this expectation to 'result'.
+void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+  ::std::vector<const ExpectationBase*> expectations(1, this);
+  while (!expectations.empty()) {
+    const ExpectationBase* exp = expectations.back();
+    expectations.pop_back();
+
+    for (ExpectationSet::const_iterator it =
+             exp->immediate_prerequisites_.begin();
+         it != exp->immediate_prerequisites_.end(); ++it) {
+      const ExpectationBase* next = it->expectation_base().get();
+
+      if (next->IsSatisfied()) {
+        // If *it is satisfied and has a call count of 0, some of its
+        // pre-requisites may not be satisfied yet.
+        if (next->call_count_ == 0) {
+          expectations.push_back(next);
+        }
+      } else {
+        // Now that we know next is unsatisfied, we are not so interested
+        // in whether its pre-requisites are satisfied.  Therefore we
+        // don't iterate into it here.
+        *result += *it;
+      }
+    }
+  }
+}
+
+// Describes how many times a function call matching this
+// expectation has occurred.
+void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+
+  // Describes how many times the function is expected to be called.
+  *os << "         Expected: to be ";
+  cardinality().DescribeTo(os);
+  *os << "\n           Actual: ";
+  Cardinality::DescribeActualCallCountTo(call_count(), os);
+
+  // Describes the state of the expectation (e.g. is it satisfied?
+  // is it active?).
+  *os << " - "
+      << (IsOverSaturated() ? "over-saturated"
+          : IsSaturated()   ? "saturated"
+          : IsSatisfied()   ? "satisfied"
+                            : "unsatisfied")
+      << " and " << (is_retired() ? "retired" : "active");
+}
+
+// Checks the action count (i.e. the number of WillOnce() and
+// WillRepeatedly() clauses) against the cardinality if this hasn't
+// been done before.  Prints a warning if there are too many or too
+// few actions.
+void ExpectationBase::CheckActionCountIfNotDone() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  bool should_check = false;
+  {
+    MutexLock l(&mutex_);
+    if (!action_count_checked_) {
+      action_count_checked_ = true;
+      should_check = true;
+    }
+  }
+
+  if (should_check) {
+    if (!cardinality_specified_) {
+      // The cardinality was inferred - no need to check the action
+      // count against it.
+      return;
+    }
+
+    // The cardinality was explicitly specified.
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    const int upper_bound = cardinality().ConservativeUpperBound();
+    const int lower_bound = cardinality().ConservativeLowerBound();
+    bool too_many;  // True if there are too many actions, or false
+    // if there are too few.
+    if (action_count > upper_bound ||
+        (action_count == upper_bound && repeated_action_specified_)) {
+      too_many = true;
+    } else if (0 < action_count && action_count < lower_bound &&
+               !repeated_action_specified_) {
+      too_many = false;
+    } else {
+      return;
+    }
+
+    ::std::stringstream ss;
+    DescribeLocationTo(&ss);
+    ss << "Too " << (too_many ? "many" : "few") << " actions specified in "
+       << source_text() << "...\n"
+       << "Expected to be ";
+    cardinality().DescribeTo(&ss);
+    ss << ", but has " << (too_many ? "" : "only ") << action_count
+       << " WillOnce()" << (action_count == 1 ? "" : "s");
+    if (repeated_action_specified_) {
+      ss << " and a WillRepeatedly()";
+    }
+    ss << ".";
+    Log(kWarning, ss.str(), -1);  // -1 means "don't print stack trace".
+  }
+}
+
+// Implements the .Times() clause.
+void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
+  if (last_clause_ == kTimes) {
+    ExpectSpecProperty(false,
+                       ".Times() cannot appear "
+                       "more than once in an EXPECT_CALL().");
+  } else {
+    ExpectSpecProperty(
+        last_clause_ < kTimes,
+        ".Times() may only appear *before* .InSequence(), .WillOnce(), "
+        ".WillRepeatedly(), or .RetiresOnSaturation(), not after.");
+  }
+  last_clause_ = kTimes;
+
+  SpecifyCardinality(a_cardinality);
+}
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+GTEST_API_ ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const std::string& msg) {
+  // Include a stack trace only if --gmock_verbose=info is specified.
+  const int stack_frames_to_skip =
+      GMOCK_FLAG_GET(verbose) == kInfoVerbosity ? 3 : -1;
+  switch (reaction) {
+    case kAllow:
+      Log(kInfo, msg, stack_frames_to_skip);
+      break;
+    case kWarn:
+      Log(kWarning,
+          msg +
+              "\nNOTE: You can safely ignore the above warning unless this "
+              "call should not happen.  Do not suppress it by blindly adding "
+              "an EXPECT_CALL() if you don't mean to enforce the call.  "
+              "See "
+              "https://github.com/google/googletest/blob/main/docs/"
+              "gmock_cook_book.md#"
+              "knowing-when-to-expect-useoncall for details.\n",
+          stack_frames_to_skip);
+      break;
+    default:  // FAIL
+      Expect(false, nullptr, -1, msg);
+  }
+}
+
+UntypedFunctionMockerBase::UntypedFunctionMockerBase()
+    : mock_obj_(nullptr), name_("") {}
+
+UntypedFunctionMockerBase::~UntypedFunctionMockerBase() = default;
+
+// Sets the mock object this mock method belongs to, and registers
+// this information in the global mock registry.  Will be called
+// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+// method.
+void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  {
+    MutexLock l(&g_gmock_mutex);
+    mock_obj_ = mock_obj;
+  }
+  Mock::Register(mock_obj, this);
+}
+
+// Sets the mock object this mock method belongs to, and sets the name
+// of the mock function.  Will be called upon each invocation of this
+// mock function.
+void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
+                                                const char* name)
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  // We protect name_ under g_gmock_mutex in case this mock function
+  // is called from two threads concurrently.
+  MutexLock l(&g_gmock_mutex);
+  mock_obj_ = mock_obj;
+  name_ = name;
+}
+
+// Returns the name of the function being mocked.  Must be called
+// after RegisterOwner() or SetOwnerAndName() has been called.
+const void* UntypedFunctionMockerBase::MockObject() const
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  const void* mock_obj;
+  {
+    // We protect mock_obj_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(mock_obj_ != nullptr, __FILE__, __LINE__,
+           "MockObject() must not be called before RegisterOwner() or "
+           "SetOwnerAndName() has been called.");
+    mock_obj = mock_obj_;
+  }
+  return mock_obj;
+}
+
+// Returns the name of this mock method.  Must be called after
+// SetOwnerAndName() has been called.
+const char* UntypedFunctionMockerBase::Name() const
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  const char* name;
+  {
+    // We protect name_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(name_ != nullptr, __FILE__, __LINE__,
+           "Name() must not be called before SetOwnerAndName() has "
+           "been called.");
+    name = name_;
+  }
+  return name;
+}
+
+// Returns an Expectation object that references and co-owns exp,
+// which must be an expectation on this mock function.
+Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
+  // See the definition of untyped_expectations_ for why access to it
+  // is unprotected here.
+  for (UntypedExpectations::const_iterator it = untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    if (it->get() == exp) {
+      return Expectation(*it);
+    }
+  }
+
+  Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
+  return Expectation();
+  // The above statement is just to make the code compile, and will
+  // never be executed.
+}
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures
+// and returns false if not.
+bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+  bool expectations_met = true;
+  for (UntypedExpectations::const_iterator it = untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    ExpectationBase* const untyped_expectation = it->get();
+    if (untyped_expectation->IsOverSaturated()) {
+      // There was an upper-bound violation.  Since the error was
+      // already reported when it occurred, there is no need to do
+      // anything here.
+      expectations_met = false;
+    } else if (!untyped_expectation->IsSatisfied()) {
+      expectations_met = false;
+      ::std::stringstream ss;
+
+      const ::std::string& expectation_name =
+          untyped_expectation->GetDescription();
+      ss << "Actual function ";
+      if (!expectation_name.empty()) {
+        ss << "\"" << expectation_name << "\" ";
+      }
+      ss << "call count doesn't match " << untyped_expectation->source_text()
+         << "...\n";
+      // No need to show the source file location of the expectation
+      // in the description, as the Expect() call that follows already
+      // takes care of it.
+      untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
+      untyped_expectation->DescribeCallCountTo(&ss);
+      Expect(false, untyped_expectation->file(), untyped_expectation->line(),
+             ss.str());
+    }
+  }
+
+  // Deleting our expectations may trigger other mock objects to be deleted, for
+  // example if an action contains a reference counted smart pointer to that
+  // mock object, and that is the last reference. So if we delete our
+  // expectations within the context of the global mutex we may deadlock when
+  // this method is called again. Instead, make a copy of the set of
+  // expectations to delete, clear our set within the mutex, and then clear the
+  // copied set outside of it.
+  UntypedExpectations expectations_to_delete;
+  untyped_expectations_.swap(expectations_to_delete);
+
+  g_gmock_mutex.Unlock();
+  expectations_to_delete.clear();
+  g_gmock_mutex.Lock();
+
+  return expectations_met;
+}
+
+static CallReaction intToCallReaction(int mock_behavior) {
+  if (mock_behavior >= kAllow && mock_behavior <= kFail) {
+    return static_cast<internal::CallReaction>(mock_behavior);
+  }
+  return kWarn;
+}
+
+}  // namespace internal
+
+// Class Mock.
+
+namespace {
+
+typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
+
+// The current state of a mock object.  Such information is needed for
+// detecting leaked mock objects and explicitly verifying a mock's
+// expectations.
+struct MockObjectState {
+  MockObjectState()
+      : first_used_file(nullptr), first_used_line(-1), leakable(false) {}
+
+  // Where in the source file an ON_CALL or EXPECT_CALL is first
+  // invoked on this mock object.
+  const char* first_used_file;
+  int first_used_line;
+  ::std::string first_used_test_suite;
+  ::std::string first_used_test;
+  bool leakable;  // true if and only if it's OK to leak the object.
+  FunctionMockers function_mockers;  // All registered methods of the object.
+};
+
+// A global registry holding the state of all mock objects that are
+// alive.  A mock object is added to this registry the first time
+// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it.  It
+// is removed from the registry in the mock object's destructor.
+class MockObjectRegistry {
+ public:
+  // Maps a mock object (identified by its address) to its state.
+  typedef std::map<const void*, MockObjectState> StateMap;
+
+  // This destructor will be called when a program exits, after all
+  // tests in it have been run.  By then, there should be no mock
+  // object alive.  Therefore we report any living object as test
+  // failure, unless the user explicitly asked us to ignore it.
+  ~MockObjectRegistry() {
+    if (!GMOCK_FLAG_GET(catch_leaked_mocks)) return;
+    internal::MutexLock l(&internal::g_gmock_mutex);
+
+    int leaked_count = 0;
+    for (StateMap::const_iterator it = states_.begin(); it != states_.end();
+         ++it) {
+      if (it->second.leakable)  // The user said it's fine to leak this object.
+        continue;
+
+      // FIXME: Print the type of the leaked object.
+      // This can help the user identify the leaked object.
+      std::cout << "\n";
+      const MockObjectState& state = it->second;
+      std::cout << internal::FormatFileLocation(state.first_used_file,
+                                                state.first_used_line);
+      std::cout << " ERROR: this mock object";
+      if (!state.first_used_test.empty()) {
+        std::cout << " (used in test " << state.first_used_test_suite << "."
+                  << state.first_used_test << ")";
+      }
+      std::cout << " should be deleted but never is. Its address is @"
+                << it->first << ".";
+      leaked_count++;
+    }
+    if (leaked_count > 0) {
+      std::cout << "\nERROR: " << leaked_count << " leaked mock "
+                << (leaked_count == 1 ? "object" : "objects")
+                << " found at program exit. Expectations on a mock object are "
+                   "verified when the object is destructed. Leaking a mock "
+                   "means that its expectations aren't verified, which is "
+                   "usually a test bug. If you really intend to leak a mock, "
+                   "you can suppress this error using "
+                   "testing::Mock::AllowLeak(mock_object), or you may use a "
+                   "fake or stub instead of a mock.\n";
+      std::cout.flush();
+      ::std::cerr.flush();
+      // RUN_ALL_TESTS() has already returned when this destructor is
+      // called.  Therefore we cannot use the normal Google Test
+      // failure reporting mechanism.
+#ifdef GTEST_OS_QURT
+      qurt_exception_raise_fatal();
+#else
+      _Exit(1);  // We cannot call exit() as it is not reentrant and
+                 // may already have been called.
+#endif
+    }
+  }
+
+  StateMap& states() { return states_; }
+
+ private:
+  StateMap states_;
+};
+
+// Protected by g_gmock_mutex.
+MockObjectRegistry g_mock_object_registry;
+
+// Maps a mock object to the reaction Google Mock should have when an
+// uninteresting method is called.  Protected by g_gmock_mutex.
+std::unordered_map<uintptr_t, internal::CallReaction>&
+UninterestingCallReactionMap() {
+  static auto* map = new std::unordered_map<uintptr_t, internal::CallReaction>;
+  return *map;
+}
+
+// Sets the reaction Google Mock should have when an uninteresting
+// method of the given mock object is called.
+void SetReactionOnUninterestingCalls(uintptr_t mock_obj,
+                                     internal::CallReaction reaction)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  UninterestingCallReactionMap()[mock_obj] = reaction;
+}
+
+}  // namespace
+
+// Tells Google Mock to allow uninteresting calls on the given mock
+// object.
+void Mock::AllowUninterestingCalls(uintptr_t mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::kAllow);
+}
+
+// Tells Google Mock to warn the user about uninteresting calls on the
+// given mock object.
+void Mock::WarnUninterestingCalls(uintptr_t mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::kWarn);
+}
+
+// Tells Google Mock to fail uninteresting calls on the given mock
+// object.
+void Mock::FailUninterestingCalls(uintptr_t mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::kFail);
+}
+
+// Tells Google Mock the given mock object is being destroyed and its
+// entry in the call-reaction table should be removed.
+void Mock::UnregisterCallReaction(uintptr_t mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  UninterestingCallReactionMap().erase(static_cast<uintptr_t>(mock_obj));
+}
+
+// Returns the reaction Google Mock will have on uninteresting calls
+// made on the given mock object.
+internal::CallReaction Mock::GetReactionOnUninterestingCalls(
+    const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return (UninterestingCallReactionMap().count(
+              reinterpret_cast<uintptr_t>(mock_obj)) == 0)
+             ? internal::intToCallReaction(
+                   GMOCK_FLAG_GET(default_mock_behavior))
+             : UninterestingCallReactionMap()[reinterpret_cast<uintptr_t>(
+                   mock_obj)];
+}
+
+// Tells Google Mock to ignore mock_obj when checking for leaked mock
+// objects.
+void Mock::AllowLeak(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].leakable = true;
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+bool Mock::VerifyAndClearExpectations(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies all expectations on the given mock object and clears its
+// default actions and expectations.  Returns true if and only if the
+// verification was successful.
+bool Mock::VerifyAndClear(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  ClearDefaultActionsLocked(mock_obj);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj)
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
+  internal::g_gmock_mutex.AssertHeld();
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No EXPECT_CALL() was set on the given mock object.
+    return true;
+  }
+
+  // Verifies and clears the expectations on each mock method in the
+  // given mock object.
+  bool expectations_met = true;
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    if (!(*it)->VerifyAndClearExpectationsLocked()) {
+      expectations_met = false;
+    }
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by ClearDefaultActionsLocked().
+  return expectations_met;
+}
+
+bool Mock::IsNaggy(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  return Mock::GetReactionOnUninterestingCalls(mock_obj) == internal::kWarn;
+}
+bool Mock::IsNice(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  return Mock::GetReactionOnUninterestingCalls(mock_obj) == internal::kAllow;
+}
+bool Mock::IsStrict(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  return Mock::GetReactionOnUninterestingCalls(mock_obj) == internal::kFail;
+}
+
+// Registers a mock object and a mock method it owns.
+void Mock::Register(const void* mock_obj,
+                    internal::UntypedFunctionMockerBase* mocker)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
+}
+
+// Tells Google Mock where in the source code mock_obj is used in an
+// ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+// information helps the user identify which object it is.
+void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
+                                           const char* file, int line)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  MockObjectState& state = g_mock_object_registry.states()[mock_obj];
+  if (state.first_used_file == nullptr) {
+    state.first_used_file = file;
+    state.first_used_line = line;
+    const TestInfo* const test_info =
+        UnitTest::GetInstance()->current_test_info();
+    if (test_info != nullptr) {
+      state.first_used_test_suite = test_info->test_suite_name();
+      state.first_used_test = test_info->name();
+    }
+  }
+}
+
+// Unregisters a mock method; removes the owning mock object from the
+// registry when the last mock method associated with it has been
+// unregistered.  This is called only in the destructor of
+// FunctionMockerBase.
+void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
+  internal::g_gmock_mutex.AssertHeld();
+  for (MockObjectRegistry::StateMap::iterator it =
+           g_mock_object_registry.states().begin();
+       it != g_mock_object_registry.states().end(); ++it) {
+    FunctionMockers& mockers = it->second.function_mockers;
+    if (mockers.erase(mocker) > 0) {
+      // mocker was in mockers and has been just removed.
+      if (mockers.empty()) {
+        g_mock_object_registry.states().erase(it);
+      }
+      return;
+    }
+  }
+}
+
+// Clears all ON_CALL()s set on the given mock object.
+void Mock::ClearDefaultActionsLocked(void* mock_obj)
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
+  internal::g_gmock_mutex.AssertHeld();
+
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No ON_CALL() was set on the given mock object.
+    return;
+  }
+
+  // Clears the default actions for each mock method in the given mock
+  // object.
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    (*it)->ClearDefaultActionsLocked();
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by VerifyAndClearExpectationsLocked().
+}
+
+Expectation::Expectation() = default;
+
+Expectation::Expectation(
+    const std::shared_ptr<internal::ExpectationBase>& an_expectation_base)
+    : expectation_base_(an_expectation_base) {}
+
+Expectation::~Expectation() = default;
+
+// Adds an expectation to a sequence.
+void Sequence::AddExpectation(const Expectation& expectation) const {
+  if (*last_expectation_ != expectation) {
+    if (last_expectation_->expectation_base() != nullptr) {
+      expectation.expectation_base()->immediate_prerequisites_ +=
+          *last_expectation_;
+    }
+    *last_expectation_ = expectation;
+  }
+}
+
+// Creates the implicit sequence if there isn't one.
+InSequence::InSequence() {
+  if (internal::g_gmock_implicit_sequence.get() == nullptr) {
+    internal::g_gmock_implicit_sequence.set(new Sequence);
+    sequence_created_ = true;
+  } else {
+    sequence_created_ = false;
+  }
+}
+
+// Deletes the implicit sequence if it was created by the constructor
+// of this object.
+InSequence::~InSequence() {
+  if (sequence_created_) {
+    delete internal::g_gmock_implicit_sequence.get();
+    internal::g_gmock_implicit_sequence.set(nullptr);
+  }
+}
+
+}  // namespace testing
+
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4800
+#endif
diff --git a/3rd-party/googletest/googlemock/src/gmock.cc b/3rd-party/googletest/googlemock/src/gmock.cc
new file mode 100644
index 0000000..b5e714d
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock.cc
@@ -0,0 +1,225 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gmock/gmock.h"
+
+#include <string>
+
+#include "gmock/internal/gmock-port.h"
+
+GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
+                   "true if and only if Google Mock should report leaked "
+                   "mock objects as failures.");
+
+GMOCK_DEFINE_string_(verbose, testing::internal::kWarningVerbosity,
+                     "Controls how verbose Google Mock's output is."
+                     "  Valid values:\n"
+                     "  info    - prints all messages.\n"
+                     "  warning - prints warnings and errors.\n"
+                     "  error   - prints errors only.");
+
+GMOCK_DEFINE_int32_(default_mock_behavior, 1,
+                    "Controls the default behavior of mocks."
+                    "  Valid values:\n"
+                    "  0 - by default, mocks act as NiceMocks.\n"
+                    "  1 - by default, mocks act as NaggyMocks.\n"
+                    "  2 - by default, mocks act as StrictMocks.");
+
+namespace testing {
+namespace internal {
+
+// Parses a string as a command line flag.  The string should have the
+// format "--gmock_flag=value".  When def_optional is true, the
+// "=value" part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+static const char* ParseGoogleMockFlagValue(const char* str,
+                                            const char* flag_name,
+                                            bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == nullptr || flag_name == nullptr) return nullptr;
+
+  // The flag must start with "--gmock_".
+  const std::string flag_name_str = std::string("--gmock_") + flag_name;
+  const size_t flag_name_len = flag_name_str.length();
+  if (strncmp(str, flag_name_str.c_str(), flag_name_len) != 0) return nullptr;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_name_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return nullptr;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a Google Mock bool flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseGoogleMockFlag(const char* str, const char* flag_name,
+                                bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag_name, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for a Google Mock string flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+template <typename String>
+static bool ParseGoogleMockFlag(const char* str, const char* flag_name,
+                                String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag_name, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+static bool ParseGoogleMockFlag(const char* str, const char* flag_name,
+                                int32_t* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag_name, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag_name, value_str,
+                    value);
+}
+
+// The internal implementation of InitGoogleMock().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleMockImpl(int* argc, CharType** argv) {
+  // Makes sure Google Test is initialized.  InitGoogleTest() is
+  // idempotent, so it's fine if the user has already called it.
+  InitGoogleTest(argc, argv);
+  if (*argc <= 0) return;
+
+  for (int i = 1; i != *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    // Do we see a Google Mock flag?
+    bool found_gmock_flag = false;
+
+#define GMOCK_INTERNAL_PARSE_FLAG(flag_name)            \
+  if (!found_gmock_flag) {                              \
+    auto value = GMOCK_FLAG_GET(flag_name);             \
+    if (ParseGoogleMockFlag(arg, #flag_name, &value)) { \
+      GMOCK_FLAG_SET(flag_name, value);                 \
+      found_gmock_flag = true;                          \
+    }                                                   \
+  }
+
+    GMOCK_INTERNAL_PARSE_FLAG(catch_leaked_mocks)
+    GMOCK_INTERNAL_PARSE_FLAG(verbose)
+    GMOCK_INTERNAL_PARSE_FLAG(default_mock_behavior)
+
+    if (found_gmock_flag) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+}
+
+}  // namespace internal
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses a command line for the flags that
+// Google Mock recognizes.  Whenever a Google Mock flag is seen, it is
+// removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+GTEST_API_ void InitGoogleMock(int* argc, char** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+// This overloaded version can be used on Arduino/embedded platforms where
+// there is no argc/argv.
+GTEST_API_ void InitGoogleMock() {
+  // Since Arduino doesn't have a command line, fake out the argc/argv arguments
+  int argc = 1;
+  const auto arg0 = "dummy";
+  char* argv0 = const_cast<char*>(arg0);
+  char** argv = &argv0;
+
+  internal::InitGoogleMockImpl(&argc, argv);
+}
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/src/gmock_main.cc b/3rd-party/googletest/googlemock/src/gmock_main.cc
new file mode 100644
index 0000000..6b55412
--- /dev/null
+++ b/3rd-party/googletest/googlemock/src/gmock_main.cc
@@ -0,0 +1,73 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#if defined(GTEST_OS_ESP8266) || defined(GTEST_OS_ESP32) || \
+    (defined(GTEST_OS_NRF52) && defined(ARDUINO))
+#ifdef GTEST_OS_ESP8266
+extern "C" {
+#endif
+void setup() {
+  // Since Google Mock depends on Google Test, InitGoogleMock() is
+  // also responsible for initializing Google Test.  Therefore there's
+  // no need for calling testing::InitGoogleTest() separately.
+  testing::InitGoogleMock();
+}
+void loop() { RUN_ALL_TESTS(); }
+#ifdef GTEST_OS_ESP8266
+}
+#endif
+
+#else
+
+// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
+// causes a link error when _tmain is defined in a static library and UNICODE
+// is enabled. For this reason instead of _tmain, main function is used on
+// Windows. See the following link to track the current status of this bug:
+// https://web.archive.org/web/20170912203238/connect.microsoft.com/VisualStudio/feedback/details/394464/wmain-link-error-in-the-static-library
+// // NOLINT
+#ifdef GTEST_OS_WINDOWS_MOBILE
+#include <tchar.h>  // NOLINT
+
+GTEST_API_ int _tmain(int argc, TCHAR** argv) {
+#else
+GTEST_API_ int main(int argc, char** argv) {
+#endif  // GTEST_OS_WINDOWS_MOBILE
+  std::cout << "Running main() from gmock_main.cc\n";
+  // Since Google Mock depends on Google Test, InitGoogleMock() is
+  // also responsible for initializing Google Test.  Therefore there's
+  // no need for calling testing::InitGoogleTest() separately.
+  testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+#endif
diff --git a/3rd-party/googletest/googlemock/test/BUILD.bazel b/3rd-party/googletest/googlemock/test/BUILD.bazel
new file mode 100644
index 0000000..d4297c8
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/BUILD.bazel
@@ -0,0 +1,118 @@
+# Copyright 2017 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#   Bazel Build for Google C++ Testing Framework(Google Test)-googlemock
+
+load("@rules_python//python:defs.bzl", "py_library", "py_test")
+
+licenses(["notice"])
+
+# Tests for GMock itself
+cc_test(
+    name = "gmock_all_test",
+    size = "small",
+    srcs = glob(include = ["gmock-*.cc"]) + ["gmock-matchers_test.h"],
+    linkopts = select({
+        "//:qnx": [],
+        "//:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
+    deps = ["//:gtest"],
+)
+
+# Python tests
+py_library(
+    name = "gmock_test_utils",
+    testonly = 1,
+    srcs = ["gmock_test_utils.py"],
+    deps = [
+        "//googletest/test:gtest_test_utils",
+    ],
+)
+
+cc_binary(
+    name = "gmock_leak_test_",
+    testonly = 1,
+    srcs = ["gmock_leak_test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+py_test(
+    name = "gmock_leak_test",
+    size = "medium",
+    srcs = ["gmock_leak_test.py"],
+    data = [
+        ":gmock_leak_test_",
+        ":gmock_test_utils",
+    ],
+    tags = [
+        "no_test_msvc2015",
+        "no_test_msvc2017",
+    ],
+)
+
+cc_test(
+    name = "gmock_link_test",
+    size = "small",
+    srcs = [
+        "gmock_link2_test.cc",
+        "gmock_link_test.cc",
+        "gmock_link_test.h",
+    ],
+    deps = ["//:gtest_main"],
+)
+
+cc_binary(
+    name = "gmock_output_test_",
+    srcs = ["gmock_output_test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "gmock_output_test",
+    size = "medium",
+    srcs = ["gmock_output_test.py"],
+    data = [
+        ":gmock_output_test_",
+        ":gmock_output_test_golden.txt",
+    ],
+    tags = [
+        "no_test_msvc2015",
+        "no_test_msvc2017",
+    ],
+    deps = [":gmock_test_utils"],
+)
+
+cc_test(
+    name = "gmock_test",
+    size = "small",
+    srcs = ["gmock_test.cc"],
+    deps = ["//:gtest_main"],
+)
diff --git a/3rd-party/googletest/googlemock/test/gmock-actions_test.cc b/3rd-party/googletest/googlemock/test/gmock-actions_test.cc
new file mode 100644
index 0000000..82c22c3
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-actions_test.cc
@@ -0,0 +1,2217 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in actions.
+
+#include "gmock/gmock-actions.h"
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+// Silence C4100 (unreferenced formal parameter) and C4503 (decorated name
+// length exceeded) for MSVC.
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100 4503)
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+// and silence C4800 (C4800: 'int *const ': forcing value
+// to bool 'true' or 'false') for MSVC 15
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800)
+#endif
+
+namespace testing {
+namespace {
+
+using ::testing::internal::BuiltInDefaultValue;
+
+TEST(TypeTraits, Negation) {
+  // Direct use with std types.
+  static_assert(std::is_base_of<std::false_type,
+                                internal::negation<std::true_type>>::value,
+                "");
+
+  static_assert(std::is_base_of<std::true_type,
+                                internal::negation<std::false_type>>::value,
+                "");
+
+  // With other types that fit the requirement of a value member that is
+  // convertible to bool.
+  static_assert(std::is_base_of<
+                    std::true_type,
+                    internal::negation<std::integral_constant<int, 0>>>::value,
+                "");
+
+  static_assert(std::is_base_of<
+                    std::false_type,
+                    internal::negation<std::integral_constant<int, 1>>>::value,
+                "");
+
+  static_assert(std::is_base_of<
+                    std::false_type,
+                    internal::negation<std::integral_constant<int, -1>>>::value,
+                "");
+}
+
+// Weird false/true types that aren't actually bool constants (but should still
+// be legal according to [meta.logical] because `bool(T::value)` is valid), are
+// distinct from std::false_type and std::true_type, and are distinct from other
+// instantiations of the same template.
+//
+// These let us check finicky details mandated by the standard like
+// "std::conjunction should evaluate to a type that inherits from the first
+// false-y input".
+template <int>
+struct MyFalse : std::integral_constant<int, 0> {};
+
+template <int>
+struct MyTrue : std::integral_constant<int, -1> {};
+
+TEST(TypeTraits, Conjunction) {
+  // Base case: always true.
+  static_assert(std::is_base_of<std::true_type, internal::conjunction<>>::value,
+                "");
+
+  // One predicate: inherits from that predicate, regardless of value.
+  static_assert(
+      std::is_base_of<MyFalse<0>, internal::conjunction<MyFalse<0>>>::value,
+      "");
+
+  static_assert(
+      std::is_base_of<MyTrue<0>, internal::conjunction<MyTrue<0>>>::value, "");
+
+  // Multiple predicates, with at least one false: inherits from that one.
+  static_assert(
+      std::is_base_of<MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>,
+                                                        MyTrue<2>>>::value,
+      "");
+
+  static_assert(
+      std::is_base_of<MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>,
+                                                        MyFalse<2>>>::value,
+      "");
+
+  // Short circuiting: in the case above, additional predicates need not even
+  // define a value member.
+  struct Empty {};
+  static_assert(
+      std::is_base_of<MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>,
+                                                        Empty>>::value,
+      "");
+
+  // All predicates true: inherits from the last.
+  static_assert(
+      std::is_base_of<MyTrue<2>, internal::conjunction<MyTrue<0>, MyTrue<1>,
+                                                       MyTrue<2>>>::value,
+      "");
+}
+
+TEST(TypeTraits, Disjunction) {
+  // Base case: always false.
+  static_assert(
+      std::is_base_of<std::false_type, internal::disjunction<>>::value, "");
+
+  // One predicate: inherits from that predicate, regardless of value.
+  static_assert(
+      std::is_base_of<MyFalse<0>, internal::disjunction<MyFalse<0>>>::value,
+      "");
+
+  static_assert(
+      std::is_base_of<MyTrue<0>, internal::disjunction<MyTrue<0>>>::value, "");
+
+  // Multiple predicates, with at least one true: inherits from that one.
+  static_assert(
+      std::is_base_of<MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>,
+                                                       MyFalse<2>>>::value,
+      "");
+
+  static_assert(
+      std::is_base_of<MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>,
+                                                       MyTrue<2>>>::value,
+      "");
+
+  // Short circuiting: in the case above, additional predicates need not even
+  // define a value member.
+  struct Empty {};
+  static_assert(
+      std::is_base_of<MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>,
+                                                       Empty>>::value,
+      "");
+
+  // All predicates false: inherits from the last.
+  static_assert(
+      std::is_base_of<MyFalse<2>, internal::disjunction<MyFalse<0>, MyFalse<1>,
+                                                        MyFalse<2>>>::value,
+      "");
+}
+
+TEST(TypeTraits, IsInvocableRV) {
+  struct C {
+    int operator()() const { return 0; }
+    void operator()(int) & {}
+    std::string operator()(int) && { return ""; };
+  };
+
+  // The first overload is callable for const and non-const rvalues and lvalues.
+  // It can be used to obtain an int, cv void, or anything int is convertible
+  // to.
+  static_assert(internal::is_callable_r<int, C>::value, "");
+  static_assert(internal::is_callable_r<int, C&>::value, "");
+  static_assert(internal::is_callable_r<int, const C>::value, "");
+  static_assert(internal::is_callable_r<int, const C&>::value, "");
+
+  static_assert(internal::is_callable_r<void, C>::value, "");
+  static_assert(internal::is_callable_r<const volatile void, C>::value, "");
+  static_assert(internal::is_callable_r<char, C>::value, "");
+
+  // It's possible to provide an int. If it's given to an lvalue, the result is
+  // void. Otherwise it is std::string (which is also treated as allowed for a
+  // void result type).
+  static_assert(internal::is_callable_r<void, C&, int>::value, "");
+  static_assert(!internal::is_callable_r<int, C&, int>::value, "");
+  static_assert(!internal::is_callable_r<std::string, C&, int>::value, "");
+  static_assert(!internal::is_callable_r<void, const C&, int>::value, "");
+
+  static_assert(internal::is_callable_r<std::string, C, int>::value, "");
+  static_assert(internal::is_callable_r<void, C, int>::value, "");
+  static_assert(!internal::is_callable_r<int, C, int>::value, "");
+
+  // It's not possible to provide other arguments.
+  static_assert(!internal::is_callable_r<void, C, std::string>::value, "");
+  static_assert(!internal::is_callable_r<void, C, int, int>::value, "");
+
+  // In C++17 and above, where it's guaranteed that functions can return
+  // non-moveable objects, everything should work fine for non-moveable rsult
+  // types too.
+#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
+    GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+  {
+    struct NonMoveable {
+      NonMoveable() = default;
+      NonMoveable(NonMoveable&&) = delete;
+    };
+
+    static_assert(!std::is_move_constructible_v<NonMoveable>);
+
+    struct Callable {
+      NonMoveable operator()() { return NonMoveable(); }
+    };
+
+    static_assert(internal::is_callable_r<NonMoveable, Callable>::value);
+    static_assert(internal::is_callable_r<void, Callable>::value);
+    static_assert(
+        internal::is_callable_r<const volatile void, Callable>::value);
+
+    static_assert(!internal::is_callable_r<int, Callable>::value);
+    static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value);
+  }
+#endif  // C++17 and above
+
+  // Nothing should choke when we try to call other arguments besides directly
+  // callable objects, but they should not show up as callable.
+  static_assert(!internal::is_callable_r<void, int>::value, "");
+  static_assert(!internal::is_callable_r<void, void (C::*)()>::value, "");
+  static_assert(!internal::is_callable_r<void, void (C::*)(), C*>::value, "");
+}
+
+// Tests that BuiltInDefaultValue<T*>::Get() returns NULL.
+TEST(BuiltInDefaultValueTest, IsNullForPointerTypes) {
+  EXPECT_TRUE(BuiltInDefaultValue<int*>::Get() == nullptr);
+  EXPECT_TRUE(BuiltInDefaultValue<const char*>::Get() == nullptr);
+  EXPECT_TRUE(BuiltInDefaultValue<void*>::Get() == nullptr);
+}
+
+// Tests that BuiltInDefaultValue<T*>::Exists() return true.
+TEST(BuiltInDefaultValueTest, ExistsForPointerTypes) {
+  EXPECT_TRUE(BuiltInDefaultValue<int*>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<const char*>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<void*>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<T>::Get() returns 0 when T is a
+// built-in numeric type.
+TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) {
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned char>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<signed char>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<char>::Get());
+#if GMOCK_WCHAR_T_IS_NATIVE_
+#if !defined(__WCHAR_UNSIGNED__)
+  EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get());
+#else
+  EXPECT_EQ(0U, BuiltInDefaultValue<wchar_t>::Get());
+#endif
+#endif
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned short>::Get());  // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<signed short>::Get());     // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<short>::Get());            // NOLINT
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned int>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<signed int>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<int>::Get());
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned long>::Get());       // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<signed long>::Get());          // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<long>::Get());                 // NOLINT
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned long long>::Get());  // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<signed long long>::Get());     // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<long long>::Get());            // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<float>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<double>::Get());
+}
+
+// Tests that BuiltInDefaultValue<T>::Exists() returns true when T is a
+// built-in numeric type.
+TEST(BuiltInDefaultValueTest, ExistsForNumericTypes) {
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned char>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<signed char>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<char>::Exists());
+#if GMOCK_WCHAR_T_IS_NATIVE_
+  EXPECT_TRUE(BuiltInDefaultValue<wchar_t>::Exists());
+#endif
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned short>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<signed short>::Exists());    // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<short>::Exists());           // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned int>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<signed int>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<int>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned long>::Exists());       // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<signed long>::Exists());         // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<long>::Exists());                // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned long long>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<signed long long>::Exists());    // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<long long>::Exists());           // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<float>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<double>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<bool>::Get() returns false.
+TEST(BuiltInDefaultValueTest, IsFalseForBool) {
+  EXPECT_FALSE(BuiltInDefaultValue<bool>::Get());
+}
+
+// Tests that BuiltInDefaultValue<bool>::Exists() returns true.
+TEST(BuiltInDefaultValueTest, BoolExists) {
+  EXPECT_TRUE(BuiltInDefaultValue<bool>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<T>::Get() returns "" when T is a
+// string type.
+TEST(BuiltInDefaultValueTest, IsEmptyStringForString) {
+  EXPECT_EQ("", BuiltInDefaultValue<::std::string>::Get());
+}
+
+// Tests that BuiltInDefaultValue<T>::Exists() returns true when T is a
+// string type.
+TEST(BuiltInDefaultValueTest, ExistsForString) {
+  EXPECT_TRUE(BuiltInDefaultValue<::std::string>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<const T>::Get() returns the same
+// value as BuiltInDefaultValue<T>::Get() does.
+TEST(BuiltInDefaultValueTest, WorksForConstTypes) {
+  EXPECT_EQ("", BuiltInDefaultValue<const std::string>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<const int>::Get());
+  EXPECT_TRUE(BuiltInDefaultValue<char* const>::Get() == nullptr);
+  EXPECT_FALSE(BuiltInDefaultValue<const bool>::Get());
+}
+
+// A type that's default constructible.
+class MyDefaultConstructible {
+ public:
+  MyDefaultConstructible() : value_(42) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+// A type that's not default constructible.
+class MyNonDefaultConstructible {
+ public:
+  // Does not have a default ctor.
+  explicit MyNonDefaultConstructible(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+TEST(BuiltInDefaultValueTest, ExistsForDefaultConstructibleType) {
+  EXPECT_TRUE(BuiltInDefaultValue<MyDefaultConstructible>::Exists());
+}
+
+TEST(BuiltInDefaultValueTest, IsDefaultConstructedForDefaultConstructibleType) {
+  EXPECT_EQ(42, BuiltInDefaultValue<MyDefaultConstructible>::Get().value());
+}
+
+TEST(BuiltInDefaultValueTest, DoesNotExistForNonDefaultConstructibleType) {
+  EXPECT_FALSE(BuiltInDefaultValue<MyNonDefaultConstructible>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<T&>::Get() aborts the program.
+TEST(BuiltInDefaultValueDeathTest, IsUndefinedForReferences) {
+  EXPECT_DEATH_IF_SUPPORTED({ BuiltInDefaultValue<int&>::Get(); }, "");
+  EXPECT_DEATH_IF_SUPPORTED({ BuiltInDefaultValue<const char&>::Get(); }, "");
+}
+
+TEST(BuiltInDefaultValueDeathTest, IsUndefinedForNonDefaultConstructibleType) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      { BuiltInDefaultValue<MyNonDefaultConstructible>::Get(); }, "");
+}
+
+// Tests that DefaultValue<T>::IsSet() is false initially.
+TEST(DefaultValueTest, IsInitiallyUnset) {
+  EXPECT_FALSE(DefaultValue<int>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyDefaultConstructible>::IsSet());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::IsSet());
+}
+
+// Tests that DefaultValue<T> can be set and then unset.
+TEST(DefaultValueTest, CanBeSetAndUnset) {
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::Exists());
+
+  DefaultValue<int>::Set(1);
+  DefaultValue<const MyNonDefaultConstructible>::Set(
+      MyNonDefaultConstructible(42));
+
+  EXPECT_EQ(1, DefaultValue<int>::Get());
+  EXPECT_EQ(42, DefaultValue<const MyNonDefaultConstructible>::Get().value());
+
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_TRUE(DefaultValue<const MyNonDefaultConstructible>::Exists());
+
+  DefaultValue<int>::Clear();
+  DefaultValue<const MyNonDefaultConstructible>::Clear();
+
+  EXPECT_FALSE(DefaultValue<int>::IsSet());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::IsSet());
+
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::Exists());
+}
+
+// Tests that DefaultValue<T>::Get() returns the
+// BuiltInDefaultValue<T>::Get() when DefaultValue<T>::IsSet() is
+// false.
+TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
+  EXPECT_FALSE(DefaultValue<int>::IsSet());
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible>::Exists());
+
+  EXPECT_EQ(0, DefaultValue<int>::Get());
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
+}
+
+TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
+  EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Exists());
+  EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Get() == nullptr);
+  DefaultValue<std::unique_ptr<int>>::SetFactory(
+      [] { return std::make_unique<int>(42); });
+  EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Exists());
+  std::unique_ptr<int> i = DefaultValue<std::unique_ptr<int>>::Get();
+  EXPECT_EQ(42, *i);
+}
+
+// Tests that DefaultValue<void>::Get() returns void.
+TEST(DefaultValueTest, GetWorksForVoid) { return DefaultValue<void>::Get(); }
+
+// Tests using DefaultValue with a reference type.
+
+// Tests that DefaultValue<T&>::IsSet() is false initially.
+TEST(DefaultValueOfReferenceTest, IsInitiallyUnset) {
+  EXPECT_FALSE(DefaultValue<int&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyDefaultConstructible&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
+}
+
+// Tests that DefaultValue<T&>::Exists is false initially.
+TEST(DefaultValueOfReferenceTest, IsInitiallyNotExisting) {
+  EXPECT_FALSE(DefaultValue<int&>::Exists());
+  EXPECT_FALSE(DefaultValue<MyDefaultConstructible&>::Exists());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::Exists());
+}
+
+// Tests that DefaultValue<T&> can be set and then unset.
+TEST(DefaultValueOfReferenceTest, CanBeSetAndUnset) {
+  int n = 1;
+  DefaultValue<const int&>::Set(n);
+  MyNonDefaultConstructible x(42);
+  DefaultValue<MyNonDefaultConstructible&>::Set(x);
+
+  EXPECT_TRUE(DefaultValue<const int&>::Exists());
+  EXPECT_TRUE(DefaultValue<MyNonDefaultConstructible&>::Exists());
+
+  EXPECT_EQ(&n, &(DefaultValue<const int&>::Get()));
+  EXPECT_EQ(&x, &(DefaultValue<MyNonDefaultConstructible&>::Get()));
+
+  DefaultValue<const int&>::Clear();
+  DefaultValue<MyNonDefaultConstructible&>::Clear();
+
+  EXPECT_FALSE(DefaultValue<const int&>::Exists());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::Exists());
+
+  EXPECT_FALSE(DefaultValue<const int&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
+}
+
+// Tests that DefaultValue<T&>::Get() returns the
+// BuiltInDefaultValue<T&>::Get() when DefaultValue<T&>::IsSet() is
+// false.
+TEST(DefaultValueOfReferenceDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
+  EXPECT_FALSE(DefaultValue<int&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
+
+  EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, "");
+  EXPECT_DEATH_IF_SUPPORTED(
+      { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
+}
+
+// Tests that ActionInterface can be implemented by defining the
+// Perform method.
+
+typedef int MyGlobalFunction(bool, int);
+
+class MyActionImpl : public ActionInterface<MyGlobalFunction> {
+ public:
+  int Perform(const std::tuple<bool, int>& args) override {
+    return std::get<0>(args) ? std::get<1>(args) : 0;
+  }
+};
+
+TEST(ActionInterfaceTest, CanBeImplementedByDefiningPerform) {
+  MyActionImpl my_action_impl;
+  (void)my_action_impl;
+}
+
+TEST(ActionInterfaceTest, MakeAction) {
+  Action<MyGlobalFunction> action = MakeAction(new MyActionImpl);
+
+  // When exercising the Perform() method of Action<F>, we must pass
+  // it a tuple whose size and type are compatible with F's argument
+  // types.  For example, if F is int(), then Perform() takes a
+  // 0-tuple; if F is void(bool, int), then Perform() takes a
+  // std::tuple<bool, int>, and so on.
+  EXPECT_EQ(5, action.Perform(std::make_tuple(true, 5)));
+}
+
+// Tests that Action<F> can be constructed from a pointer to
+// ActionInterface<F>.
+TEST(ActionTest, CanBeConstructedFromActionInterface) {
+  Action<MyGlobalFunction> action(new MyActionImpl);
+}
+
+// Tests that Action<F> delegates actual work to ActionInterface<F>.
+TEST(ActionTest, DelegatesWorkToActionInterface) {
+  const Action<MyGlobalFunction> action(new MyActionImpl);
+
+  EXPECT_EQ(5, action.Perform(std::make_tuple(true, 5)));
+  EXPECT_EQ(0, action.Perform(std::make_tuple(false, 1)));
+}
+
+// Tests that Action<F> can be copied.
+TEST(ActionTest, IsCopyable) {
+  Action<MyGlobalFunction> a1(new MyActionImpl);
+  Action<MyGlobalFunction> a2(a1);  // Tests the copy constructor.
+
+  // a1 should continue to work after being copied from.
+  EXPECT_EQ(5, a1.Perform(std::make_tuple(true, 5)));
+  EXPECT_EQ(0, a1.Perform(std::make_tuple(false, 1)));
+
+  // a2 should work like the action it was copied from.
+  EXPECT_EQ(5, a2.Perform(std::make_tuple(true, 5)));
+  EXPECT_EQ(0, a2.Perform(std::make_tuple(false, 1)));
+
+  a2 = a1;  // Tests the assignment operator.
+
+  // a1 should continue to work after being copied from.
+  EXPECT_EQ(5, a1.Perform(std::make_tuple(true, 5)));
+  EXPECT_EQ(0, a1.Perform(std::make_tuple(false, 1)));
+
+  // a2 should work like the action it was copied from.
+  EXPECT_EQ(5, a2.Perform(std::make_tuple(true, 5)));
+  EXPECT_EQ(0, a2.Perform(std::make_tuple(false, 1)));
+}
+
+// Tests that an Action<From> object can be converted to a
+// compatible Action<To> object.
+
+class IsNotZero : public ActionInterface<bool(int)> {  // NOLINT
+ public:
+  bool Perform(const std::tuple<int>& arg) override {
+    return std::get<0>(arg) != 0;
+  }
+};
+
+TEST(ActionTest, CanBeConvertedToOtherActionType) {
+  const Action<bool(int)> a1(new IsNotZero);           // NOLINT
+  const Action<int(char)> a2 = Action<int(char)>(a1);  // NOLINT
+  EXPECT_EQ(1, a2.Perform(std::make_tuple('a')));
+  EXPECT_EQ(0, a2.Perform(std::make_tuple('\0')));
+}
+
+// The following two classes are for testing MakePolymorphicAction().
+
+// Implements a polymorphic action that returns the second of the
+// arguments it receives.
+class ReturnSecondArgumentAction {
+ public:
+  // We want to verify that MakePolymorphicAction() can work with a
+  // polymorphic action whose Perform() method template is either
+  // const or not.  This lets us verify the non-const case.
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) {
+    return std::get<1>(args);
+  }
+};
+
+// Implements a polymorphic action that can be used in a nullary
+// function to return 0.
+class ReturnZeroFromNullaryFunctionAction {
+ public:
+  // For testing that MakePolymorphicAction() works when the
+  // implementation class' Perform() method template takes only one
+  // template parameter.
+  //
+  // We want to verify that MakePolymorphicAction() can work with a
+  // polymorphic action whose Perform() method template is either
+  // const or not.  This lets us verify the const case.
+  template <typename Result>
+  Result Perform(const std::tuple<>&) const {
+    return 0;
+  }
+};
+
+// These functions verify that MakePolymorphicAction() returns a
+// PolymorphicAction<T> where T is the argument's type.
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+
+PolymorphicAction<ReturnZeroFromNullaryFunctionAction>
+ReturnZeroFromNullaryFunction() {
+  return MakePolymorphicAction(ReturnZeroFromNullaryFunctionAction());
+}
+
+// Tests that MakePolymorphicAction() turns a polymorphic action
+// implementation class into a polymorphic action.
+TEST(MakePolymorphicActionTest, ConstructsActionFromImpl) {
+  Action<int(bool, int, double)> a1 = ReturnSecondArgument();  // NOLINT
+  EXPECT_EQ(5, a1.Perform(std::make_tuple(false, 5, 2.0)));
+}
+
+// Tests that MakePolymorphicAction() works when the implementation
+// class' Perform() method template has only one template parameter.
+TEST(MakePolymorphicActionTest, WorksWhenPerformHasOneTemplateParameter) {
+  Action<int()> a1 = ReturnZeroFromNullaryFunction();
+  EXPECT_EQ(0, a1.Perform(std::make_tuple()));
+
+  Action<void*()> a2 = ReturnZeroFromNullaryFunction();
+  EXPECT_TRUE(a2.Perform(std::make_tuple()) == nullptr);
+}
+
+// Tests that Return() works as an action for void-returning
+// functions.
+TEST(ReturnTest, WorksForVoid) {
+  const Action<void(int)> ret = Return();  // NOLINT
+  return ret.Perform(std::make_tuple(1));
+}
+
+// Tests that Return(v) returns v.
+TEST(ReturnTest, ReturnsGivenValue) {
+  Action<int()> ret = Return(1);  // NOLINT
+  EXPECT_EQ(1, ret.Perform(std::make_tuple()));
+
+  ret = Return(-5);
+  EXPECT_EQ(-5, ret.Perform(std::make_tuple()));
+}
+
+// Tests that Return("string literal") works.
+TEST(ReturnTest, AcceptsStringLiteral) {
+  Action<const char*()> a1 = Return("Hello");
+  EXPECT_STREQ("Hello", a1.Perform(std::make_tuple()));
+
+  Action<std::string()> a2 = Return("world");
+  EXPECT_EQ("world", a2.Perform(std::make_tuple()));
+}
+
+// Return(x) should work fine when the mock function's return type is a
+// reference-like wrapper for decltype(x), as when x is a std::string and the
+// mock function returns std::string_view.
+TEST(ReturnTest, SupportsReferenceLikeReturnType) {
+  // A reference wrapper for std::vector<int>, implicitly convertible from it.
+  struct Result {
+    const std::vector<int>* v;
+    Result(const std::vector<int>& vec) : v(&vec) {}  // NOLINT
+  };
+
+  // Set up an action for a mock function that returns the reference wrapper
+  // type, initializing it with an actual vector.
+  //
+  // The returned wrapper should be initialized with a copy of that vector
+  // that's embedded within the action itself (which should stay alive as long
+  // as the mock object is alive), rather than e.g. a reference to the temporary
+  // we feed to Return. This should work fine both for WillOnce and
+  // WillRepeatedly.
+  MockFunction<Result()> mock;
+  EXPECT_CALL(mock, Call)
+      .WillOnce(Return(std::vector<int>{17, 19, 23}))
+      .WillRepeatedly(Return(std::vector<int>{29, 31, 37}));
+
+  EXPECT_THAT(mock.AsStdFunction()(),
+              Field(&Result::v, Pointee(ElementsAre(17, 19, 23))));
+
+  EXPECT_THAT(mock.AsStdFunction()(),
+              Field(&Result::v, Pointee(ElementsAre(29, 31, 37))));
+}
+
+TEST(ReturnTest, PrefersConversionOperator) {
+  // Define types In and Out such that:
+  //
+  //  *  In is implicitly convertible to Out.
+  //  *  Out also has an explicit constructor from In.
+  //
+  struct In;
+  struct Out {
+    int x;
+
+    explicit Out(const int val) : x(val) {}
+    explicit Out(const In&) : x(0) {}
+  };
+
+  struct In {
+    operator Out() const { return Out{19}; }  // NOLINT
+  };
+
+  // Assumption check: the C++ language rules are such that a function that
+  // returns Out which uses In a return statement will use the implicit
+  // conversion path rather than the explicit constructor.
+  EXPECT_THAT([]() -> Out { return In(); }(), Field(&Out::x, 19));
+
+  // Return should work the same way: if the mock function's return type is Out
+  // and we feed Return an In value, then the Out should be created through the
+  // implicit conversion path rather than the explicit constructor.
+  MockFunction<Out()> mock;
+  EXPECT_CALL(mock, Call).WillOnce(Return(In()));
+  EXPECT_THAT(mock.AsStdFunction()(), Field(&Out::x, 19));
+}
+
+// It should be possible to use Return(R) with a mock function result type U
+// that is convertible from const R& but *not* R (such as
+// std::reference_wrapper). This should work for both WillOnce and
+// WillRepeatedly.
+TEST(ReturnTest, ConversionRequiresConstLvalueReference) {
+  using R = int;
+  using U = std::reference_wrapper<const int>;
+
+  static_assert(std::is_convertible<const R&, U>::value, "");
+  static_assert(!std::is_convertible<R, U>::value, "");
+
+  MockFunction<U()> mock;
+  EXPECT_CALL(mock, Call).WillOnce(Return(17)).WillRepeatedly(Return(19));
+
+  EXPECT_EQ(17, mock.AsStdFunction()());
+  EXPECT_EQ(19, mock.AsStdFunction()());
+}
+
+// Return(x) should not be usable with a mock function result type that's
+// implicitly convertible from decltype(x) but requires a non-const lvalue
+// reference to the input. It doesn't make sense for the conversion operator to
+// modify the input.
+TEST(ReturnTest, ConversionRequiresMutableLvalueReference) {
+  // Set up a type that is implicitly convertible from std::string&, but not
+  // std::string&& or `const std::string&`.
+  //
+  // Avoid asserting about conversion from std::string on MSVC, which seems to
+  // implement std::is_convertible incorrectly in this case.
+  struct S {
+    S(std::string&) {}  // NOLINT
+  };
+
+  static_assert(std::is_convertible<std::string&, S>::value, "");
+#ifndef _MSC_VER
+  static_assert(!std::is_convertible<std::string&&, S>::value, "");
+#endif
+  static_assert(!std::is_convertible<const std::string&, S>::value, "");
+
+  // It shouldn't be possible to use the result of Return(std::string) in a
+  // context where an S is needed.
+  //
+  // Here too we disable the assertion for MSVC, since its incorrect
+  // implementation of is_convertible causes our SFINAE to be wrong.
+  using RA = decltype(Return(std::string()));
+
+  static_assert(!std::is_convertible<RA, Action<S()>>::value, "");
+#ifndef _MSC_VER
+  static_assert(!std::is_convertible<RA, OnceAction<S()>>::value, "");
+#endif
+}
+
+TEST(ReturnTest, MoveOnlyResultType) {
+  // Return should support move-only result types when used with WillOnce.
+  {
+    MockFunction<std::unique_ptr<int>()> mock;
+    EXPECT_CALL(mock, Call)
+        // NOLINTNEXTLINE
+        .WillOnce(Return(std::unique_ptr<int>(new int(17))));
+
+    EXPECT_THAT(mock.AsStdFunction()(), Pointee(17));
+  }
+
+  // The result of Return should not be convertible to Action (so it can't be
+  // used with WillRepeatedly).
+  static_assert(!std::is_convertible<decltype(Return(std::unique_ptr<int>())),
+                                     Action<std::unique_ptr<int>()>>::value,
+                "");
+}
+
+// Tests that Return(v) is covariant.
+
+struct Base {
+  bool operator==(const Base&) { return true; }
+};
+
+struct Derived : public Base {
+  bool operator==(const Derived&) { return true; }
+};
+
+TEST(ReturnTest, IsCovariant) {
+  Base base;
+  Derived derived;
+  Action<Base*()> ret = Return(&base);
+  EXPECT_EQ(&base, ret.Perform(std::make_tuple()));
+
+  ret = Return(&derived);
+  EXPECT_EQ(&derived, ret.Perform(std::make_tuple()));
+}
+
+// Tests that the type of the value passed into Return is converted into T
+// when the action is cast to Action<T(...)> rather than when the action is
+// performed. See comments on testing::internal::ReturnAction in
+// gmock-actions.h for more information.
+class FromType {
+ public:
+  explicit FromType(bool* is_converted) : converted_(is_converted) {}
+  bool* converted() const { return converted_; }
+
+ private:
+  bool* const converted_;
+};
+
+class ToType {
+ public:
+  // Must allow implicit conversion due to use in ImplicitCast_<T>.
+  ToType(const FromType& x) { *x.converted() = true; }  // NOLINT
+};
+
+TEST(ReturnTest, ConvertsArgumentWhenConverted) {
+  bool converted = false;
+  FromType x(&converted);
+  Action<ToType()> action(Return(x));
+  EXPECT_TRUE(converted) << "Return must convert its argument in its own "
+                         << "conversion operator.";
+  converted = false;
+  action.Perform(std::tuple<>());
+  EXPECT_FALSE(converted) << "Action must NOT convert its argument "
+                          << "when performed.";
+}
+
+// Tests that ReturnNull() returns NULL in a pointer-returning function.
+TEST(ReturnNullTest, WorksInPointerReturningFunction) {
+  const Action<int*()> a1 = ReturnNull();
+  EXPECT_TRUE(a1.Perform(std::make_tuple()) == nullptr);
+
+  const Action<const char*(bool)> a2 = ReturnNull();  // NOLINT
+  EXPECT_TRUE(a2.Perform(std::make_tuple(true)) == nullptr);
+}
+
+// Tests that ReturnNull() returns NULL for shared_ptr and unique_ptr returning
+// functions.
+TEST(ReturnNullTest, WorksInSmartPointerReturningFunction) {
+  const Action<std::unique_ptr<const int>()> a1 = ReturnNull();
+  EXPECT_TRUE(a1.Perform(std::make_tuple()) == nullptr);
+
+  const Action<std::shared_ptr<int>(std::string)> a2 = ReturnNull();
+  EXPECT_TRUE(a2.Perform(std::make_tuple("foo")) == nullptr);
+}
+
+// Tests that ReturnRef(v) works for reference types.
+TEST(ReturnRefTest, WorksForReference) {
+  const int n = 0;
+  const Action<const int&(bool)> ret = ReturnRef(n);  // NOLINT
+
+  EXPECT_EQ(&n, &ret.Perform(std::make_tuple(true)));
+}
+
+// Tests that ReturnRef(v) is covariant.
+TEST(ReturnRefTest, IsCovariant) {
+  Base base;
+  Derived derived;
+  Action<Base&()> a = ReturnRef(base);
+  EXPECT_EQ(&base, &a.Perform(std::make_tuple()));
+
+  a = ReturnRef(derived);
+  EXPECT_EQ(&derived, &a.Perform(std::make_tuple()));
+}
+
+template <typename T, typename = decltype(ReturnRef(std::declval<T&&>()))>
+bool CanCallReturnRef(T&&) {
+  return true;
+}
+bool CanCallReturnRef(Unused) { return false; }
+
+// Tests that ReturnRef(v) is working with non-temporaries (T&)
+TEST(ReturnRefTest, WorksForNonTemporary) {
+  int scalar_value = 123;
+  EXPECT_TRUE(CanCallReturnRef(scalar_value));
+
+  std::string non_scalar_value("ABC");
+  EXPECT_TRUE(CanCallReturnRef(non_scalar_value));
+
+  const int const_scalar_value{321};
+  EXPECT_TRUE(CanCallReturnRef(const_scalar_value));
+
+  const std::string const_non_scalar_value("CBA");
+  EXPECT_TRUE(CanCallReturnRef(const_non_scalar_value));
+}
+
+// Tests that ReturnRef(v) is not working with temporaries (T&&)
+TEST(ReturnRefTest, DoesNotWorkForTemporary) {
+  auto scalar_value = []() -> int { return 123; };
+  EXPECT_FALSE(CanCallReturnRef(scalar_value()));
+
+  auto non_scalar_value = []() -> std::string { return "ABC"; };
+  EXPECT_FALSE(CanCallReturnRef(non_scalar_value()));
+
+  // cannot use here callable returning "const scalar type",
+  // because such const for scalar return type is ignored
+  EXPECT_FALSE(CanCallReturnRef(static_cast<const int>(321)));
+
+  auto const_non_scalar_value = []() -> const std::string { return "CBA"; };
+  EXPECT_FALSE(CanCallReturnRef(const_non_scalar_value()));
+}
+
+// Tests that ReturnRefOfCopy(v) works for reference types.
+TEST(ReturnRefOfCopyTest, WorksForReference) {
+  int n = 42;
+  const Action<const int&()> ret = ReturnRefOfCopy(n);
+
+  EXPECT_NE(&n, &ret.Perform(std::make_tuple()));
+  EXPECT_EQ(42, ret.Perform(std::make_tuple()));
+
+  n = 43;
+  EXPECT_NE(&n, &ret.Perform(std::make_tuple()));
+  EXPECT_EQ(42, ret.Perform(std::make_tuple()));
+}
+
+// Tests that ReturnRefOfCopy(v) is covariant.
+TEST(ReturnRefOfCopyTest, IsCovariant) {
+  Base base;
+  Derived derived;
+  Action<Base&()> a = ReturnRefOfCopy(base);
+  EXPECT_NE(&base, &a.Perform(std::make_tuple()));
+
+  a = ReturnRefOfCopy(derived);
+  EXPECT_NE(&derived, &a.Perform(std::make_tuple()));
+}
+
+// Tests that ReturnRoundRobin(v) works with initializer lists
+TEST(ReturnRoundRobinTest, WorksForInitList) {
+  Action<int()> ret = ReturnRoundRobin({1, 2, 3});
+
+  EXPECT_EQ(1, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(2, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(3, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(1, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(2, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(3, ret.Perform(std::make_tuple()));
+}
+
+// Tests that ReturnRoundRobin(v) works with vectors
+TEST(ReturnRoundRobinTest, WorksForVector) {
+  std::vector<double> v = {4.4, 5.5, 6.6};
+  Action<double()> ret = ReturnRoundRobin(v);
+
+  EXPECT_EQ(4.4, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(5.5, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(6.6, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(4.4, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(5.5, ret.Perform(std::make_tuple()));
+  EXPECT_EQ(6.6, ret.Perform(std::make_tuple()));
+}
+
+// Tests that DoDefault() does the default action for the mock method.
+
+class MockClass {
+ public:
+  MockClass() = default;
+
+  MOCK_METHOD1(IntFunc, int(bool flag));  // NOLINT
+  MOCK_METHOD0(Foo, MyNonDefaultConstructible());
+  MOCK_METHOD0(MakeUnique, std::unique_ptr<int>());
+  MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>());
+  MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>());
+  MOCK_METHOD1(TakeUnique, int(std::unique_ptr<int>));
+  MOCK_METHOD2(TakeUnique,
+               int(const std::unique_ptr<int>&, std::unique_ptr<int>));
+
+ private:
+  MockClass(const MockClass&) = delete;
+  MockClass& operator=(const MockClass&) = delete;
+};
+
+// Tests that DoDefault() returns the built-in default value for the
+// return type by default.
+TEST(DoDefaultTest, ReturnsBuiltInDefaultValueByDefault) {
+  MockClass mock;
+  EXPECT_CALL(mock, IntFunc(_)).WillOnce(DoDefault());
+  EXPECT_EQ(0, mock.IntFunc(true));
+}
+
+// Tests that DoDefault() throws (when exceptions are enabled) or aborts
+// the process when there is no built-in default value for the return type.
+TEST(DoDefaultDeathTest, DiesForUnknowType) {
+  MockClass mock;
+  EXPECT_CALL(mock, Foo()).WillRepeatedly(DoDefault());
+#if GTEST_HAS_EXCEPTIONS
+  EXPECT_ANY_THROW(mock.Foo());
+#else
+  EXPECT_DEATH_IF_SUPPORTED({ mock.Foo(); }, "");
+#endif
+}
+
+// Tests that using DoDefault() inside a composite action leads to a
+// run-time error.
+
+void VoidFunc(bool /* flag */) {}
+
+TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
+  MockClass mock;
+  EXPECT_CALL(mock, IntFunc(_))
+      .WillRepeatedly(DoAll(Invoke(VoidFunc), DoDefault()));
+
+  // Ideally we should verify the error message as well.  Sadly,
+  // EXPECT_DEATH() can only capture stderr, while Google Mock's
+  // errors are printed on stdout.  Therefore we have to settle for
+  // not verifying the message.
+  EXPECT_DEATH_IF_SUPPORTED({ mock.IntFunc(true); }, "");
+}
+
+// Tests that DoDefault() returns the default value set by
+// DefaultValue<T>::Set() when it's not overridden by an ON_CALL().
+TEST(DoDefaultTest, ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne) {
+  DefaultValue<int>::Set(1);
+  MockClass mock;
+  EXPECT_CALL(mock, IntFunc(_)).WillOnce(DoDefault());
+  EXPECT_EQ(1, mock.IntFunc(false));
+  DefaultValue<int>::Clear();
+}
+
+// Tests that DoDefault() does the action specified by ON_CALL().
+TEST(DoDefaultTest, DoesWhatOnCallSpecifies) {
+  MockClass mock;
+  ON_CALL(mock, IntFunc(_)).WillByDefault(Return(2));
+  EXPECT_CALL(mock, IntFunc(_)).WillOnce(DoDefault());
+  EXPECT_EQ(2, mock.IntFunc(false));
+}
+
+// Tests that using DoDefault() in ON_CALL() leads to a run-time failure.
+TEST(DoDefaultTest, CannotBeUsedInOnCall) {
+  MockClass mock;
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        ON_CALL(mock, IntFunc(_)).WillByDefault(DoDefault());
+      },
+      "DoDefault() cannot be used in ON_CALL()");
+}
+
+// Tests that SetArgPointee<N>(v) sets the variable pointed to by
+// the N-th (0-based) argument to v.
+TEST(SetArgPointeeTest, SetsTheNthPointee) {
+  typedef void MyFunction(bool, int*, char*);
+  Action<MyFunction> a = SetArgPointee<1>(2);
+
+  int n = 0;
+  char ch = '\0';
+  a.Perform(std::make_tuple(true, &n, &ch));
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('\0', ch);
+
+  a = SetArgPointee<2>('a');
+  n = 0;
+  ch = '\0';
+  a.Perform(std::make_tuple(true, &n, &ch));
+  EXPECT_EQ(0, n);
+  EXPECT_EQ('a', ch);
+}
+
+// Tests that SetArgPointee<N>() accepts a string literal.
+TEST(SetArgPointeeTest, AcceptsStringLiteral) {
+  typedef void MyFunction(std::string*, const char**);
+  Action<MyFunction> a = SetArgPointee<0>("hi");
+  std::string str;
+  const char* ptr = nullptr;
+  a.Perform(std::make_tuple(&str, &ptr));
+  EXPECT_EQ("hi", str);
+  EXPECT_TRUE(ptr == nullptr);
+
+  a = SetArgPointee<1>("world");
+  str = "";
+  a.Perform(std::make_tuple(&str, &ptr));
+  EXPECT_EQ("", str);
+  EXPECT_STREQ("world", ptr);
+}
+
+TEST(SetArgPointeeTest, AcceptsWideStringLiteral) {
+  typedef void MyFunction(const wchar_t**);
+  Action<MyFunction> a = SetArgPointee<0>(L"world");
+  const wchar_t* ptr = nullptr;
+  a.Perform(std::make_tuple(&ptr));
+  EXPECT_STREQ(L"world", ptr);
+
+#if GTEST_HAS_STD_WSTRING
+
+  typedef void MyStringFunction(std::wstring*);
+  Action<MyStringFunction> a2 = SetArgPointee<0>(L"world");
+  std::wstring str = L"";
+  a2.Perform(std::make_tuple(&str));
+  EXPECT_EQ(L"world", str);
+
+#endif
+}
+
+// Tests that SetArgPointee<N>() accepts a char pointer.
+TEST(SetArgPointeeTest, AcceptsCharPointer) {
+  typedef void MyFunction(bool, std::string*, const char**);
+  const char* const hi = "hi";
+  Action<MyFunction> a = SetArgPointee<1>(hi);
+  std::string str;
+  const char* ptr = nullptr;
+  a.Perform(std::make_tuple(true, &str, &ptr));
+  EXPECT_EQ("hi", str);
+  EXPECT_TRUE(ptr == nullptr);
+
+  char world_array[] = "world";
+  char* const world = world_array;
+  a = SetArgPointee<2>(world);
+  str = "";
+  a.Perform(std::make_tuple(true, &str, &ptr));
+  EXPECT_EQ("", str);
+  EXPECT_EQ(world, ptr);
+}
+
+TEST(SetArgPointeeTest, AcceptsWideCharPointer) {
+  typedef void MyFunction(bool, const wchar_t**);
+  const wchar_t* const hi = L"hi";
+  Action<MyFunction> a = SetArgPointee<1>(hi);
+  const wchar_t* ptr = nullptr;
+  a.Perform(std::make_tuple(true, &ptr));
+  EXPECT_EQ(hi, ptr);
+
+#if GTEST_HAS_STD_WSTRING
+
+  typedef void MyStringFunction(bool, std::wstring*);
+  wchar_t world_array[] = L"world";
+  wchar_t* const world = world_array;
+  Action<MyStringFunction> a2 = SetArgPointee<1>(world);
+  std::wstring str;
+  a2.Perform(std::make_tuple(true, &str));
+  EXPECT_EQ(world_array, str);
+#endif
+}
+
+// Tests that SetArgumentPointee<N>(v) sets the variable pointed to by
+// the N-th (0-based) argument to v.
+TEST(SetArgumentPointeeTest, SetsTheNthPointee) {
+  typedef void MyFunction(bool, int*, char*);
+  Action<MyFunction> a = SetArgumentPointee<1>(2);
+
+  int n = 0;
+  char ch = '\0';
+  a.Perform(std::make_tuple(true, &n, &ch));
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('\0', ch);
+
+  a = SetArgumentPointee<2>('a');
+  n = 0;
+  ch = '\0';
+  a.Perform(std::make_tuple(true, &n, &ch));
+  EXPECT_EQ(0, n);
+  EXPECT_EQ('a', ch);
+}
+
+// Sample functions and functors for testing Invoke() and etc.
+int Nullary() { return 1; }
+
+class NullaryFunctor {
+ public:
+  int operator()() { return 2; }
+};
+
+bool g_done = false;
+void VoidNullary() { g_done = true; }
+
+class VoidNullaryFunctor {
+ public:
+  void operator()() { g_done = true; }
+};
+
+short Short(short n) { return n; }  // NOLINT
+char Char(char ch) { return ch; }
+
+const char* CharPtr(const char* s) { return s; }
+
+bool Unary(int x) { return x < 0; }
+
+const char* Binary(const char* input, short n) { return input + n; }  // NOLINT
+
+void VoidBinary(int, char) { g_done = true; }
+
+int Ternary(int x, char y, short z) { return x + y + z; }  // NOLINT
+
+int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
+
+class Foo {
+ public:
+  Foo() : value_(123) {}
+
+  int Nullary() const { return value_; }
+
+ private:
+  int value_;
+};
+
+// Tests InvokeWithoutArgs(function).
+TEST(InvokeWithoutArgsTest, Function) {
+  // As an action that takes one argument.
+  Action<int(int)> a = InvokeWithoutArgs(Nullary);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
+
+  // As an action that takes two arguments.
+  Action<int(int, double)> a2 = InvokeWithoutArgs(Nullary);  // NOLINT
+  EXPECT_EQ(1, a2.Perform(std::make_tuple(2, 3.5)));
+
+  // As an action that returns void.
+  Action<void(int)> a3 = InvokeWithoutArgs(VoidNullary);  // NOLINT
+  g_done = false;
+  a3.Perform(std::make_tuple(1));
+  EXPECT_TRUE(g_done);
+}
+
+// Tests InvokeWithoutArgs(functor).
+TEST(InvokeWithoutArgsTest, Functor) {
+  // As an action that takes no argument.
+  Action<int()> a = InvokeWithoutArgs(NullaryFunctor());  // NOLINT
+  EXPECT_EQ(2, a.Perform(std::make_tuple()));
+
+  // As an action that takes three arguments.
+  Action<int(int, double, char)> a2 =  // NOLINT
+      InvokeWithoutArgs(NullaryFunctor());
+  EXPECT_EQ(2, a2.Perform(std::make_tuple(3, 3.5, 'a')));
+
+  // As an action that returns void.
+  Action<void()> a3 = InvokeWithoutArgs(VoidNullaryFunctor());
+  g_done = false;
+  a3.Perform(std::make_tuple());
+  EXPECT_TRUE(g_done);
+}
+
+// Tests InvokeWithoutArgs(obj_ptr, method).
+TEST(InvokeWithoutArgsTest, Method) {
+  Foo foo;
+  Action<int(bool, char)> a =  // NOLINT
+      InvokeWithoutArgs(&foo, &Foo::Nullary);
+  EXPECT_EQ(123, a.Perform(std::make_tuple(true, 'a')));
+}
+
+// Tests using IgnoreResult() on a polymorphic action.
+TEST(IgnoreResultTest, PolymorphicAction) {
+  Action<void(int)> a = IgnoreResult(Return(5));  // NOLINT
+  a.Perform(std::make_tuple(1));
+}
+
+// Tests using IgnoreResult() on a monomorphic action.
+
+int ReturnOne() {
+  g_done = true;
+  return 1;
+}
+
+TEST(IgnoreResultTest, MonomorphicAction) {
+  g_done = false;
+  Action<void()> a = IgnoreResult(Invoke(ReturnOne));
+  a.Perform(std::make_tuple());
+  EXPECT_TRUE(g_done);
+}
+
+// Tests using IgnoreResult() on an action that returns a class type.
+
+MyNonDefaultConstructible ReturnMyNonDefaultConstructible(double /* x */) {
+  g_done = true;
+  return MyNonDefaultConstructible(42);
+}
+
+TEST(IgnoreResultTest, ActionReturningClass) {
+  g_done = false;
+  Action<void(int)> a =
+      IgnoreResult(Invoke(ReturnMyNonDefaultConstructible));  // NOLINT
+  a.Perform(std::make_tuple(2));
+  EXPECT_TRUE(g_done);
+}
+
+TEST(AssignTest, Int) {
+  int x = 0;
+  Action<void(int)> a = Assign(&x, 5);
+  a.Perform(std::make_tuple(0));
+  EXPECT_EQ(5, x);
+}
+
+TEST(AssignTest, String) {
+  ::std::string x;
+  Action<void(void)> a = Assign(&x, "Hello, world");
+  a.Perform(std::make_tuple());
+  EXPECT_EQ("Hello, world", x);
+}
+
+TEST(AssignTest, CompatibleTypes) {
+  double x = 0;
+  Action<void(int)> a = Assign(&x, 5);
+  a.Perform(std::make_tuple(0));
+  EXPECT_DOUBLE_EQ(5, x);
+}
+
+// DoAll should support &&-qualified actions when used with WillOnce.
+TEST(DoAll, SupportsRefQualifiedActions) {
+  struct InitialAction {
+    void operator()(const int arg) && { EXPECT_EQ(17, arg); }
+  };
+
+  struct FinalAction {
+    int operator()() && { return 19; }
+  };
+
+  MockFunction<int(int)> mock;
+  EXPECT_CALL(mock, Call).WillOnce(DoAll(InitialAction{}, FinalAction{}));
+  EXPECT_EQ(19, mock.AsStdFunction()(17));
+}
+
+// DoAll should never provide rvalue references to the initial actions. If the
+// mock action itself accepts an rvalue reference or a non-scalar object by
+// value then the final action should receive an rvalue reference, but initial
+// actions should receive only lvalue references.
+TEST(DoAll, ProvidesLvalueReferencesToInitialActions) {
+  struct Obj {};
+
+  // Mock action accepts by value: the initial action should be fed a const
+  // lvalue reference, and the final action an rvalue reference.
+  {
+    struct InitialAction {
+      void operator()(Obj&) const { FAIL() << "Unexpected call"; }
+      void operator()(const Obj&) const {}
+      void operator()(Obj&&) const { FAIL() << "Unexpected call"; }
+      void operator()(const Obj&&) const { FAIL() << "Unexpected call"; }
+    };
+
+    MockFunction<void(Obj)> mock;
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(InitialAction{}, InitialAction{}, [](Obj&&) {}))
+        .WillRepeatedly(DoAll(InitialAction{}, InitialAction{}, [](Obj&&) {}));
+
+    mock.AsStdFunction()(Obj{});
+    mock.AsStdFunction()(Obj{});
+  }
+
+  // Mock action accepts by const lvalue reference: both actions should receive
+  // a const lvalue reference.
+  {
+    struct InitialAction {
+      void operator()(Obj&) const { FAIL() << "Unexpected call"; }
+      void operator()(const Obj&) const {}
+      void operator()(Obj&&) const { FAIL() << "Unexpected call"; }
+      void operator()(const Obj&&) const { FAIL() << "Unexpected call"; }
+    };
+
+    MockFunction<void(const Obj&)> mock;
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(InitialAction{}, InitialAction{}, [](const Obj&) {}))
+        .WillRepeatedly(
+            DoAll(InitialAction{}, InitialAction{}, [](const Obj&) {}));
+
+    mock.AsStdFunction()(Obj{});
+    mock.AsStdFunction()(Obj{});
+  }
+
+  // Mock action accepts by non-const lvalue reference: both actions should get
+  // a non-const lvalue reference if they want them.
+  {
+    struct InitialAction {
+      void operator()(Obj&) const {}
+      void operator()(Obj&&) const { FAIL() << "Unexpected call"; }
+    };
+
+    MockFunction<void(Obj&)> mock;
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(InitialAction{}, InitialAction{}, [](Obj&) {}))
+        .WillRepeatedly(DoAll(InitialAction{}, InitialAction{}, [](Obj&) {}));
+
+    Obj obj;
+    mock.AsStdFunction()(obj);
+    mock.AsStdFunction()(obj);
+  }
+
+  // Mock action accepts by rvalue reference: the initial actions should receive
+  // a non-const lvalue reference if it wants it, and the final action an rvalue
+  // reference.
+  {
+    struct InitialAction {
+      void operator()(Obj&) const {}
+      void operator()(Obj&&) const { FAIL() << "Unexpected call"; }
+    };
+
+    MockFunction<void(Obj&&)> mock;
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(InitialAction{}, InitialAction{}, [](Obj&&) {}))
+        .WillRepeatedly(DoAll(InitialAction{}, InitialAction{}, [](Obj&&) {}));
+
+    mock.AsStdFunction()(Obj{});
+    mock.AsStdFunction()(Obj{});
+  }
+
+  // &&-qualified initial actions should also be allowed with WillOnce.
+  {
+    struct InitialAction {
+      void operator()(Obj&) && {}
+    };
+
+    MockFunction<void(Obj&)> mock;
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(InitialAction{}, InitialAction{}, [](Obj&) {}));
+
+    Obj obj;
+    mock.AsStdFunction()(obj);
+  }
+
+  {
+    struct InitialAction {
+      void operator()(Obj&) && {}
+    };
+
+    MockFunction<void(Obj&&)> mock;
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(InitialAction{}, InitialAction{}, [](Obj&&) {}));
+
+    mock.AsStdFunction()(Obj{});
+  }
+}
+
+// DoAll should support being used with type-erased Action objects, both through
+// WillOnce and WillRepeatedly.
+TEST(DoAll, SupportsTypeErasedActions) {
+  // With only type-erased actions.
+  const Action<void()> initial_action = [] {};
+  const Action<int()> final_action = [] { return 17; };
+
+  MockFunction<int()> mock;
+  EXPECT_CALL(mock, Call)
+      .WillOnce(DoAll(initial_action, initial_action, final_action))
+      .WillRepeatedly(DoAll(initial_action, initial_action, final_action));
+
+  EXPECT_EQ(17, mock.AsStdFunction()());
+
+  // With &&-qualified and move-only final action.
+  {
+    struct FinalAction {
+      FinalAction() = default;
+      FinalAction(FinalAction&&) = default;
+
+      int operator()() && { return 17; }
+    };
+
+    EXPECT_CALL(mock, Call)
+        .WillOnce(DoAll(initial_action, initial_action, FinalAction{}));
+
+    EXPECT_EQ(17, mock.AsStdFunction()());
+  }
+}
+
+// A DoAll action should be convertible to a OnceAction, even when its component
+// sub-actions are user-provided types that define only an Action conversion
+// operator. If they supposed being called more than once then they also support
+// being called at most once.
+TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
+  // Simplest case: only one sub-action.
+  struct CustomFinal final {
+    operator Action<int()>() {  // NOLINT
+      return Return(17);
+    }
+
+    operator Action<int(int, char)>() {  // NOLINT
+      return Return(19);
+    }
+  };
+
+  {
+    OnceAction<int()> action = DoAll(CustomFinal{});
+    EXPECT_EQ(17, std::move(action).Call());
+  }
+
+  {
+    OnceAction<int(int, char)> action = DoAll(CustomFinal{});
+    EXPECT_EQ(19, std::move(action).Call(0, 0));
+  }
+
+  // It should also work with multiple sub-actions.
+  struct CustomInitial final {
+    operator Action<void()>() {  // NOLINT
+      return [] {};
+    }
+
+    operator Action<void(int, char)>() {  // NOLINT
+      return [] {};
+    }
+  };
+
+  {
+    OnceAction<int()> action = DoAll(CustomInitial{}, CustomFinal{});
+    EXPECT_EQ(17, std::move(action).Call());
+  }
+
+  {
+    OnceAction<int(int, char)> action = DoAll(CustomInitial{}, CustomFinal{});
+    EXPECT_EQ(19, std::move(action).Call(0, 0));
+  }
+}
+
+// Tests using WithArgs and with an action that takes 1 argument.
+TEST(WithArgsTest, OneArg) {
+  Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary));  // NOLINT
+  EXPECT_TRUE(a.Perform(std::make_tuple(1.5, -1)));
+  EXPECT_FALSE(a.Perform(std::make_tuple(1.5, 1)));
+}
+
+// Tests using WithArgs with an action that takes 2 arguments.
+TEST(WithArgsTest, TwoArgs) {
+  Action<const char*(const char* s, double x, short n)> a =  // NOLINT
+      WithArgs<0, 2>(Invoke(Binary));
+  const char s[] = "Hello";
+  EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
+}
+
+struct ConcatAll {
+  std::string operator()() const { return {}; }
+  template <typename... I>
+  std::string operator()(const char* a, I... i) const {
+    return a + ConcatAll()(i...);
+  }
+};
+
+// Tests using WithArgs with an action that takes 10 arguments.
+TEST(WithArgsTest, TenArgs) {
+  Action<std::string(const char*, const char*, const char*, const char*)> a =
+      WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(ConcatAll{}));
+  EXPECT_EQ("0123210123",
+            a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
+                                      CharPtr("3"))));
+}
+
+// Tests using WithArgs with an action that is not Invoke().
+class SubtractAction : public ActionInterface<int(int, int)> {
+ public:
+  int Perform(const std::tuple<int, int>& args) override {
+    return std::get<0>(args) - std::get<1>(args);
+  }
+};
+
+TEST(WithArgsTest, NonInvokeAction) {
+  Action<int(const std::string&, int, int)> a =
+      WithArgs<2, 1>(MakeAction(new SubtractAction));
+  std::tuple<std::string, int, int> dummy =
+      std::make_tuple(std::string("hi"), 2, 10);
+  EXPECT_EQ(8, a.Perform(dummy));
+}
+
+// Tests using WithArgs to pass all original arguments in the original order.
+TEST(WithArgsTest, Identity) {
+  Action<int(int x, char y, short z)> a =  // NOLINT
+      WithArgs<0, 1, 2>(Invoke(Ternary));
+  EXPECT_EQ(123, a.Perform(std::make_tuple(100, Char(20), Short(3))));
+}
+
+// Tests using WithArgs with repeated arguments.
+TEST(WithArgsTest, RepeatedArguments) {
+  Action<int(bool, int m, int n)> a =  // NOLINT
+      WithArgs<1, 1, 1, 1>(Invoke(SumOf4));
+  EXPECT_EQ(4, a.Perform(std::make_tuple(false, 1, 10)));
+}
+
+// Tests using WithArgs with reversed argument order.
+TEST(WithArgsTest, ReversedArgumentOrder) {
+  Action<const char*(short n, const char* input)> a =  // NOLINT
+      WithArgs<1, 0>(Invoke(Binary));
+  const char s[] = "Hello";
+  EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
+}
+
+// Tests using WithArgs with compatible, but not identical, argument types.
+TEST(WithArgsTest, ArgsOfCompatibleTypes) {
+  Action<long(short x, char y, double z, char c)> a =  // NOLINT
+      WithArgs<0, 1, 3>(Invoke(Ternary));
+  EXPECT_EQ(123,
+            a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
+}
+
+// Tests using WithArgs with an action that returns void.
+TEST(WithArgsTest, VoidAction) {
+  Action<void(double x, char c, int n)> a = WithArgs<2, 1>(Invoke(VoidBinary));
+  g_done = false;
+  a.Perform(std::make_tuple(1.5, 'a', 3));
+  EXPECT_TRUE(g_done);
+}
+
+TEST(WithArgsTest, ReturnReference) {
+  Action<int&(int&, void*)> aa = WithArgs<0>([](int& a) -> int& { return a; });
+  int i = 0;
+  const int& res = aa.Perform(std::forward_as_tuple(i, nullptr));
+  EXPECT_EQ(&i, &res);
+}
+
+TEST(WithArgsTest, InnerActionWithConversion) {
+  Action<Derived*()> inner = [] { return nullptr; };
+
+  MockFunction<Base*(double)> mock;
+  EXPECT_CALL(mock, Call)
+      .WillOnce(WithoutArgs(inner))
+      .WillRepeatedly(WithoutArgs(inner));
+
+  EXPECT_EQ(nullptr, mock.AsStdFunction()(1.1));
+  EXPECT_EQ(nullptr, mock.AsStdFunction()(1.1));
+}
+
+// It should be possible to use an &&-qualified inner action as long as the
+// whole shebang is used as an rvalue with WillOnce.
+TEST(WithArgsTest, RefQualifiedInnerAction) {
+  struct SomeAction {
+    int operator()(const int arg) && {
+      EXPECT_EQ(17, arg);
+      return 19;
+    }
+  };
+
+  MockFunction<int(int, int)> mock;
+  EXPECT_CALL(mock, Call).WillOnce(WithArg<1>(SomeAction{}));
+  EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
+}
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+
+class SetErrnoAndReturnTest : public testing::Test {
+ protected:
+  void SetUp() override { errno = 0; }
+  void TearDown() override { errno = 0; }
+};
+
+TEST_F(SetErrnoAndReturnTest, Int) {
+  Action<int(void)> a = SetErrnoAndReturn(ENOTTY, -5);
+  EXPECT_EQ(-5, a.Perform(std::make_tuple()));
+  EXPECT_EQ(ENOTTY, errno);
+}
+
+TEST_F(SetErrnoAndReturnTest, Ptr) {
+  int x;
+  Action<int*(void)> a = SetErrnoAndReturn(ENOTTY, &x);
+  EXPECT_EQ(&x, a.Perform(std::make_tuple()));
+  EXPECT_EQ(ENOTTY, errno);
+}
+
+TEST_F(SetErrnoAndReturnTest, CompatibleTypes) {
+  Action<double()> a = SetErrnoAndReturn(EINVAL, 5);
+  EXPECT_DOUBLE_EQ(5.0, a.Perform(std::make_tuple()));
+  EXPECT_EQ(EINVAL, errno);
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests ByRef().
+
+// Tests that the result of ByRef() is copyable.
+TEST(ByRefTest, IsCopyable) {
+  const std::string s1 = "Hi";
+  const std::string s2 = "Hello";
+
+  auto ref_wrapper = ByRef(s1);
+  const std::string& r1 = ref_wrapper;
+  EXPECT_EQ(&s1, &r1);
+
+  // Assigns a new value to ref_wrapper.
+  ref_wrapper = ByRef(s2);
+  const std::string& r2 = ref_wrapper;
+  EXPECT_EQ(&s2, &r2);
+
+  auto ref_wrapper1 = ByRef(s1);
+  // Copies ref_wrapper1 to ref_wrapper.
+  ref_wrapper = ref_wrapper1;
+  const std::string& r3 = ref_wrapper;
+  EXPECT_EQ(&s1, &r3);
+}
+
+// Tests using ByRef() on a const value.
+TEST(ByRefTest, ConstValue) {
+  const int n = 0;
+  // int& ref = ByRef(n);  // This shouldn't compile - we have a
+  // negative compilation test to catch it.
+  const int& const_ref = ByRef(n);
+  EXPECT_EQ(&n, &const_ref);
+}
+
+// Tests using ByRef() on a non-const value.
+TEST(ByRefTest, NonConstValue) {
+  int n = 0;
+
+  // ByRef(n) can be used as either an int&,
+  int& ref = ByRef(n);
+  EXPECT_EQ(&n, &ref);
+
+  // or a const int&.
+  const int& const_ref = ByRef(n);
+  EXPECT_EQ(&n, &const_ref);
+}
+
+// Tests explicitly specifying the type when using ByRef().
+TEST(ByRefTest, ExplicitType) {
+  int n = 0;
+  const int& r1 = ByRef<const int>(n);
+  EXPECT_EQ(&n, &r1);
+
+  // ByRef<char>(n);  // This shouldn't compile - we have a negative
+  // compilation test to catch it.
+
+  Derived d;
+  Derived& r2 = ByRef<Derived>(d);
+  EXPECT_EQ(&d, &r2);
+
+  const Derived& r3 = ByRef<const Derived>(d);
+  EXPECT_EQ(&d, &r3);
+
+  Base& r4 = ByRef<Base>(d);
+  EXPECT_EQ(&d, &r4);
+
+  const Base& r5 = ByRef<const Base>(d);
+  EXPECT_EQ(&d, &r5);
+
+  // The following shouldn't compile - we have a negative compilation
+  // test for it.
+  //
+  // Base b;
+  // ByRef<Derived>(b);
+}
+
+// Tests that Google Mock prints expression ByRef(x) as a reference to x.
+TEST(ByRefTest, PrintsCorrectly) {
+  int n = 42;
+  ::std::stringstream expected, actual;
+  testing::internal::UniversalPrinter<const int&>::Print(n, &expected);
+  testing::internal::UniversalPrint(ByRef(n), &actual);
+  EXPECT_EQ(expected.str(), actual.str());
+}
+
+struct UnaryConstructorClass {
+  explicit UnaryConstructorClass(int v) : value(v) {}
+  int value;
+};
+
+// Tests using ReturnNew() with a unary constructor.
+TEST(ReturnNewTest, Unary) {
+  Action<UnaryConstructorClass*()> a = ReturnNew<UnaryConstructorClass>(4000);
+  UnaryConstructorClass* c = a.Perform(std::make_tuple());
+  EXPECT_EQ(4000, c->value);
+  delete c;
+}
+
+TEST(ReturnNewTest, UnaryWorksWhenMockMethodHasArgs) {
+  Action<UnaryConstructorClass*(bool, int)> a =
+      ReturnNew<UnaryConstructorClass>(4000);
+  UnaryConstructorClass* c = a.Perform(std::make_tuple(false, 5));
+  EXPECT_EQ(4000, c->value);
+  delete c;
+}
+
+TEST(ReturnNewTest, UnaryWorksWhenMockMethodReturnsPointerToConst) {
+  Action<const UnaryConstructorClass*()> a =
+      ReturnNew<UnaryConstructorClass>(4000);
+  const UnaryConstructorClass* c = a.Perform(std::make_tuple());
+  EXPECT_EQ(4000, c->value);
+  delete c;
+}
+
+class TenArgConstructorClass {
+ public:
+  TenArgConstructorClass(int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+                         int a8, int a9, int a10)
+      : value_(a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10) {}
+  int value_;
+};
+
+// Tests using ReturnNew() with a 10-argument constructor.
+TEST(ReturnNewTest, ConstructorThatTakes10Arguments) {
+  Action<TenArgConstructorClass*()> a = ReturnNew<TenArgConstructorClass>(
+      1000000000, 200000000, 30000000, 4000000, 500000, 60000, 7000, 800, 90,
+      0);
+  TenArgConstructorClass* c = a.Perform(std::make_tuple());
+  EXPECT_EQ(1234567890, c->value_);
+  delete c;
+}
+
+std::unique_ptr<int> UniquePtrSource() { return std::make_unique<int>(19); }
+
+std::vector<std::unique_ptr<int>> VectorUniquePtrSource() {
+  std::vector<std::unique_ptr<int>> out;
+  out.emplace_back(new int(7));
+  return out;
+}
+
+TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
+  MockClass mock;
+  std::unique_ptr<int> i(new int(19));
+  EXPECT_CALL(mock, MakeUnique()).WillOnce(Return(ByMove(std::move(i))));
+  EXPECT_CALL(mock, MakeVectorUnique())
+      .WillOnce(Return(ByMove(VectorUniquePtrSource())));
+  Derived* d = new Derived;
+  EXPECT_CALL(mock, MakeUniqueBase())
+      .WillOnce(Return(ByMove(std::unique_ptr<Derived>(d))));
+
+  std::unique_ptr<int> result1 = mock.MakeUnique();
+  EXPECT_EQ(19, *result1);
+
+  std::vector<std::unique_ptr<int>> vresult = mock.MakeVectorUnique();
+  EXPECT_EQ(1u, vresult.size());
+  EXPECT_NE(nullptr, vresult[0]);
+  EXPECT_EQ(7, *vresult[0]);
+
+  std::unique_ptr<Base> result2 = mock.MakeUniqueBase();
+  EXPECT_EQ(d, result2.get());
+}
+
+TEST(MockMethodTest, CanReturnMoveOnlyValue_DoAllReturn) {
+  testing::MockFunction<void()> mock_function;
+  MockClass mock;
+  std::unique_ptr<int> i(new int(19));
+  EXPECT_CALL(mock_function, Call());
+  EXPECT_CALL(mock, MakeUnique())
+      .WillOnce(DoAll(InvokeWithoutArgs(&mock_function,
+                                        &testing::MockFunction<void()>::Call),
+                      Return(ByMove(std::move(i)))));
+
+  std::unique_ptr<int> result1 = mock.MakeUnique();
+  EXPECT_EQ(19, *result1);
+}
+
+TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
+  MockClass mock;
+
+  // Check default value
+  DefaultValue<std::unique_ptr<int>>::SetFactory(
+      [] { return std::make_unique<int>(42); });
+  EXPECT_EQ(42, *mock.MakeUnique());
+
+  EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(Invoke(UniquePtrSource));
+  EXPECT_CALL(mock, MakeVectorUnique())
+      .WillRepeatedly(Invoke(VectorUniquePtrSource));
+  std::unique_ptr<int> result1 = mock.MakeUnique();
+  EXPECT_EQ(19, *result1);
+  std::unique_ptr<int> result2 = mock.MakeUnique();
+  EXPECT_EQ(19, *result2);
+  EXPECT_NE(result1, result2);
+
+  std::vector<std::unique_ptr<int>> vresult = mock.MakeVectorUnique();
+  EXPECT_EQ(1u, vresult.size());
+  EXPECT_NE(nullptr, vresult[0]);
+  EXPECT_EQ(7, *vresult[0]);
+}
+
+TEST(MockMethodTest, CanTakeMoveOnlyValue) {
+  MockClass mock;
+  auto make = [](int i) { return std::make_unique<int>(i); };
+
+  EXPECT_CALL(mock, TakeUnique(_)).WillRepeatedly([](std::unique_ptr<int> i) {
+    return *i;
+  });
+  // DoAll() does not compile, since it would move from its arguments twice.
+  // EXPECT_CALL(mock, TakeUnique(_, _))
+  //     .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
+  //     Return(1)));
+  EXPECT_CALL(mock, TakeUnique(testing::Pointee(7)))
+      .WillOnce(Return(-7))
+      .RetiresOnSaturation();
+  EXPECT_CALL(mock, TakeUnique(testing::IsNull()))
+      .WillOnce(Return(-1))
+      .RetiresOnSaturation();
+
+  EXPECT_EQ(5, mock.TakeUnique(make(5)));
+  EXPECT_EQ(-7, mock.TakeUnique(make(7)));
+  EXPECT_EQ(7, mock.TakeUnique(make(7)));
+  EXPECT_EQ(7, mock.TakeUnique(make(7)));
+  EXPECT_EQ(-1, mock.TakeUnique({}));
+
+  // Some arguments are moved, some passed by reference.
+  auto lvalue = make(6);
+  EXPECT_CALL(mock, TakeUnique(_, _))
+      .WillOnce([](const std::unique_ptr<int>& i, std::unique_ptr<int> j) {
+        return *i * *j;
+      });
+  EXPECT_EQ(42, mock.TakeUnique(lvalue, make(7)));
+
+  // The unique_ptr can be saved by the action.
+  std::unique_ptr<int> saved;
+  EXPECT_CALL(mock, TakeUnique(_)).WillOnce([&saved](std::unique_ptr<int> i) {
+    saved = std::move(i);
+    return 0;
+  });
+  EXPECT_EQ(0, mock.TakeUnique(make(42)));
+  EXPECT_EQ(42, *saved);
+}
+
+// It should be possible to use callables with an &&-qualified call operator
+// with WillOnce, since they will be called only once. This allows actions to
+// contain and manipulate move-only types.
+TEST(MockMethodTest, ActionHasRvalueRefQualifiedCallOperator) {
+  struct Return17 {
+    int operator()() && { return 17; }
+  };
+
+  // Action is directly compatible with mocked function type.
+  {
+    MockFunction<int()> mock;
+    EXPECT_CALL(mock, Call).WillOnce(Return17());
+
+    EXPECT_EQ(17, mock.AsStdFunction()());
+  }
+
+  // Action doesn't want mocked function arguments.
+  {
+    MockFunction<int(int)> mock;
+    EXPECT_CALL(mock, Call).WillOnce(Return17());
+
+    EXPECT_EQ(17, mock.AsStdFunction()(0));
+  }
+}
+
+// Edge case: if an action has both a const-qualified and an &&-qualified call
+// operator, there should be no "ambiguous call" errors. The &&-qualified
+// operator should be used by WillOnce (since it doesn't need to retain the
+// action beyond one call), and the const-qualified one by WillRepeatedly.
+TEST(MockMethodTest, ActionHasMultipleCallOperators) {
+  struct ReturnInt {
+    int operator()() && { return 17; }
+    int operator()() const& { return 19; }
+  };
+
+  // Directly compatible with mocked function type.
+  {
+    MockFunction<int()> mock;
+    EXPECT_CALL(mock, Call).WillOnce(ReturnInt()).WillRepeatedly(ReturnInt());
+
+    EXPECT_EQ(17, mock.AsStdFunction()());
+    EXPECT_EQ(19, mock.AsStdFunction()());
+    EXPECT_EQ(19, mock.AsStdFunction()());
+  }
+
+  // Ignores function arguments.
+  {
+    MockFunction<int(int)> mock;
+    EXPECT_CALL(mock, Call).WillOnce(ReturnInt()).WillRepeatedly(ReturnInt());
+
+    EXPECT_EQ(17, mock.AsStdFunction()(0));
+    EXPECT_EQ(19, mock.AsStdFunction()(0));
+    EXPECT_EQ(19, mock.AsStdFunction()(0));
+  }
+}
+
+// WillOnce should have no problem coping with a move-only action, whether it is
+// &&-qualified or not.
+TEST(MockMethodTest, MoveOnlyAction) {
+  // &&-qualified
+  {
+    struct Return17 {
+      Return17() = default;
+      Return17(Return17&&) = default;
+
+      Return17(const Return17&) = delete;
+      Return17 operator=(const Return17&) = delete;
+
+      int operator()() && { return 17; }
+    };
+
+    MockFunction<int()> mock;
+    EXPECT_CALL(mock, Call).WillOnce(Return17());
+    EXPECT_EQ(17, mock.AsStdFunction()());
+  }
+
+  // Not &&-qualified
+  {
+    struct Return17 {
+      Return17() = default;
+      Return17(Return17&&) = default;
+
+      Return17(const Return17&) = delete;
+      Return17 operator=(const Return17&) = delete;
+
+      int operator()() const { return 17; }
+    };
+
+    MockFunction<int()> mock;
+    EXPECT_CALL(mock, Call).WillOnce(Return17());
+    EXPECT_EQ(17, mock.AsStdFunction()());
+  }
+}
+
+// It should be possible to use an action that returns a value with a mock
+// function that doesn't, both through WillOnce and WillRepeatedly.
+TEST(MockMethodTest, ActionReturnsIgnoredValue) {
+  struct ReturnInt {
+    int operator()() const { return 0; }
+  };
+
+  MockFunction<void()> mock;
+  EXPECT_CALL(mock, Call).WillOnce(ReturnInt()).WillRepeatedly(ReturnInt());
+
+  mock.AsStdFunction()();
+  mock.AsStdFunction()();
+}
+
+// Despite the fanciness around move-only actions and so on, it should still be
+// possible to hand an lvalue reference to a copyable action to WillOnce.
+TEST(MockMethodTest, WillOnceCanAcceptLvalueReference) {
+  MockFunction<int()> mock;
+
+  const auto action = [] { return 17; };
+  EXPECT_CALL(mock, Call).WillOnce(action);
+
+  EXPECT_EQ(17, mock.AsStdFunction()());
+}
+
+// A callable that doesn't use SFINAE to restrict its call operator's overload
+// set, but is still picky about which arguments it will accept.
+struct StaticAssertSingleArgument {
+  template <typename... Args>
+  static constexpr bool CheckArgs() {
+    static_assert(sizeof...(Args) == 1, "");
+    return true;
+  }
+
+  template <typename... Args, bool = CheckArgs<Args...>()>
+  int operator()(Args...) const {
+    return 17;
+  }
+};
+
+// WillOnce and WillRepeatedly should both work fine with naïve implementations
+// of actions that don't use SFINAE to limit the overload set for their call
+// operator. If they are compatible with the actual mocked signature, we
+// shouldn't probe them with no arguments and trip a static_assert.
+TEST(MockMethodTest, ActionSwallowsAllArguments) {
+  MockFunction<int(int)> mock;
+  EXPECT_CALL(mock, Call)
+      .WillOnce(StaticAssertSingleArgument{})
+      .WillRepeatedly(StaticAssertSingleArgument{});
+
+  EXPECT_EQ(17, mock.AsStdFunction()(0));
+  EXPECT_EQ(17, mock.AsStdFunction()(0));
+}
+
+struct ActionWithTemplatedConversionOperators {
+  template <typename... Args>
+  operator OnceAction<int(Args...)>() && {  // NOLINT
+    return [] { return 17; };
+  }
+
+  template <typename... Args>
+  operator Action<int(Args...)>() const {  // NOLINT
+    return [] { return 19; };
+  }
+};
+
+// It should be fine to hand both WillOnce and WillRepeatedly a function that
+// defines templated conversion operators to OnceAction and Action. WillOnce
+// should prefer the OnceAction version.
+TEST(MockMethodTest, ActionHasTemplatedConversionOperators) {
+  MockFunction<int()> mock;
+  EXPECT_CALL(mock, Call)
+      .WillOnce(ActionWithTemplatedConversionOperators{})
+      .WillRepeatedly(ActionWithTemplatedConversionOperators{});
+
+  EXPECT_EQ(17, mock.AsStdFunction()());
+  EXPECT_EQ(19, mock.AsStdFunction()());
+}
+
+// Tests for std::function based action.
+
+int Add(int val, int& ref, int* ptr) {  // NOLINT
+  int result = val + ref + *ptr;
+  ref = 42;
+  *ptr = 43;
+  return result;
+}
+
+int Deref(std::unique_ptr<int> ptr) { return *ptr; }
+
+struct Double {
+  template <typename T>
+  T operator()(T t) {
+    return 2 * t;
+  }
+};
+
+std::unique_ptr<int> UniqueInt(int i) { return std::make_unique<int>(i); }
+
+TEST(FunctorActionTest, ActionFromFunction) {
+  Action<int(int, int&, int*)> a = &Add;
+  int x = 1, y = 2, z = 3;
+  EXPECT_EQ(6, a.Perform(std::forward_as_tuple(x, y, &z)));
+  EXPECT_EQ(42, y);
+  EXPECT_EQ(43, z);
+
+  Action<int(std::unique_ptr<int>)> a1 = &Deref;
+  EXPECT_EQ(7, a1.Perform(std::make_tuple(UniqueInt(7))));
+}
+
+TEST(FunctorActionTest, ActionFromLambda) {
+  Action<int(bool, int)> a1 = [](bool b, int i) { return b ? i : 0; };
+  EXPECT_EQ(5, a1.Perform(std::make_tuple(true, 5)));
+  EXPECT_EQ(0, a1.Perform(std::make_tuple(false, 5)));
+
+  std::unique_ptr<int> saved;
+  Action<void(std::unique_ptr<int>)> a2 = [&saved](std::unique_ptr<int> p) {
+    saved = std::move(p);
+  };
+  a2.Perform(std::make_tuple(UniqueInt(5)));
+  EXPECT_EQ(5, *saved);
+}
+
+TEST(FunctorActionTest, PolymorphicFunctor) {
+  Action<int(int)> ai = Double();
+  EXPECT_EQ(2, ai.Perform(std::make_tuple(1)));
+  Action<double(double)> ad = Double();  // Double? Double double!
+  EXPECT_EQ(3.0, ad.Perform(std::make_tuple(1.5)));
+}
+
+TEST(FunctorActionTest, TypeConversion) {
+  // Numeric promotions are allowed.
+  const Action<bool(int)> a1 = [](int i) { return i > 1; };
+  const Action<int(bool)> a2 = Action<int(bool)>(a1);
+  EXPECT_EQ(1, a1.Perform(std::make_tuple(42)));
+  EXPECT_EQ(0, a2.Perform(std::make_tuple(42)));
+
+  // Implicit constructors are allowed.
+  const Action<bool(std::string)> s1 = [](std::string s) { return !s.empty(); };
+  const Action<int(const char*)> s2 = Action<int(const char*)>(s1);
+  EXPECT_EQ(0, s2.Perform(std::make_tuple("")));
+  EXPECT_EQ(1, s2.Perform(std::make_tuple("hello")));
+
+  // Also between the lambda and the action itself.
+  const Action<bool(std::string)> x1 = [](Unused) { return 42; };
+  const Action<bool(std::string)> x2 = [] { return 42; };
+  EXPECT_TRUE(x1.Perform(std::make_tuple("hello")));
+  EXPECT_TRUE(x2.Perform(std::make_tuple("hello")));
+
+  // Ensure decay occurs where required.
+  std::function<int()> f = [] { return 7; };
+  Action<int(int)> d = f;
+  f = nullptr;
+  EXPECT_EQ(7, d.Perform(std::make_tuple(1)));
+
+  // Ensure creation of an empty action succeeds.
+  Action<void(int)>(nullptr);
+}
+
+TEST(FunctorActionTest, UnusedArguments) {
+  // Verify that users can ignore uninteresting arguments.
+  Action<int(int, double y, double z)> a = [](int i, Unused, Unused) {
+    return 2 * i;
+  };
+  std::tuple<int, double, double> dummy = std::make_tuple(3, 7.3, 9.44);
+  EXPECT_EQ(6, a.Perform(dummy));
+}
+
+// Test that basic built-in actions work with move-only arguments.
+TEST(MoveOnlyArgumentsTest, ReturningActions) {
+  Action<int(std::unique_ptr<int>)> a = Return(1);
+  EXPECT_EQ(1, a.Perform(std::make_tuple(nullptr)));
+
+  a = testing::WithoutArgs([]() { return 7; });
+  EXPECT_EQ(7, a.Perform(std::make_tuple(nullptr)));
+
+  Action<void(std::unique_ptr<int>, int*)> a2 = testing::SetArgPointee<1>(3);
+  int x = 0;
+  a2.Perform(std::make_tuple(nullptr, &x));
+  EXPECT_EQ(x, 3);
+}
+
+ACTION(ReturnArity) { return std::tuple_size<args_type>::value; }
+
+TEST(ActionMacro, LargeArity) {
+  EXPECT_EQ(
+      1, testing::Action<int(int)>(ReturnArity()).Perform(std::make_tuple(0)));
+  EXPECT_EQ(
+      10,
+      testing::Action<int(int, int, int, int, int, int, int, int, int, int)>(
+          ReturnArity())
+          .Perform(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)));
+  EXPECT_EQ(
+      20,
+      testing::Action<int(int, int, int, int, int, int, int, int, int, int, int,
+                          int, int, int, int, int, int, int, int, int)>(
+          ReturnArity())
+          .Perform(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+                                   14, 15, 16, 17, 18, 19)));
+}
+
+}  // namespace
+}  // namespace testing
+
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4800
+#endif
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100 4503
diff --git a/3rd-party/googletest/googlemock/test/gmock-cardinalities_test.cc b/3rd-party/googletest/googlemock/test/gmock-cardinalities_test.cc
new file mode 100644
index 0000000..ad49752
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-cardinalities_test.cc
@@ -0,0 +1,424 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in cardinalities.
+
+#include <ostream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using std::stringstream;
+using testing::AnyNumber;
+using testing::AtLeast;
+using testing::AtMost;
+using testing::Between;
+using testing::Cardinality;
+using testing::CardinalityInterface;
+using testing::Exactly;
+using testing::IsSubstring;
+using testing::MakeCardinality;
+
+class MockFoo {
+ public:
+  MockFoo() = default;
+  MOCK_METHOD0(Bar, int());  // NOLINT
+
+ private:
+  MockFoo(const MockFoo&) = delete;
+  MockFoo& operator=(const MockFoo&) = delete;
+};
+
+// Tests that Cardinality objects can be default constructed.
+TEST(CardinalityTest, IsDefaultConstructable) { Cardinality c; }
+
+// Tests that Cardinality objects are copyable.
+TEST(CardinalityTest, IsCopyable) {
+  // Tests the copy constructor.
+  Cardinality c = Exactly(1);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  // Tests the assignment operator.
+  c = Exactly(2);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+}
+
+TEST(CardinalityTest, IsOverSaturatedByCallCountWorks) {
+  const Cardinality c = AtMost(5);
+  EXPECT_FALSE(c.IsOverSaturatedByCallCount(4));
+  EXPECT_FALSE(c.IsOverSaturatedByCallCount(5));
+  EXPECT_TRUE(c.IsOverSaturatedByCallCount(6));
+}
+
+// Tests that Cardinality::DescribeActualCallCountTo() creates the
+// correct description.
+TEST(CardinalityTest, CanDescribeActualCallCount) {
+  stringstream ss0;
+  Cardinality::DescribeActualCallCountTo(0, &ss0);
+  EXPECT_EQ("never called", ss0.str());
+
+  stringstream ss1;
+  Cardinality::DescribeActualCallCountTo(1, &ss1);
+  EXPECT_EQ("called once", ss1.str());
+
+  stringstream ss2;
+  Cardinality::DescribeActualCallCountTo(2, &ss2);
+  EXPECT_EQ("called twice", ss2.str());
+
+  stringstream ss3;
+  Cardinality::DescribeActualCallCountTo(3, &ss3);
+  EXPECT_EQ("called 3 times", ss3.str());
+}
+
+// Tests AnyNumber()
+TEST(AnyNumber, Works) {
+  const Cardinality c = AnyNumber();
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(9));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(9));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called any number of times", ss.str());
+}
+
+TEST(AnyNumberTest, HasCorrectBounds) {
+  const Cardinality c = AnyNumber();
+  EXPECT_EQ(0, c.ConservativeLowerBound());
+  EXPECT_EQ(INT_MAX, c.ConservativeUpperBound());
+}
+
+// Tests AtLeast(n).
+
+TEST(AtLeastTest, OnNegativeNumber) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        AtLeast(-1);
+      },
+      "The invocation lower bound must be >= 0");
+}
+
+TEST(AtLeastTest, OnZero) {
+  const Cardinality c = AtLeast(0);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "any number of times", ss.str());
+}
+
+TEST(AtLeastTest, OnPositiveNumber) {
+  const Cardinality c = AtLeast(2);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(2));
+
+  stringstream ss1;
+  AtLeast(1).DescribeTo(&ss1);
+  EXPECT_PRED_FORMAT2(IsSubstring, "at least once", ss1.str());
+
+  stringstream ss2;
+  c.DescribeTo(&ss2);
+  EXPECT_PRED_FORMAT2(IsSubstring, "at least twice", ss2.str());
+
+  stringstream ss3;
+  AtLeast(3).DescribeTo(&ss3);
+  EXPECT_PRED_FORMAT2(IsSubstring, "at least 3 times", ss3.str());
+}
+
+TEST(AtLeastTest, HasCorrectBounds) {
+  const Cardinality c = AtLeast(2);
+  EXPECT_EQ(2, c.ConservativeLowerBound());
+  EXPECT_EQ(INT_MAX, c.ConservativeUpperBound());
+}
+
+// Tests AtMost(n).
+
+TEST(AtMostTest, OnNegativeNumber) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        AtMost(-1);
+      },
+      "The invocation upper bound must be >= 0");
+}
+
+TEST(AtMostTest, OnZero) {
+  const Cardinality c = AtMost(0);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "never called", ss.str());
+}
+
+TEST(AtMostTest, OnPositiveNumber) {
+  const Cardinality c = AtMost(2);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+
+  stringstream ss1;
+  AtMost(1).DescribeTo(&ss1);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most once", ss1.str());
+
+  stringstream ss2;
+  c.DescribeTo(&ss2);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most twice", ss2.str());
+
+  stringstream ss3;
+  AtMost(3).DescribeTo(&ss3);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most 3 times", ss3.str());
+}
+
+TEST(AtMostTest, HasCorrectBounds) {
+  const Cardinality c = AtMost(2);
+  EXPECT_EQ(0, c.ConservativeLowerBound());
+  EXPECT_EQ(2, c.ConservativeUpperBound());
+}
+
+// Tests Between(m, n).
+
+TEST(BetweenTest, OnNegativeStart) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        Between(-1, 2);
+      },
+      "The invocation lower bound must be >= 0, but is actually -1");
+}
+
+TEST(BetweenTest, OnNegativeEnd) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        Between(1, -2);
+      },
+      "The invocation upper bound must be >= 0, but is actually -2");
+}
+
+TEST(BetweenTest, OnStartBiggerThanEnd) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        Between(2, 1);
+      },
+      "The invocation upper bound (1) must be >= "
+      "the invocation lower bound (2)");
+}
+
+TEST(BetweenTest, OnZeroStartAndZeroEnd) {
+  const Cardinality c = Between(0, 0);
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "never called", ss.str());
+}
+
+TEST(BetweenTest, OnZeroStartAndNonZeroEnd) {
+  const Cardinality c = Between(0, 2);
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(4));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(4));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most twice", ss.str());
+}
+
+TEST(BetweenTest, OnSameStartAndEnd) {
+  const Cardinality c = Between(3, 3);
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(2));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(3));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(3));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(4));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(4));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called 3 times", ss.str());
+}
+
+TEST(BetweenTest, OnDifferentStartAndEnd) {
+  const Cardinality c = Between(3, 5);
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(2));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(3));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(3));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(5));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(5));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(6));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(6));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called between 3 and 5 times", ss.str());
+}
+
+TEST(BetweenTest, HasCorrectBounds) {
+  const Cardinality c = Between(3, 5);
+  EXPECT_EQ(3, c.ConservativeLowerBound());
+  EXPECT_EQ(5, c.ConservativeUpperBound());
+}
+
+// Tests Exactly(n).
+
+TEST(ExactlyTest, OnNegativeNumber) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        Exactly(-1);
+      },
+      "The invocation lower bound must be >= 0");
+}
+
+TEST(ExactlyTest, OnZero) {
+  const Cardinality c = Exactly(0);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "never called", ss.str());
+}
+
+TEST(ExactlyTest, OnPositiveNumber) {
+  const Cardinality c = Exactly(2);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+
+  stringstream ss1;
+  Exactly(1).DescribeTo(&ss1);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called once", ss1.str());
+
+  stringstream ss2;
+  c.DescribeTo(&ss2);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called twice", ss2.str());
+
+  stringstream ss3;
+  Exactly(3).DescribeTo(&ss3);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called 3 times", ss3.str());
+}
+
+TEST(ExactlyTest, HasCorrectBounds) {
+  const Cardinality c = Exactly(3);
+  EXPECT_EQ(3, c.ConservativeLowerBound());
+  EXPECT_EQ(3, c.ConservativeUpperBound());
+}
+
+// Tests that a user can make their own cardinality by implementing
+// CardinalityInterface and calling MakeCardinality().
+
+class EvenCardinality : public CardinalityInterface {
+ public:
+  // Returns true if and only if call_count calls will satisfy this
+  // cardinality.
+  bool IsSatisfiedByCallCount(int call_count) const override {
+    return (call_count % 2 == 0);
+  }
+
+  // Returns true if and only if call_count calls will saturate this
+  // cardinality.
+  bool IsSaturatedByCallCount(int /* call_count */) const override {
+    return false;
+  }
+
+  // Describes self to an ostream.
+  void DescribeTo(::std::ostream* ss) const override {
+    *ss << "called even number of times";
+  }
+};
+
+TEST(MakeCardinalityTest, ConstructsCardinalityFromInterface) {
+  const Cardinality c = MakeCardinality(new EvenCardinality);
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(3));
+
+  EXPECT_FALSE(c.IsSaturatedByCallCount(10000));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_EQ("called even number of times", ss.str());
+}
+
+}  // Unnamed namespace
diff --git a/3rd-party/googletest/googlemock/test/gmock-function-mocker_test.cc b/3rd-party/googletest/googlemock/test/gmock-function-mocker_test.cc
new file mode 100644
index 0000000..f7b31ae
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-function-mocker_test.cc
@@ -0,0 +1,998 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the function mocker classes.
+#include "gmock/gmock-function-mocker.h"
+
+// Silence C4503 (decorated name length exceeded) for MSVC.
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4503)
+
+#ifdef GTEST_OS_WINDOWS
+// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
+// we are getting compiler errors if we use basetyps.h, hence including
+// objbase.h for definition of STDMETHOD.
+#include <objbase.h>
+#endif  // GTEST_OS_WINDOWS
+
+#include <functional>
+#include <map>
+#include <string>
+#include <type_traits>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace gmock_function_mocker_test {
+
+using testing::_;
+using testing::A;
+using testing::An;
+using testing::AnyNumber;
+using testing::Const;
+using testing::DoDefault;
+using testing::Eq;
+using testing::Lt;
+using testing::MockFunction;
+using testing::Ref;
+using testing::Return;
+using testing::ReturnRef;
+using testing::TypedEq;
+
+template <typename T>
+class TemplatedCopyable {
+ public:
+  TemplatedCopyable() = default;
+
+  template <typename U>
+  TemplatedCopyable(const U& other) {}  // NOLINT
+};
+
+class FooInterface {
+ public:
+  virtual ~FooInterface() = default;
+
+  virtual void VoidReturning(int x) = 0;
+
+  virtual int Nullary() = 0;
+  virtual bool Unary(int x) = 0;
+  virtual long Binary(short x, int y) = 0;                     // NOLINT
+  virtual int Decimal(bool b, char c, short d, int e, long f,  // NOLINT
+                      float g, double h, unsigned i, char* j,
+                      const std::string& k) = 0;
+
+  virtual bool TakesNonConstReference(int& n) = 0;  // NOLINT
+  virtual std::string TakesConstReference(const int& n) = 0;
+  virtual bool TakesConst(const int x) = 0;
+
+  virtual int OverloadedOnArgumentNumber() = 0;
+  virtual int OverloadedOnArgumentNumber(int n) = 0;
+
+  virtual int OverloadedOnArgumentType(int n) = 0;
+  virtual char OverloadedOnArgumentType(char c) = 0;
+
+  virtual int OverloadedOnConstness() = 0;
+  virtual char OverloadedOnConstness() const = 0;
+
+  virtual int TypeWithHole(int (*func)()) = 0;
+  virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0;
+  virtual int TypeWithTemplatedCopyCtor(const TemplatedCopyable<int>&) = 0;
+
+  virtual int (*ReturnsFunctionPointer1(int))(bool) = 0;
+  using fn_ptr = int (*)(bool);
+  virtual fn_ptr ReturnsFunctionPointer2(int) = 0;
+
+  virtual int RefQualifiedConstRef() const& = 0;
+  virtual int RefQualifiedConstRefRef() const&& = 0;
+  virtual int RefQualifiedRef() & = 0;
+  virtual int RefQualifiedRefRef() && = 0;
+
+  virtual int RefQualifiedOverloaded() const& = 0;
+  virtual int RefQualifiedOverloaded() const&& = 0;
+  virtual int RefQualifiedOverloaded() & = 0;
+  virtual int RefQualifiedOverloaded() && = 0;
+
+#ifdef GTEST_OS_WINDOWS
+  STDMETHOD_(int, CTNullary)() = 0;
+  STDMETHOD_(bool, CTUnary)(int x) = 0;
+  STDMETHOD_(int, CTDecimal)
+  (bool b, char c, short d, int e, long f,  // NOLINT
+   float g, double h, unsigned i, char* j, const std::string& k) = 0;
+  STDMETHOD_(char, CTConst)(int x) const = 0;
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Const qualifiers on arguments were once (incorrectly) considered
+// significant in determining whether two virtual functions had the same
+// signature. This was fixed in Visual Studio 2008. However, the compiler
+// still emits a warning that alerts about this change in behavior.
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4373)
+class MockFoo : public FooInterface {
+ public:
+  MockFoo() = default;
+
+  // Makes sure that a mock function parameter can be named.
+  MOCK_METHOD(void, VoidReturning, (int n));  // NOLINT
+
+  MOCK_METHOD(int, Nullary, ());  // NOLINT
+
+  // Makes sure that a mock function parameter can be unnamed.
+  MOCK_METHOD(bool, Unary, (int));          // NOLINT
+  MOCK_METHOD(long, Binary, (short, int));  // NOLINT
+  MOCK_METHOD(int, Decimal,
+              (bool, char, short, int, long, float,  // NOLINT
+               double, unsigned, char*, const std::string& str),
+              (override));
+
+  MOCK_METHOD(bool, TakesNonConstReference, (int&));  // NOLINT
+  MOCK_METHOD(std::string, TakesConstReference, (const int&));
+  MOCK_METHOD(bool, TakesConst, (const int));  // NOLINT
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD((std::map<int, std::string>), ReturnTypeWithComma, (), ());
+  MOCK_METHOD((std::map<int, std::string>), ReturnTypeWithComma, (int),
+              (const));  // NOLINT
+
+  MOCK_METHOD(int, OverloadedOnArgumentNumber, ());     // NOLINT
+  MOCK_METHOD(int, OverloadedOnArgumentNumber, (int));  // NOLINT
+
+  MOCK_METHOD(int, OverloadedOnArgumentType, (int));    // NOLINT
+  MOCK_METHOD(char, OverloadedOnArgumentType, (char));  // NOLINT
+
+  MOCK_METHOD(int, OverloadedOnConstness, (), (override));          // NOLINT
+  MOCK_METHOD(char, OverloadedOnConstness, (), (override, const));  // NOLINT
+
+  MOCK_METHOD(int, TypeWithHole, (int (*)()), ());  // NOLINT
+  MOCK_METHOD(int, TypeWithComma, ((const std::map<int, std::string>&)));
+  MOCK_METHOD(int, TypeWithTemplatedCopyCtor,
+              (const TemplatedCopyable<int>&));  // NOLINT
+
+  MOCK_METHOD(int (*)(bool), ReturnsFunctionPointer1, (int), ());
+  MOCK_METHOD(fn_ptr, ReturnsFunctionPointer2, (int), ());
+
+#ifdef GTEST_OS_WINDOWS
+  MOCK_METHOD(int, CTNullary, (), (Calltype(STDMETHODCALLTYPE)));
+  MOCK_METHOD(bool, CTUnary, (int), (Calltype(STDMETHODCALLTYPE)));
+  MOCK_METHOD(int, CTDecimal,
+              (bool b, char c, short d, int e, long f, float g, double h,
+               unsigned i, char* j, const std::string& k),
+              (Calltype(STDMETHODCALLTYPE)));
+  MOCK_METHOD(char, CTConst, (int), (const, Calltype(STDMETHODCALLTYPE)));
+  MOCK_METHOD((std::map<int, std::string>), CTReturnTypeWithComma, (),
+              (Calltype(STDMETHODCALLTYPE)));
+#endif  // GTEST_OS_WINDOWS
+
+  // Test reference qualified functions.
+  MOCK_METHOD(int, RefQualifiedConstRef, (), (const, ref(&), override));
+  MOCK_METHOD(int, RefQualifiedConstRefRef, (), (const, ref(&&), override));
+  MOCK_METHOD(int, RefQualifiedRef, (), (ref(&), override));
+  MOCK_METHOD(int, RefQualifiedRefRef, (), (ref(&&), override));
+
+  MOCK_METHOD(int, RefQualifiedOverloaded, (), (const, ref(&), override));
+  MOCK_METHOD(int, RefQualifiedOverloaded, (), (const, ref(&&), override));
+  MOCK_METHOD(int, RefQualifiedOverloaded, (), (ref(&), override));
+  MOCK_METHOD(int, RefQualifiedOverloaded, (), (ref(&&), override));
+
+ private:
+  MockFoo(const MockFoo&) = delete;
+  MockFoo& operator=(const MockFoo&) = delete;
+};
+
+class LegacyMockFoo : public FooInterface {
+ public:
+  LegacyMockFoo() = default;
+
+  // Makes sure that a mock function parameter can be named.
+  MOCK_METHOD1(VoidReturning, void(int n));  // NOLINT
+
+  MOCK_METHOD0(Nullary, int());  // NOLINT
+
+  // Makes sure that a mock function parameter can be unnamed.
+  MOCK_METHOD1(Unary, bool(int));                                  // NOLINT
+  MOCK_METHOD2(Binary, long(short, int));                          // NOLINT
+  MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float,  // NOLINT
+                             double, unsigned, char*, const std::string& str));
+
+  MOCK_METHOD1(TakesNonConstReference, bool(int&));  // NOLINT
+  MOCK_METHOD1(TakesConstReference, std::string(const int&));
+  MOCK_METHOD1(TakesConst, bool(const int));  // NOLINT
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>());
+  MOCK_CONST_METHOD1(ReturnTypeWithComma,
+                     std::map<int, std::string>(int));  // NOLINT
+
+  MOCK_METHOD0(OverloadedOnArgumentNumber, int());     // NOLINT
+  MOCK_METHOD1(OverloadedOnArgumentNumber, int(int));  // NOLINT
+
+  MOCK_METHOD1(OverloadedOnArgumentType, int(int));    // NOLINT
+  MOCK_METHOD1(OverloadedOnArgumentType, char(char));  // NOLINT
+
+  MOCK_METHOD0(OverloadedOnConstness, int());         // NOLINT
+  MOCK_CONST_METHOD0(OverloadedOnConstness, char());  // NOLINT
+
+  MOCK_METHOD1(TypeWithHole, int(int (*)()));  // NOLINT
+  MOCK_METHOD1(TypeWithComma,
+               int(const std::map<int, std::string>&));  // NOLINT
+  MOCK_METHOD1(TypeWithTemplatedCopyCtor,
+               int(const TemplatedCopyable<int>&));  // NOLINT
+
+  MOCK_METHOD1(ReturnsFunctionPointer1, int (*(int))(bool));
+  MOCK_METHOD1(ReturnsFunctionPointer2, fn_ptr(int));
+
+#ifdef GTEST_OS_WINDOWS
+  MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int());
+  MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int));  // NOLINT
+  MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal,
+                              int(bool b, char c, short d, int e,  // NOLINT
+                                  long f, float g, double h,       // NOLINT
+                                  unsigned i, char* j, const std::string& k));
+  MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst,
+                                   char(int));  // NOLINT
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma,
+                             std::map<int, std::string>());
+#endif  // GTEST_OS_WINDOWS
+
+  // We can't mock these with the old macros, but we need to define them to make
+  // it concrete.
+  int RefQualifiedConstRef() const& override { return 0; }
+  int RefQualifiedConstRefRef() const&& override { return 0; }
+  int RefQualifiedRef() & override { return 0; }
+  int RefQualifiedRefRef() && override { return 0; }
+  int RefQualifiedOverloaded() const& override { return 0; }
+  int RefQualifiedOverloaded() const&& override { return 0; }
+  int RefQualifiedOverloaded() & override { return 0; }
+  int RefQualifiedOverloaded() && override { return 0; }
+
+ private:
+  LegacyMockFoo(const LegacyMockFoo&) = delete;
+  LegacyMockFoo& operator=(const LegacyMockFoo&) = delete;
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4373
+
+template <class T>
+class FunctionMockerTest : public testing::Test {
+ protected:
+  FunctionMockerTest() : foo_(&mock_foo_) {}
+
+  FooInterface* const foo_;
+  T mock_foo_;
+};
+using FunctionMockerTestTypes = ::testing::Types<MockFoo, LegacyMockFoo>;
+TYPED_TEST_SUITE(FunctionMockerTest, FunctionMockerTestTypes);
+
+// Tests mocking a void-returning function.
+TYPED_TEST(FunctionMockerTest, MocksVoidFunction) {
+  EXPECT_CALL(this->mock_foo_, VoidReturning(Lt(100)));
+  this->foo_->VoidReturning(0);
+}
+
+// Tests mocking a nullary function.
+TYPED_TEST(FunctionMockerTest, MocksNullaryFunction) {
+  EXPECT_CALL(this->mock_foo_, Nullary())
+      .WillOnce(DoDefault())
+      .WillOnce(Return(1));
+
+  EXPECT_EQ(0, this->foo_->Nullary());
+  EXPECT_EQ(1, this->foo_->Nullary());
+}
+
+// Tests mocking a unary function.
+TYPED_TEST(FunctionMockerTest, MocksUnaryFunction) {
+  EXPECT_CALL(this->mock_foo_, Unary(Eq(2))).Times(2).WillOnce(Return(true));
+
+  EXPECT_TRUE(this->foo_->Unary(2));
+  EXPECT_FALSE(this->foo_->Unary(2));
+}
+
+// Tests mocking a binary function.
+TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) {
+  EXPECT_CALL(this->mock_foo_, Binary(2, _)).WillOnce(Return(3));
+
+  EXPECT_EQ(3, this->foo_->Binary(2, 1));
+}
+
+// Tests mocking a decimal function.
+TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
+  EXPECT_CALL(this->mock_foo_,
+              Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi"))
+      .WillOnce(Return(5));
+
+  EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
+}
+
+// Tests mocking a function that takes a non-const reference.
+TYPED_TEST(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) {
+  int a = 0;
+  EXPECT_CALL(this->mock_foo_, TakesNonConstReference(Ref(a)))
+      .WillOnce(Return(true));
+
+  EXPECT_TRUE(this->foo_->TakesNonConstReference(a));
+}
+
+// Tests mocking a function that takes a const reference.
+TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
+  int a = 0;
+  EXPECT_CALL(this->mock_foo_, TakesConstReference(Ref(a)))
+      .WillOnce(Return("Hello"));
+
+  EXPECT_EQ("Hello", this->foo_->TakesConstReference(a));
+}
+
+// Tests mocking a function that takes a const variable.
+TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstArgument) {
+  EXPECT_CALL(this->mock_foo_, TakesConst(Lt(10))).WillOnce(DoDefault());
+
+  EXPECT_FALSE(this->foo_->TakesConst(5));
+}
+
+// Tests mocking functions overloaded on the number of arguments.
+TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
+  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber())
+      .WillOnce(Return(1));
+  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber(_))
+      .WillOnce(Return(2));
+
+  EXPECT_EQ(2, this->foo_->OverloadedOnArgumentNumber(1));
+  EXPECT_EQ(1, this->foo_->OverloadedOnArgumentNumber());
+}
+
+// Tests mocking functions overloaded on the types of argument.
+TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
+  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(An<int>()))
+      .WillOnce(Return(1));
+  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
+      .WillOnce(Return('b'));
+
+  EXPECT_EQ(1, this->foo_->OverloadedOnArgumentType(0));
+  EXPECT_EQ('b', this->foo_->OverloadedOnArgumentType('a'));
+}
+
+// Tests mocking functions overloaded on the const-ness of this object.
+TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) {
+  EXPECT_CALL(this->mock_foo_, OverloadedOnConstness());
+  EXPECT_CALL(Const(this->mock_foo_), OverloadedOnConstness())
+      .WillOnce(Return('a'));
+
+  EXPECT_EQ(0, this->foo_->OverloadedOnConstness());
+  EXPECT_EQ('a', Const(*this->foo_).OverloadedOnConstness());
+}
+
+TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithComma) {
+  const std::map<int, std::string> a_map;
+  EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma()).WillOnce(Return(a_map));
+  EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma(42)).WillOnce(Return(a_map));
+
+  EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma());
+  EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma(42));
+}
+
+TYPED_TEST(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
+  EXPECT_CALL(this->mock_foo_, TypeWithTemplatedCopyCtor(_))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(this->foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
+}
+
+#ifdef GTEST_OS_WINDOWS
+// Tests mocking a nullary function with calltype.
+TYPED_TEST(FunctionMockerTest, MocksNullaryFunctionWithCallType) {
+  EXPECT_CALL(this->mock_foo_, CTNullary())
+      .WillOnce(Return(-1))
+      .WillOnce(Return(0));
+
+  EXPECT_EQ(-1, this->foo_->CTNullary());
+  EXPECT_EQ(0, this->foo_->CTNullary());
+}
+
+// Tests mocking a unary function with calltype.
+TYPED_TEST(FunctionMockerTest, MocksUnaryFunctionWithCallType) {
+  EXPECT_CALL(this->mock_foo_, CTUnary(Eq(2)))
+      .Times(2)
+      .WillOnce(Return(true))
+      .WillOnce(Return(false));
+
+  EXPECT_TRUE(this->foo_->CTUnary(2));
+  EXPECT_FALSE(this->foo_->CTUnary(2));
+}
+
+// Tests mocking a decimal function with calltype.
+TYPED_TEST(FunctionMockerTest, MocksDecimalFunctionWithCallType) {
+  EXPECT_CALL(this->mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(),
+                                         Lt(100), 5U, NULL, "hi"))
+      .WillOnce(Return(10));
+
+  EXPECT_EQ(10, this->foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
+}
+
+// Tests mocking functions overloaded on the const-ness of this object.
+TYPED_TEST(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
+  EXPECT_CALL(Const(this->mock_foo_), CTConst(_)).WillOnce(Return('a'));
+
+  EXPECT_EQ('a', Const(*this->foo_).CTConst(0));
+}
+
+TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
+  const std::map<int, std::string> a_map;
+  EXPECT_CALL(this->mock_foo_, CTReturnTypeWithComma()).WillOnce(Return(a_map));
+
+  EXPECT_EQ(a_map, this->mock_foo_.CTReturnTypeWithComma());
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+TEST(FunctionMockerTest, RefQualified) {
+  MockFoo mock_foo;
+
+  EXPECT_CALL(mock_foo, RefQualifiedConstRef).WillOnce(Return(1));
+  EXPECT_CALL(std::move(mock_foo),  // NOLINT
+              RefQualifiedConstRefRef)
+      .WillOnce(Return(2));
+  EXPECT_CALL(mock_foo, RefQualifiedRef).WillOnce(Return(3));
+  EXPECT_CALL(std::move(mock_foo),  // NOLINT
+              RefQualifiedRefRef)
+      .WillOnce(Return(4));
+
+  EXPECT_CALL(static_cast<const MockFoo&>(mock_foo), RefQualifiedOverloaded())
+      .WillOnce(Return(5));
+  EXPECT_CALL(static_cast<const MockFoo&&>(mock_foo), RefQualifiedOverloaded())
+      .WillOnce(Return(6));
+  EXPECT_CALL(static_cast<MockFoo&>(mock_foo), RefQualifiedOverloaded())
+      .WillOnce(Return(7));
+  EXPECT_CALL(static_cast<MockFoo&&>(mock_foo), RefQualifiedOverloaded())
+      .WillOnce(Return(8));
+
+  EXPECT_EQ(mock_foo.RefQualifiedConstRef(), 1);
+  EXPECT_EQ(std::move(mock_foo).RefQualifiedConstRefRef(), 2);  // NOLINT
+  EXPECT_EQ(mock_foo.RefQualifiedRef(), 3);
+  EXPECT_EQ(std::move(mock_foo).RefQualifiedRefRef(), 4);  // NOLINT
+
+  EXPECT_EQ(std::cref(mock_foo).get().RefQualifiedOverloaded(), 5);
+  EXPECT_EQ(std::move(std::cref(mock_foo).get())  // NOLINT
+                .RefQualifiedOverloaded(),
+            6);
+  EXPECT_EQ(mock_foo.RefQualifiedOverloaded(), 7);
+  EXPECT_EQ(std::move(mock_foo).RefQualifiedOverloaded(), 8);  // NOLINT
+}
+
+class MockB {
+ public:
+  MockB() = default;
+
+  MOCK_METHOD(void, DoB, ());
+
+ private:
+  MockB(const MockB&) = delete;
+  MockB& operator=(const MockB&) = delete;
+};
+
+class LegacyMockB {
+ public:
+  LegacyMockB() = default;
+
+  MOCK_METHOD0(DoB, void());
+
+ private:
+  LegacyMockB(const LegacyMockB&) = delete;
+  LegacyMockB& operator=(const LegacyMockB&) = delete;
+};
+
+template <typename T>
+class ExpectCallTest : public ::testing::Test {};
+using ExpectCallTestTypes = ::testing::Types<MockB, LegacyMockB>;
+TYPED_TEST_SUITE(ExpectCallTest, ExpectCallTestTypes);
+
+// Tests that functions with no EXPECT_CALL() rules can be called any
+// number of times.
+TYPED_TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
+  { TypeParam b; }
+
+  {
+    TypeParam b;
+    b.DoB();
+  }
+
+  {
+    TypeParam b;
+    b.DoB();
+    b.DoB();
+  }
+}
+
+// Tests mocking template interfaces.
+
+template <typename T>
+class StackInterface {
+ public:
+  virtual ~StackInterface() = default;
+
+  // Template parameter appears in function parameter.
+  virtual void Push(const T& value) = 0;
+  virtual void Pop() = 0;
+  virtual int GetSize() const = 0;
+  // Template parameter appears in function return type.
+  virtual const T& GetTop() const = 0;
+};
+
+template <typename T>
+class MockStack : public StackInterface<T> {
+ public:
+  MockStack() = default;
+
+  MOCK_METHOD(void, Push, (const T& elem), ());
+  MOCK_METHOD(void, Pop, (), (final));
+  MOCK_METHOD(int, GetSize, (), (const, override));
+  MOCK_METHOD(const T&, GetTop, (), (const));
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD((std::map<int, int>), ReturnTypeWithComma, (), ());
+  MOCK_METHOD((std::map<int, int>), ReturnTypeWithComma, (int), (const));
+
+ private:
+  MockStack(const MockStack&) = delete;
+  MockStack& operator=(const MockStack&) = delete;
+};
+
+template <typename T>
+class LegacyMockStack : public StackInterface<T> {
+ public:
+  LegacyMockStack() = default;
+
+  MOCK_METHOD1_T(Push, void(const T& elem));
+  MOCK_METHOD0_T(Pop, void());
+  MOCK_CONST_METHOD0_T(GetSize, int());  // NOLINT
+  MOCK_CONST_METHOD0_T(GetTop, const T&());
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>());
+  MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int));  // NOLINT
+
+ private:
+  LegacyMockStack(const LegacyMockStack&) = delete;
+  LegacyMockStack& operator=(const LegacyMockStack&) = delete;
+};
+
+template <typename T>
+class TemplateMockTest : public ::testing::Test {};
+using TemplateMockTestTypes =
+    ::testing::Types<MockStack<int>, LegacyMockStack<int>>;
+TYPED_TEST_SUITE(TemplateMockTest, TemplateMockTestTypes);
+
+// Tests that template mock works.
+TYPED_TEST(TemplateMockTest, Works) {
+  TypeParam mock;
+
+  EXPECT_CALL(mock, GetSize())
+      .WillOnce(Return(0))
+      .WillOnce(Return(1))
+      .WillOnce(Return(0));
+  EXPECT_CALL(mock, Push(_));
+  int n = 5;
+  EXPECT_CALL(mock, GetTop()).WillOnce(ReturnRef(n));
+  EXPECT_CALL(mock, Pop()).Times(AnyNumber());
+
+  EXPECT_EQ(0, mock.GetSize());
+  mock.Push(5);
+  EXPECT_EQ(1, mock.GetSize());
+  EXPECT_EQ(5, mock.GetTop());
+  mock.Pop();
+  EXPECT_EQ(0, mock.GetSize());
+}
+
+TYPED_TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) {
+  TypeParam mock;
+
+  const std::map<int, int> a_map;
+  EXPECT_CALL(mock, ReturnTypeWithComma()).WillOnce(Return(a_map));
+  EXPECT_CALL(mock, ReturnTypeWithComma(1)).WillOnce(Return(a_map));
+
+  EXPECT_EQ(a_map, mock.ReturnTypeWithComma());
+  EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1));
+}
+
+#ifdef GTEST_OS_WINDOWS
+// Tests mocking template interfaces with calltype.
+
+template <typename T>
+class StackInterfaceWithCallType {
+ public:
+  virtual ~StackInterfaceWithCallType() {}
+
+  // Template parameter appears in function parameter.
+  STDMETHOD_(void, Push)(const T& value) = 0;
+  STDMETHOD_(void, Pop)() = 0;
+  STDMETHOD_(int, GetSize)() const = 0;
+  // Template parameter appears in function return type.
+  STDMETHOD_(const T&, GetTop)() const = 0;
+};
+
+template <typename T>
+class MockStackWithCallType : public StackInterfaceWithCallType<T> {
+ public:
+  MockStackWithCallType() {}
+
+  MOCK_METHOD(void, Push, (const T& elem),
+              (Calltype(STDMETHODCALLTYPE), override));
+  MOCK_METHOD(void, Pop, (), (Calltype(STDMETHODCALLTYPE), override));
+  MOCK_METHOD(int, GetSize, (), (Calltype(STDMETHODCALLTYPE), override, const));
+  MOCK_METHOD(const T&, GetTop, (),
+              (Calltype(STDMETHODCALLTYPE), override, const));
+
+ private:
+  MockStackWithCallType(const MockStackWithCallType&) = delete;
+  MockStackWithCallType& operator=(const MockStackWithCallType&) = delete;
+};
+
+template <typename T>
+class LegacyMockStackWithCallType : public StackInterfaceWithCallType<T> {
+ public:
+  LegacyMockStackWithCallType() {}
+
+  MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem));
+  MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void());
+  MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int());
+  MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&());
+
+ private:
+  LegacyMockStackWithCallType(const LegacyMockStackWithCallType&) = delete;
+  LegacyMockStackWithCallType& operator=(const LegacyMockStackWithCallType&) =
+      delete;
+};
+
+template <typename T>
+class TemplateMockTestWithCallType : public ::testing::Test {};
+using TemplateMockTestWithCallTypeTypes =
+    ::testing::Types<MockStackWithCallType<int>,
+                     LegacyMockStackWithCallType<int>>;
+TYPED_TEST_SUITE(TemplateMockTestWithCallType,
+                 TemplateMockTestWithCallTypeTypes);
+
+// Tests that template mock with calltype works.
+TYPED_TEST(TemplateMockTestWithCallType, Works) {
+  TypeParam mock;
+
+  EXPECT_CALL(mock, GetSize())
+      .WillOnce(Return(0))
+      .WillOnce(Return(1))
+      .WillOnce(Return(0));
+  EXPECT_CALL(mock, Push(_));
+  int n = 5;
+  EXPECT_CALL(mock, GetTop()).WillOnce(ReturnRef(n));
+  EXPECT_CALL(mock, Pop()).Times(AnyNumber());
+
+  EXPECT_EQ(0, mock.GetSize());
+  mock.Push(5);
+  EXPECT_EQ(1, mock.GetSize());
+  EXPECT_EQ(5, mock.GetTop());
+  mock.Pop();
+  EXPECT_EQ(0, mock.GetSize());
+}
+#endif  // GTEST_OS_WINDOWS
+
+#define MY_MOCK_METHODS1_                       \
+  MOCK_METHOD(void, Overloaded, ());            \
+  MOCK_METHOD(int, Overloaded, (int), (const)); \
+  MOCK_METHOD(bool, Overloaded, (bool f, int n))
+
+#define LEGACY_MY_MOCK_METHODS1_              \
+  MOCK_METHOD0(Overloaded, void());           \
+  MOCK_CONST_METHOD1(Overloaded, int(int n)); \
+  MOCK_METHOD2(Overloaded, bool(bool f, int n))
+
+class MockOverloadedOnArgNumber {
+ public:
+  MockOverloadedOnArgNumber() = default;
+
+  MY_MOCK_METHODS1_;
+
+ private:
+  MockOverloadedOnArgNumber(const MockOverloadedOnArgNumber&) = delete;
+  MockOverloadedOnArgNumber& operator=(const MockOverloadedOnArgNumber&) =
+      delete;
+};
+
+class LegacyMockOverloadedOnArgNumber {
+ public:
+  LegacyMockOverloadedOnArgNumber() = default;
+
+  LEGACY_MY_MOCK_METHODS1_;
+
+ private:
+  LegacyMockOverloadedOnArgNumber(const LegacyMockOverloadedOnArgNumber&) =
+      delete;
+  LegacyMockOverloadedOnArgNumber& operator=(
+      const LegacyMockOverloadedOnArgNumber&) = delete;
+};
+
+template <typename T>
+class OverloadedMockMethodTest : public ::testing::Test {};
+using OverloadedMockMethodTestTypes =
+    ::testing::Types<MockOverloadedOnArgNumber,
+                     LegacyMockOverloadedOnArgNumber>;
+TYPED_TEST_SUITE(OverloadedMockMethodTest, OverloadedMockMethodTestTypes);
+
+TYPED_TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
+  TypeParam mock;
+  EXPECT_CALL(mock, Overloaded());
+  EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
+  EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));
+
+  mock.Overloaded();
+  EXPECT_EQ(2, mock.Overloaded(1));
+  EXPECT_TRUE(mock.Overloaded(true, 1));
+}
+
+#define MY_MOCK_METHODS2_                     \
+  MOCK_CONST_METHOD1(Overloaded, int(int n)); \
+  MOCK_METHOD1(Overloaded, int(int n))
+
+class MockOverloadedOnConstness {
+ public:
+  MockOverloadedOnConstness() = default;
+
+  MY_MOCK_METHODS2_;
+
+ private:
+  MockOverloadedOnConstness(const MockOverloadedOnConstness&) = delete;
+  MockOverloadedOnConstness& operator=(const MockOverloadedOnConstness&) =
+      delete;
+};
+
+TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) {
+  MockOverloadedOnConstness mock;
+  const MockOverloadedOnConstness* const_mock = &mock;
+  EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
+  EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3));
+
+  EXPECT_EQ(2, mock.Overloaded(1));
+  EXPECT_EQ(3, const_mock->Overloaded(1));
+}
+
+TEST(MockMethodMockFunctionTest, WorksForVoidNullary) {
+  MockFunction<void()> foo;
+  EXPECT_CALL(foo, Call());
+  foo.Call();
+}
+
+TEST(MockMethodMockFunctionTest, WorksForNonVoidNullary) {
+  MockFunction<int()> foo;
+  EXPECT_CALL(foo, Call()).WillOnce(Return(1)).WillOnce(Return(2));
+  EXPECT_EQ(1, foo.Call());
+  EXPECT_EQ(2, foo.Call());
+}
+
+TEST(MockMethodMockFunctionTest, WorksForVoidUnary) {
+  MockFunction<void(int)> foo;
+  EXPECT_CALL(foo, Call(1));
+  foo.Call(1);
+}
+
+TEST(MockMethodMockFunctionTest, WorksForNonVoidBinary) {
+  MockFunction<int(bool, int)> foo;
+  EXPECT_CALL(foo, Call(false, 42)).WillOnce(Return(1)).WillOnce(Return(2));
+  EXPECT_CALL(foo, Call(true, Ge(100))).WillOnce(Return(3));
+  EXPECT_EQ(1, foo.Call(false, 42));
+  EXPECT_EQ(2, foo.Call(false, 42));
+  EXPECT_EQ(3, foo.Call(true, 120));
+}
+
+TEST(MockMethodMockFunctionTest, WorksFor10Arguments) {
+  MockFunction<int(bool a0, char a1, int a2, int a3, int a4, int a5, int a6,
+                   char a7, int a8, bool a9)>
+      foo;
+  EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _))
+      .WillOnce(Return(1))
+      .WillOnce(Return(2));
+  EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true));
+  EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false));
+}
+
+TEST(MockMethodMockFunctionTest, AsStdFunction) {
+  MockFunction<int(int)> foo;
+  auto call = [](const std::function<int(int)>& f, int i) { return f(i); };
+  EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1));
+  EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2));
+  EXPECT_EQ(-1, call(foo.AsStdFunction(), 1));
+  EXPECT_EQ(-2, call(foo.AsStdFunction(), 2));
+}
+
+TEST(MockMethodMockFunctionTest, AsStdFunctionReturnsReference) {
+  MockFunction<int&()> foo;
+  int value = 1;
+  EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value));
+  int& ref = foo.AsStdFunction()();
+  EXPECT_EQ(1, ref);
+  value = 2;
+  EXPECT_EQ(2, ref);
+}
+
+TEST(MockMethodMockFunctionTest, AsStdFunctionWithReferenceParameter) {
+  MockFunction<int(int&)> foo;
+  auto call = [](const std::function<int(int&)>& f, int& i) { return f(i); };
+  int i = 42;
+  EXPECT_CALL(foo, Call(i)).WillOnce(Return(-1));
+  EXPECT_EQ(-1, call(foo.AsStdFunction(), i));
+}
+
+namespace {
+
+template <typename Expected, typename F>
+static constexpr bool IsMockFunctionTemplateArgumentDeducedTo(
+    const internal::MockFunction<F>&) {
+  return std::is_same<F, Expected>::value;
+}
+
+}  // namespace
+
+template <typename F>
+class MockMethodMockFunctionSignatureTest : public Test {};
+
+using MockMethodMockFunctionSignatureTypes =
+    Types<void(), int(), void(int), int(int), int(bool, int),
+          int(bool, char, int, int, int, int, int, char, int, bool)>;
+TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest,
+                 MockMethodMockFunctionSignatureTypes);
+
+TYPED_TEST(MockMethodMockFunctionSignatureTest,
+           IsMockFunctionTemplateArgumentDeducedForRawSignature) {
+  using Argument = TypeParam;
+  MockFunction<Argument> foo;
+  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
+}
+
+TYPED_TEST(MockMethodMockFunctionSignatureTest,
+           IsMockFunctionTemplateArgumentDeducedForStdFunction) {
+  using Argument = std::function<TypeParam>;
+  MockFunction<Argument> foo;
+  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
+}
+
+TYPED_TEST(
+    MockMethodMockFunctionSignatureTest,
+    IsMockFunctionCallMethodSignatureTheSameForRawSignatureAndStdFunction) {
+  using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
+  using ForStdFunction =
+      decltype(&MockFunction<std::function<TypeParam>>::Call);
+  EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
+}
+
+template <typename F>
+struct AlternateCallable {};
+
+TYPED_TEST(MockMethodMockFunctionSignatureTest,
+           IsMockFunctionTemplateArgumentDeducedForAlternateCallable) {
+  using Argument = AlternateCallable<TypeParam>;
+  MockFunction<Argument> foo;
+  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
+}
+
+TYPED_TEST(MockMethodMockFunctionSignatureTest,
+           IsMockFunctionCallMethodSignatureTheSameForAlternateCallable) {
+  using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
+  using ForStdFunction =
+      decltype(&MockFunction<std::function<TypeParam>>::Call);
+  EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
+}
+
+struct MockMethodSizes0 {
+  MOCK_METHOD(void, func, ());
+};
+struct MockMethodSizes1 {
+  MOCK_METHOD(void, func, (int));
+};
+struct MockMethodSizes2 {
+  MOCK_METHOD(void, func, (int, int));
+};
+struct MockMethodSizes3 {
+  MOCK_METHOD(void, func, (int, int, int));
+};
+struct MockMethodSizes4 {
+  MOCK_METHOD(void, func, (int, int, int, int));
+};
+
+struct LegacyMockMethodSizes0 {
+  MOCK_METHOD0(func, void());
+};
+struct LegacyMockMethodSizes1 {
+  MOCK_METHOD1(func, void(int));
+};
+struct LegacyMockMethodSizes2 {
+  MOCK_METHOD2(func, void(int, int));
+};
+struct LegacyMockMethodSizes3 {
+  MOCK_METHOD3(func, void(int, int, int));
+};
+struct LegacyMockMethodSizes4 {
+  MOCK_METHOD4(func, void(int, int, int, int));
+};
+
+TEST(MockMethodMockFunctionTest, MockMethodSizeOverhead) {
+  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1));
+  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2));
+  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3));
+  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4));
+
+  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes1));
+  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes2));
+  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes3));
+  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes4));
+
+  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(MockMethodSizes0));
+}
+
+TEST(MockMethodMockFunctionTest, EnsureNoUnusedMemberFunction) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wunused-member-function"
+#endif
+  // https://github.com/google/googletest/issues/4052
+  struct Foo {
+    MOCK_METHOD(void, foo, ());
+  };
+  EXPECT_CALL(Foo(), foo()).Times(0);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+}
+
+void hasTwoParams(int, int);
+void MaybeThrows();
+void DoesntThrow() noexcept;
+struct MockMethodNoexceptSpecifier {
+  MOCK_METHOD(void, func1, (), (noexcept));
+  MOCK_METHOD(void, func2, (), (noexcept(true)));
+  MOCK_METHOD(void, func3, (), (noexcept(false)));
+  MOCK_METHOD(void, func4, (), (noexcept(noexcept(MaybeThrows()))));
+  MOCK_METHOD(void, func5, (), (noexcept(noexcept(DoesntThrow()))));
+  MOCK_METHOD(void, func6, (), (noexcept(noexcept(DoesntThrow())), const));
+  MOCK_METHOD(void, func7, (), (const, noexcept(noexcept(DoesntThrow()))));
+  // Put commas in the noexcept expression
+  MOCK_METHOD(void, func8, (), (noexcept(noexcept(hasTwoParams(1, 2))), const));
+};
+
+TEST(MockMethodMockFunctionTest, NoexceptSpecifierPreserved) {
+  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func1()));
+  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func2()));
+  EXPECT_FALSE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func3()));
+  EXPECT_FALSE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func4()));
+  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func5()));
+  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func6()));
+  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func7()));
+  EXPECT_EQ(noexcept(std::declval<MockMethodNoexceptSpecifier>().func8()),
+            noexcept(hasTwoParams(1, 2)));
+}
+
+}  // namespace gmock_function_mocker_test
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4503
diff --git a/3rd-party/googletest/googlemock/test/gmock-internal-utils_test.cc b/3rd-party/googletest/googlemock/test/gmock-internal-utils_test.cc
new file mode 100644
index 0000000..6c769a8
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-internal-utils_test.cc
@@ -0,0 +1,766 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the internal utilities.
+
+#include "gmock/internal/gmock-internal-utils.h"
+
+#include <stdlib.h>
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// their code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#ifdef GTEST_OS_CYGWIN
+#include <sys/types.h>  // For ssize_t. NOLINT
+#endif
+
+namespace proto2 {
+class Message;
+}  // namespace proto2
+
+namespace testing {
+namespace internal {
+
+namespace {
+
+TEST(JoinAsKeyValueTupleTest, JoinsEmptyTuple) {
+  EXPECT_EQ("", JoinAsKeyValueTuple({}, Strings()));
+}
+
+TEST(JoinAsKeyValueTupleTest, JoinsOneTuple) {
+  EXPECT_EQ("(a: 1)", JoinAsKeyValueTuple({"a"}, {"1"}));
+}
+
+TEST(JoinAsKeyValueTupleTest, JoinsTwoTuple) {
+  EXPECT_EQ("(a: 1, b: 2)", JoinAsKeyValueTuple({"a", "b"}, {"1", "2"}));
+}
+
+TEST(JoinAsKeyValueTupleTest, JoinsTenTuple) {
+  EXPECT_EQ(
+      "(a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10)",
+      JoinAsKeyValueTuple({"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"},
+                          {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
+  EXPECT_EQ("", ConvertIdentifierNameToWords(""));
+  EXPECT_EQ("", ConvertIdentifierNameToWords("_"));
+  EXPECT_EQ("", ConvertIdentifierNameToWords("__"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsDigits) {
+  EXPECT_EQ("1", ConvertIdentifierNameToWords("_1"));
+  EXPECT_EQ("2", ConvertIdentifierNameToWords("2_"));
+  EXPECT_EQ("34", ConvertIdentifierNameToWords("_34_"));
+  EXPECT_EQ("34 56", ConvertIdentifierNameToWords("_34_56"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsCamelCaseWords) {
+  EXPECT_EQ("a big word", ConvertIdentifierNameToWords("ABigWord"));
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("FooBar"));
+  EXPECT_EQ("foo", ConvertIdentifierNameToWords("Foo_"));
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("_Foo_Bar_"));
+  EXPECT_EQ("foo and bar", ConvertIdentifierNameToWords("_Foo__And_Bar"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContains_SeparatedWords) {
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("foo_bar"));
+  EXPECT_EQ("foo", ConvertIdentifierNameToWords("_foo_"));
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("_foo_bar_"));
+  EXPECT_EQ("foo and bar", ConvertIdentifierNameToWords("_foo__and_bar"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameIsMixture) {
+  EXPECT_EQ("foo bar 123", ConvertIdentifierNameToWords("Foo_bar123"));
+  EXPECT_EQ("chapter 11 section 1",
+            ConvertIdentifierNameToWords("_Chapter11Section_1_"));
+}
+
+TEST(GetRawPointerTest, WorksForSmartPointers) {
+  const char* const raw_p1 = new const char('a');  // NOLINT
+  const std::unique_ptr<const char> p1(raw_p1);
+  EXPECT_EQ(raw_p1, GetRawPointer(p1));
+  double* const raw_p2 = new double(2.5);  // NOLINT
+  const std::shared_ptr<double> p2(raw_p2);
+  EXPECT_EQ(raw_p2, GetRawPointer(p2));
+}
+
+TEST(GetRawPointerTest, WorksForRawPointers) {
+  int* p = nullptr;
+  EXPECT_TRUE(nullptr == GetRawPointer(p));
+  int n = 1;
+  EXPECT_EQ(&n, GetRawPointer(&n));
+}
+
+TEST(GetRawPointerTest, WorksForStdReferenceWrapper) {
+  int n = 1;
+  EXPECT_EQ(&n, GetRawPointer(std::ref(n)));
+  EXPECT_EQ(&n, GetRawPointer(std::cref(n)));
+}
+
+// Tests KindOf<T>.
+
+class Base {};
+class Derived : public Base {};
+
+TEST(KindOfTest, Bool) {
+  EXPECT_EQ(kBool, GMOCK_KIND_OF_(bool));  // NOLINT
+}
+
+TEST(KindOfTest, Integer) {
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(char));                // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(signed char));         // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned char));       // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(short));               // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned short));      // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(int));                 // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned int));        // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(long));                // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned long));       // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(long long));           // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned long long));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(wchar_t));             // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(size_t));              // NOLINT
+#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_MAC) || defined(GTEST_OS_CYGWIN)
+  // ssize_t is not defined on Windows and possibly some other OSes.
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(ssize_t));  // NOLINT
+#endif
+}
+
+TEST(KindOfTest, FloatingPoint) {
+  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(float));        // NOLINT
+  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(double));       // NOLINT
+  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(long double));  // NOLINT
+}
+
+TEST(KindOfTest, Other) {
+  EXPECT_EQ(kOther, GMOCK_KIND_OF_(void*));   // NOLINT
+  EXPECT_EQ(kOther, GMOCK_KIND_OF_(char**));  // NOLINT
+  EXPECT_EQ(kOther, GMOCK_KIND_OF_(Base));    // NOLINT
+}
+
+// Tests LosslessArithmeticConvertible<T, U>.
+
+TEST(LosslessArithmeticConvertibleTest, BoolToBool) {
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, bool>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, BoolToInteger) {
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, char>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, int>::value));
+  EXPECT_TRUE(
+      (LosslessArithmeticConvertible<bool, unsigned long>::value));  // NOLINT
+}
+
+TEST(LosslessArithmeticConvertibleTest, BoolToFloatingPoint) {
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, float>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, double>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, IntegerToBool) {
+  EXPECT_FALSE((LosslessArithmeticConvertible<unsigned char, bool>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, bool>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, IntegerToInteger) {
+  // Unsigned => larger signed is fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<unsigned char, int>::value));
+
+  // Unsigned => larger unsigned is fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<unsigned short,
+                                             uint64_t>::value));  // NOLINT
+
+  // Signed => unsigned is not fine.
+  EXPECT_FALSE(
+      (LosslessArithmeticConvertible<short, uint64_t>::value));  // NOLINT
+  EXPECT_FALSE((LosslessArithmeticConvertible<signed char,
+                                              unsigned int>::value));  // NOLINT
+
+  // Same size and same signedness: fine too.
+  EXPECT_TRUE(
+      (LosslessArithmeticConvertible<unsigned char, unsigned char>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<int, int>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<wchar_t, wchar_t>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<unsigned long,
+                                             unsigned long>::value));  // NOLINT
+
+  // Same size, different signedness: not fine.
+  EXPECT_FALSE(
+      (LosslessArithmeticConvertible<unsigned char, signed char>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, unsigned int>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<uint64_t, int64_t>::value));
+
+  // Larger size => smaller size is not fine.
+  EXPECT_FALSE((LosslessArithmeticConvertible<long, char>::value));  // NOLINT
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, signed char>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int64_t, unsigned int>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, IntegerToFloatingPoint) {
+  // Integers cannot be losslessly converted to floating-points, as
+  // the format of the latter is implementation-defined.
+  EXPECT_FALSE((LosslessArithmeticConvertible<char, float>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, double>::value));
+  EXPECT_FALSE(
+      (LosslessArithmeticConvertible<short, long double>::value));  // NOLINT
+}
+
+TEST(LosslessArithmeticConvertibleTest, FloatingPointToBool) {
+  EXPECT_FALSE((LosslessArithmeticConvertible<float, bool>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<double, bool>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, FloatingPointToInteger) {
+  EXPECT_FALSE((LosslessArithmeticConvertible<float, long>::value));  // NOLINT
+  EXPECT_FALSE((LosslessArithmeticConvertible<double, int64_t>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<long double, int>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, FloatingPointToFloatingPoint) {
+  // Smaller size => larger size is fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<float, double>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<float, long double>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<double, long double>::value));
+
+  // Same size: fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<float, float>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<double, double>::value));
+
+  // Larger size => smaller size is not fine.
+  EXPECT_FALSE((LosslessArithmeticConvertible<double, float>::value));
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (sizeof(double) == sizeof(long double)) {  // NOLINT
+    GTEST_INTENTIONAL_CONST_COND_POP_()
+    // In some implementations (e.g. MSVC), double and long double
+    // have the same size.
+    EXPECT_TRUE((LosslessArithmeticConvertible<long double, double>::value));
+  } else {
+    EXPECT_FALSE((LosslessArithmeticConvertible<long double, double>::value));
+  }
+}
+
+// Tests the TupleMatches() template function.
+
+TEST(TupleMatchesTest, WorksForSize0) {
+  std::tuple<> matchers;
+  std::tuple<> values;
+
+  EXPECT_TRUE(TupleMatches(matchers, values));
+}
+
+TEST(TupleMatchesTest, WorksForSize1) {
+  std::tuple<Matcher<int>> matchers(Eq(1));
+  std::tuple<int> values1(1), values2(2);
+
+  EXPECT_TRUE(TupleMatches(matchers, values1));
+  EXPECT_FALSE(TupleMatches(matchers, values2));
+}
+
+TEST(TupleMatchesTest, WorksForSize2) {
+  std::tuple<Matcher<int>, Matcher<char>> matchers(Eq(1), Eq('a'));
+  std::tuple<int, char> values1(1, 'a'), values2(1, 'b'), values3(2, 'a'),
+      values4(2, 'b');
+
+  EXPECT_TRUE(TupleMatches(matchers, values1));
+  EXPECT_FALSE(TupleMatches(matchers, values2));
+  EXPECT_FALSE(TupleMatches(matchers, values3));
+  EXPECT_FALSE(TupleMatches(matchers, values4));
+}
+
+TEST(TupleMatchesTest, WorksForSize5) {
+  std::tuple<Matcher<int>, Matcher<char>, Matcher<bool>,
+             Matcher<long>,  // NOLINT
+             Matcher<std::string>>
+      matchers(Eq(1), Eq('a'), Eq(true), Eq(2L), Eq("hi"));
+  std::tuple<int, char, bool, long, std::string>  // NOLINT
+      values1(1, 'a', true, 2L, "hi"), values2(1, 'a', true, 2L, "hello"),
+      values3(2, 'a', true, 2L, "hi");
+
+  EXPECT_TRUE(TupleMatches(matchers, values1));
+  EXPECT_FALSE(TupleMatches(matchers, values2));
+  EXPECT_FALSE(TupleMatches(matchers, values3));
+}
+
+// Tests that Assert(true, ...) succeeds.
+TEST(AssertTest, SucceedsOnTrue) {
+  Assert(true, __FILE__, __LINE__, "This should succeed.");
+  Assert(true, __FILE__, __LINE__);  // This should succeed too.
+}
+
+// Tests that Assert(false, ...) generates a fatal failure.
+TEST(AssertTest, FailsFatallyOnFalse) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      { Assert(false, __FILE__, __LINE__, "This should fail."); }, "");
+
+  EXPECT_DEATH_IF_SUPPORTED({ Assert(false, __FILE__, __LINE__); }, "");
+}
+
+// Tests that Expect(true, ...) succeeds.
+TEST(ExpectTest, SucceedsOnTrue) {
+  Expect(true, __FILE__, __LINE__, "This should succeed.");
+  Expect(true, __FILE__, __LINE__);  // This should succeed too.
+}
+
+// Tests that Expect(false, ...) generates a non-fatal failure.
+TEST(ExpectTest, FailsNonfatallyOnFalse) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        Expect(false, __FILE__, __LINE__, "This should fail.");
+      },
+      "This should fail");
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        Expect(false, __FILE__, __LINE__);
+      },
+      "Expectation failed");
+}
+
+// Tests LogIsVisible().
+
+class LogIsVisibleTest : public ::testing::Test {
+ protected:
+  void SetUp() override { original_verbose_ = GMOCK_FLAG_GET(verbose); }
+
+  void TearDown() override { GMOCK_FLAG_SET(verbose, original_verbose_); }
+
+  std::string original_verbose_;
+};
+
+TEST_F(LogIsVisibleTest, AlwaysReturnsTrueIfVerbosityIsInfo) {
+  GMOCK_FLAG_SET(verbose, kInfoVerbosity);
+  EXPECT_TRUE(LogIsVisible(kInfo));
+  EXPECT_TRUE(LogIsVisible(kWarning));
+}
+
+TEST_F(LogIsVisibleTest, AlwaysReturnsFalseIfVerbosityIsError) {
+  GMOCK_FLAG_SET(verbose, kErrorVerbosity);
+  EXPECT_FALSE(LogIsVisible(kInfo));
+  EXPECT_FALSE(LogIsVisible(kWarning));
+}
+
+TEST_F(LogIsVisibleTest, WorksWhenVerbosityIsWarning) {
+  GMOCK_FLAG_SET(verbose, kWarningVerbosity);
+  EXPECT_FALSE(LogIsVisible(kInfo));
+  EXPECT_TRUE(LogIsVisible(kWarning));
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests the Log() function.
+
+// Verifies that Log() behaves correctly for the given verbosity level
+// and log severity.
+void TestLogWithSeverity(const std::string& verbosity, LogSeverity severity,
+                         bool should_print) {
+  const std::string old_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, verbosity);
+  CaptureStdout();
+  Log(severity, "Test log.\n", 0);
+  if (should_print) {
+    EXPECT_THAT(
+        GetCapturedStdout().c_str(),
+        ContainsRegex(severity == kWarning
+                          ? "^\nGMOCK WARNING:\nTest log\\.\nStack trace:\n"
+                          : "^\nTest log\\.\nStack trace:\n"));
+  } else {
+    EXPECT_STREQ("", GetCapturedStdout().c_str());
+  }
+  GMOCK_FLAG_SET(verbose, old_flag);
+}
+
+// Tests that when the stack_frames_to_skip parameter is negative,
+// Log() doesn't include the stack trace in the output.
+TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, kInfoVerbosity);
+  CaptureStdout();
+  Log(kInfo, "Test log.\n", -1);
+  EXPECT_STREQ("\nTest log.\n", GetCapturedStdout().c_str());
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+struct MockStackTraceGetter : testing::internal::OsStackTraceGetterInterface {
+  std::string CurrentStackTrace(int max_depth, int skip_count) override {
+    return (testing::Message() << max_depth << "::" << skip_count << "\n")
+        .GetString();
+  }
+  void UponLeavingGTest() override {}
+};
+
+// Tests that in opt mode, a positive stack_frames_to_skip argument is
+// treated as 0.
+TEST(LogTest, NoSkippingStackFrameInOptMode) {
+  MockStackTraceGetter* mock_os_stack_trace_getter = new MockStackTraceGetter;
+  GetUnitTestImpl()->set_os_stack_trace_getter(mock_os_stack_trace_getter);
+
+  CaptureStdout();
+  Log(kWarning, "Test log.\n", 100);
+  const std::string log = GetCapturedStdout();
+
+  std::string expected_trace =
+      (testing::Message() << GTEST_FLAG_GET(stack_trace_depth) << "::")
+          .GetString();
+  std::string expected_message =
+      "\nGMOCK WARNING:\n"
+      "Test log.\n"
+      "Stack trace:\n" +
+      expected_trace;
+  EXPECT_THAT(log, HasSubstr(expected_message));
+  int skip_count = atoi(log.substr(expected_message.size()).c_str());
+
+#if defined(NDEBUG)
+  // In opt mode, no stack frame should be skipped.
+  const int expected_skip_count = 0;
+#else
+  // In dbg mode, the stack frames should be skipped.
+  const int expected_skip_count = 100;
+#endif
+
+  // Note that each inner implementation layer will +1 the number to remove
+  // itself from the trace. This means that the value is a little higher than
+  // expected, but close enough.
+  EXPECT_THAT(skip_count,
+              AllOf(Ge(expected_skip_count), Le(expected_skip_count + 10)));
+
+  // Restores the default OS stack trace getter.
+  GetUnitTestImpl()->set_os_stack_trace_getter(nullptr);
+}
+
+// Tests that all logs are printed when the value of the
+// --gmock_verbose flag is "info".
+TEST(LogTest, AllLogsArePrintedWhenVerbosityIsInfo) {
+  TestLogWithSeverity(kInfoVerbosity, kInfo, true);
+  TestLogWithSeverity(kInfoVerbosity, kWarning, true);
+}
+
+// Tests that only warnings are printed when the value of the
+// --gmock_verbose flag is "warning".
+TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsWarning) {
+  TestLogWithSeverity(kWarningVerbosity, kInfo, false);
+  TestLogWithSeverity(kWarningVerbosity, kWarning, true);
+}
+
+// Tests that no logs are printed when the value of the
+// --gmock_verbose flag is "error".
+TEST(LogTest, NoLogsArePrintedWhenVerbosityIsError) {
+  TestLogWithSeverity(kErrorVerbosity, kInfo, false);
+  TestLogWithSeverity(kErrorVerbosity, kWarning, false);
+}
+
+// Tests that only warnings are printed when the value of the
+// --gmock_verbose flag is invalid.
+TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsInvalid) {
+  TestLogWithSeverity("invalid", kInfo, false);
+  TestLogWithSeverity("invalid", kWarning, true);
+}
+
+// Verifies that Log() behaves correctly for the given verbosity level
+// and log severity.
+std::string GrabOutput(void (*logger)(), const char* verbosity) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, verbosity);
+  CaptureStdout();
+  logger();
+  GMOCK_FLAG_SET(verbose, saved_flag);
+  return GetCapturedStdout();
+}
+
+class DummyMock {
+ public:
+  MOCK_METHOD0(TestMethod, void());
+  MOCK_METHOD1(TestMethodArg, void(int dummy));
+};
+
+void ExpectCallLogger() {
+  DummyMock mock;
+  EXPECT_CALL(mock, TestMethod());
+  mock.TestMethod();
+}
+
+// Verifies that EXPECT_CALL logs if the --gmock_verbose flag is set to "info".
+TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) {
+  EXPECT_THAT(std::string(GrabOutput(ExpectCallLogger, kInfoVerbosity)),
+              HasSubstr("EXPECT_CALL(mock, TestMethod())"));
+}
+
+// Verifies that EXPECT_CALL doesn't log
+// if the --gmock_verbose flag is set to "warning".
+TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsWarning) {
+  EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kWarningVerbosity).c_str());
+}
+
+// Verifies that EXPECT_CALL doesn't log
+// if the --gmock_verbose flag is set to "error".
+TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsError) {
+  EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kErrorVerbosity).c_str());
+}
+
+void OnCallLogger() {
+  DummyMock mock;
+  ON_CALL(mock, TestMethod());
+}
+
+// Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info".
+TEST(OnCallTest, LogsWhenVerbosityIsInfo) {
+  EXPECT_THAT(std::string(GrabOutput(OnCallLogger, kInfoVerbosity)),
+              HasSubstr("ON_CALL(mock, TestMethod())"));
+}
+
+// Verifies that ON_CALL doesn't log
+// if the --gmock_verbose flag is set to "warning".
+TEST(OnCallTest, DoesNotLogWhenVerbosityIsWarning) {
+  EXPECT_STREQ("", GrabOutput(OnCallLogger, kWarningVerbosity).c_str());
+}
+
+// Verifies that ON_CALL doesn't log if
+// the --gmock_verbose flag is set to "error".
+TEST(OnCallTest, DoesNotLogWhenVerbosityIsError) {
+  EXPECT_STREQ("", GrabOutput(OnCallLogger, kErrorVerbosity).c_str());
+}
+
+void OnCallAnyArgumentLogger() {
+  DummyMock mock;
+  ON_CALL(mock, TestMethodArg(_));
+}
+
+// Verifies that ON_CALL prints provided _ argument.
+TEST(OnCallTest, LogsAnythingArgument) {
+  EXPECT_THAT(std::string(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity)),
+              HasSubstr("ON_CALL(mock, TestMethodArg(_)"));
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests StlContainerView.
+
+TEST(StlContainerViewTest, WorksForStlContainer) {
+  StaticAssertTypeEq<std::vector<int>,
+                     StlContainerView<std::vector<int>>::type>();
+  StaticAssertTypeEq<const std::vector<double>&,
+                     StlContainerView<std::vector<double>>::const_reference>();
+
+  typedef std::vector<char> Chars;
+  Chars v1;
+  const Chars& v2(StlContainerView<Chars>::ConstReference(v1));
+  EXPECT_EQ(&v1, &v2);
+
+  v1.push_back('a');
+  Chars v3 = StlContainerView<Chars>::Copy(v1);
+  EXPECT_THAT(v3, Eq(v3));
+}
+
+TEST(StlContainerViewTest, WorksForStaticNativeArray) {
+  StaticAssertTypeEq<NativeArray<int>, StlContainerView<int[3]>::type>();
+  StaticAssertTypeEq<NativeArray<double>,
+                     StlContainerView<const double[4]>::type>();
+  StaticAssertTypeEq<NativeArray<char[3]>,
+                     StlContainerView<const char[2][3]>::type>();
+
+  StaticAssertTypeEq<const NativeArray<int>,
+                     StlContainerView<int[2]>::const_reference>();
+
+  int a1[3] = {0, 1, 2};
+  NativeArray<int> a2 = StlContainerView<int[3]>::ConstReference(a1);
+  EXPECT_EQ(3U, a2.size());
+  EXPECT_EQ(a1, a2.begin());
+
+  const NativeArray<int> a3 = StlContainerView<int[3]>::Copy(a1);
+  ASSERT_EQ(3U, a3.size());
+  EXPECT_EQ(0, a3.begin()[0]);
+  EXPECT_EQ(1, a3.begin()[1]);
+  EXPECT_EQ(2, a3.begin()[2]);
+
+  // Makes sure a1 and a3 aren't aliases.
+  a1[0] = 3;
+  EXPECT_EQ(0, a3.begin()[0]);
+}
+
+TEST(StlContainerViewTest, WorksForDynamicNativeArray) {
+  StaticAssertTypeEq<NativeArray<int>,
+                     StlContainerView<std::tuple<const int*, size_t>>::type>();
+  StaticAssertTypeEq<
+      NativeArray<double>,
+      StlContainerView<std::tuple<std::shared_ptr<double>, int>>::type>();
+
+  StaticAssertTypeEq<
+      const NativeArray<int>,
+      StlContainerView<std::tuple<const int*, int>>::const_reference>();
+
+  int a1[3] = {0, 1, 2};
+  const int* const p1 = a1;
+  NativeArray<int> a2 =
+      StlContainerView<std::tuple<const int*, int>>::ConstReference(
+          std::make_tuple(p1, 3));
+  EXPECT_EQ(3U, a2.size());
+  EXPECT_EQ(a1, a2.begin());
+
+  const NativeArray<int> a3 = StlContainerView<std::tuple<int*, size_t>>::Copy(
+      std::make_tuple(static_cast<int*>(a1), 3));
+  ASSERT_EQ(3U, a3.size());
+  EXPECT_EQ(0, a3.begin()[0]);
+  EXPECT_EQ(1, a3.begin()[1]);
+  EXPECT_EQ(2, a3.begin()[2]);
+
+  // Makes sure a1 and a3 aren't aliases.
+  a1[0] = 3;
+  EXPECT_EQ(0, a3.begin()[0]);
+}
+
+// Tests the Function template struct.
+
+TEST(FunctionTest, Nullary) {
+  typedef Function<int()> F;  // NOLINT
+  EXPECT_EQ(0u, F::ArgumentCount);
+  EXPECT_TRUE((std::is_same<int, F::Result>::value));
+  EXPECT_TRUE((std::is_same<std::tuple<>, F::ArgumentTuple>::value));
+  EXPECT_TRUE((std::is_same<std::tuple<>, F::ArgumentMatcherTuple>::value));
+  EXPECT_TRUE((std::is_same<void(), F::MakeResultVoid>::value));
+  EXPECT_TRUE((std::is_same<IgnoredValue(), F::MakeResultIgnoredValue>::value));
+}
+
+TEST(FunctionTest, Unary) {
+  typedef Function<int(bool)> F;  // NOLINT
+  EXPECT_EQ(1u, F::ArgumentCount);
+  EXPECT_TRUE((std::is_same<int, F::Result>::value));
+  EXPECT_TRUE((std::is_same<bool, F::Arg<0>::type>::value));
+  EXPECT_TRUE((std::is_same<std::tuple<bool>, F::ArgumentTuple>::value));
+  EXPECT_TRUE((
+      std::is_same<std::tuple<Matcher<bool>>, F::ArgumentMatcherTuple>::value));
+  EXPECT_TRUE((std::is_same<void(bool), F::MakeResultVoid>::value));  // NOLINT
+  EXPECT_TRUE((std::is_same<IgnoredValue(bool),                       // NOLINT
+                            F::MakeResultIgnoredValue>::value));
+}
+
+TEST(FunctionTest, Binary) {
+  typedef Function<int(bool, const long&)> F;  // NOLINT
+  EXPECT_EQ(2u, F::ArgumentCount);
+  EXPECT_TRUE((std::is_same<int, F::Result>::value));
+  EXPECT_TRUE((std::is_same<bool, F::Arg<0>::type>::value));
+  EXPECT_TRUE((std::is_same<const long&, F::Arg<1>::type>::value));  // NOLINT
+  EXPECT_TRUE((std::is_same<std::tuple<bool, const long&>,           // NOLINT
+                            F::ArgumentTuple>::value));
+  EXPECT_TRUE(
+      (std::is_same<std::tuple<Matcher<bool>, Matcher<const long&>>,  // NOLINT
+                    F::ArgumentMatcherTuple>::value));
+  EXPECT_TRUE((std::is_same<void(bool, const long&),  // NOLINT
+                            F::MakeResultVoid>::value));
+  EXPECT_TRUE((std::is_same<IgnoredValue(bool, const long&),  // NOLINT
+                            F::MakeResultIgnoredValue>::value));
+}
+
+TEST(FunctionTest, LongArgumentList) {
+  typedef Function<char(bool, int, char*, int&, const long&)> F;  // NOLINT
+  EXPECT_EQ(5u, F::ArgumentCount);
+  EXPECT_TRUE((std::is_same<char, F::Result>::value));
+  EXPECT_TRUE((std::is_same<bool, F::Arg<0>::type>::value));
+  EXPECT_TRUE((std::is_same<int, F::Arg<1>::type>::value));
+  EXPECT_TRUE((std::is_same<char*, F::Arg<2>::type>::value));
+  EXPECT_TRUE((std::is_same<int&, F::Arg<3>::type>::value));
+  EXPECT_TRUE((std::is_same<const long&, F::Arg<4>::type>::value));  // NOLINT
+  EXPECT_TRUE(
+      (std::is_same<std::tuple<bool, int, char*, int&, const long&>,  // NOLINT
+                    F::ArgumentTuple>::value));
+  EXPECT_TRUE(
+      (std::is_same<
+          std::tuple<Matcher<bool>, Matcher<int>, Matcher<char*>, Matcher<int&>,
+                     Matcher<const long&>>,  // NOLINT
+          F::ArgumentMatcherTuple>::value));
+  EXPECT_TRUE(
+      (std::is_same<void(bool, int, char*, int&, const long&),  // NOLINT
+                    F::MakeResultVoid>::value));
+  EXPECT_TRUE((
+      std::is_same<IgnoredValue(bool, int, char*, int&, const long&),  // NOLINT
+                   F::MakeResultIgnoredValue>::value));
+}
+
+TEST(Base64Unescape, InvalidString) {
+  std::string unescaped;
+  EXPECT_FALSE(Base64Unescape("(invalid)", &unescaped));
+}
+
+TEST(Base64Unescape, ShortString) {
+  std::string unescaped;
+  EXPECT_TRUE(Base64Unescape("SGVsbG8gd29ybGQh", &unescaped));
+  EXPECT_EQ("Hello world!", unescaped);
+}
+
+TEST(Base64Unescape, ShortStringWithPadding) {
+  std::string unescaped;
+  EXPECT_TRUE(Base64Unescape("SGVsbG8gd29ybGQ=", &unescaped));
+  EXPECT_EQ("Hello world", unescaped);
+}
+
+TEST(Base64Unescape, ShortStringWithoutPadding) {
+  std::string unescaped;
+  EXPECT_TRUE(Base64Unescape("SGVsbG8gd29ybGQ", &unescaped));
+  EXPECT_EQ("Hello world", unescaped);
+}
+
+TEST(Base64Unescape, LongStringWithWhiteSpaces) {
+  std::string escaped =
+      R"(TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
+  IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
+  dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
+  dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
+  ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=)";
+  std::string expected =
+      "Man is distinguished, not only by his reason, but by this singular "
+      "passion from other animals, which is a lust of the mind, that by a "
+      "perseverance of delight in the continued and indefatigable generation "
+      "of knowledge, exceeds the short vehemence of any carnal pleasure.";
+  std::string unescaped;
+  EXPECT_TRUE(Base64Unescape(escaped, &unescaped));
+  EXPECT_EQ(expected, unescaped);
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc b/3rd-party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc
new file mode 100644
index 0000000..7521c0d
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc
@@ -0,0 +1,1516 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests some commonly used argument matchers.
+
+#include <cmath>
+#include <limits>
+#include <memory>
+#include <string>
+
+#include "test/gmock-matchers_test.h"
+
+// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
+// possible loss of data and C4100, unreferenced local parameter
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
+
+namespace testing {
+namespace gmock_matchers_test {
+namespace {
+
+typedef ::std::tuple<long, int> Tuple2;  // NOLINT
+
+// Tests that Eq() matches a 2-tuple where the first field == the
+// second field.
+TEST(Eq2Test, MatchesEqualArguments) {
+  Matcher<const Tuple2&> m = Eq();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 6)));
+}
+
+// Tests that Eq() describes itself properly.
+TEST(Eq2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Eq();
+  EXPECT_EQ("are an equal pair", Describe(m));
+}
+
+// Tests that Ge() matches a 2-tuple where the first field >= the
+// second field.
+TEST(Ge2Test, MatchesGreaterThanOrEqualArguments) {
+  Matcher<const Tuple2&> m = Ge();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 4)));
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 6)));
+}
+
+// Tests that Ge() describes itself properly.
+TEST(Ge2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Ge();
+  EXPECT_EQ("are a pair where the first >= the second", Describe(m));
+}
+
+// Tests that Gt() matches a 2-tuple where the first field > the
+// second field.
+TEST(Gt2Test, MatchesGreaterThanArguments) {
+  Matcher<const Tuple2&> m = Gt();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 4)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 6)));
+}
+
+// Tests that Gt() describes itself properly.
+TEST(Gt2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Gt();
+  EXPECT_EQ("are a pair where the first > the second", Describe(m));
+}
+
+// Tests that Le() matches a 2-tuple where the first field <= the
+// second field.
+TEST(Le2Test, MatchesLessThanOrEqualArguments) {
+  Matcher<const Tuple2&> m = Le();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 6)));
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 4)));
+}
+
+// Tests that Le() describes itself properly.
+TEST(Le2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Le();
+  EXPECT_EQ("are a pair where the first <= the second", Describe(m));
+}
+
+// Tests that Lt() matches a 2-tuple where the first field < the
+// second field.
+TEST(Lt2Test, MatchesLessThanArguments) {
+  Matcher<const Tuple2&> m = Lt();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 6)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 4)));
+}
+
+// Tests that Lt() describes itself properly.
+TEST(Lt2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Lt();
+  EXPECT_EQ("are a pair where the first < the second", Describe(m));
+}
+
+// Tests that Ne() matches a 2-tuple where the first field != the
+// second field.
+TEST(Ne2Test, MatchesUnequalArguments) {
+  Matcher<const Tuple2&> m = Ne();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 6)));
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 4)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 5)));
+}
+
+// Tests that Ne() describes itself properly.
+TEST(Ne2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Ne();
+  EXPECT_EQ("are an unequal pair", Describe(m));
+}
+
+TEST(PairMatchBaseTest, WorksWithMoveOnly) {
+  using Pointers = std::tuple<std::unique_ptr<int>, std::unique_ptr<int>>;
+  Matcher<Pointers> matcher = Eq();
+  Pointers pointers;
+  // Tested values don't matter; the point is that matcher does not copy the
+  // matched values.
+  EXPECT_TRUE(matcher.Matches(pointers));
+}
+
+// Tests that IsNan() matches a NaN, with float.
+TEST(IsNan, FloatMatchesNan) {
+  float quiet_nan = std::numeric_limits<float>::quiet_NaN();
+  float other_nan = std::nanf("1");
+  float real_value = 1.0f;
+
+  Matcher<float> m = IsNan();
+  EXPECT_TRUE(m.Matches(quiet_nan));
+  EXPECT_TRUE(m.Matches(other_nan));
+  EXPECT_FALSE(m.Matches(real_value));
+
+  Matcher<float&> m_ref = IsNan();
+  EXPECT_TRUE(m_ref.Matches(quiet_nan));
+  EXPECT_TRUE(m_ref.Matches(other_nan));
+  EXPECT_FALSE(m_ref.Matches(real_value));
+
+  Matcher<const float&> m_cref = IsNan();
+  EXPECT_TRUE(m_cref.Matches(quiet_nan));
+  EXPECT_TRUE(m_cref.Matches(other_nan));
+  EXPECT_FALSE(m_cref.Matches(real_value));
+}
+
+// Tests that IsNan() matches a NaN, with double.
+TEST(IsNan, DoubleMatchesNan) {
+  double quiet_nan = std::numeric_limits<double>::quiet_NaN();
+  double other_nan = std::nan("1");
+  double real_value = 1.0;
+
+  Matcher<double> m = IsNan();
+  EXPECT_TRUE(m.Matches(quiet_nan));
+  EXPECT_TRUE(m.Matches(other_nan));
+  EXPECT_FALSE(m.Matches(real_value));
+
+  Matcher<double&> m_ref = IsNan();
+  EXPECT_TRUE(m_ref.Matches(quiet_nan));
+  EXPECT_TRUE(m_ref.Matches(other_nan));
+  EXPECT_FALSE(m_ref.Matches(real_value));
+
+  Matcher<const double&> m_cref = IsNan();
+  EXPECT_TRUE(m_cref.Matches(quiet_nan));
+  EXPECT_TRUE(m_cref.Matches(other_nan));
+  EXPECT_FALSE(m_cref.Matches(real_value));
+}
+
+// Tests that IsNan() matches a NaN, with long double.
+TEST(IsNan, LongDoubleMatchesNan) {
+  long double quiet_nan = std::numeric_limits<long double>::quiet_NaN();
+  long double other_nan = std::nan("1");
+  long double real_value = 1.0;
+
+  Matcher<long double> m = IsNan();
+  EXPECT_TRUE(m.Matches(quiet_nan));
+  EXPECT_TRUE(m.Matches(other_nan));
+  EXPECT_FALSE(m.Matches(real_value));
+
+  Matcher<long double&> m_ref = IsNan();
+  EXPECT_TRUE(m_ref.Matches(quiet_nan));
+  EXPECT_TRUE(m_ref.Matches(other_nan));
+  EXPECT_FALSE(m_ref.Matches(real_value));
+
+  Matcher<const long double&> m_cref = IsNan();
+  EXPECT_TRUE(m_cref.Matches(quiet_nan));
+  EXPECT_TRUE(m_cref.Matches(other_nan));
+  EXPECT_FALSE(m_cref.Matches(real_value));
+}
+
+// Tests that IsNan() works with Not.
+TEST(IsNan, NotMatchesNan) {
+  Matcher<float> mf = Not(IsNan());
+  EXPECT_FALSE(mf.Matches(std::numeric_limits<float>::quiet_NaN()));
+  EXPECT_FALSE(mf.Matches(std::nanf("1")));
+  EXPECT_TRUE(mf.Matches(1.0));
+
+  Matcher<double> md = Not(IsNan());
+  EXPECT_FALSE(md.Matches(std::numeric_limits<double>::quiet_NaN()));
+  EXPECT_FALSE(md.Matches(std::nan("1")));
+  EXPECT_TRUE(md.Matches(1.0));
+
+  Matcher<long double> mld = Not(IsNan());
+  EXPECT_FALSE(mld.Matches(std::numeric_limits<long double>::quiet_NaN()));
+  EXPECT_FALSE(mld.Matches(std::nanl("1")));
+  EXPECT_TRUE(mld.Matches(1.0));
+}
+
+// Tests that IsNan() can describe itself.
+TEST(IsNan, CanDescribeSelf) {
+  Matcher<float> mf = IsNan();
+  EXPECT_EQ("is NaN", Describe(mf));
+
+  Matcher<double> md = IsNan();
+  EXPECT_EQ("is NaN", Describe(md));
+
+  Matcher<long double> mld = IsNan();
+  EXPECT_EQ("is NaN", Describe(mld));
+}
+
+// Tests that IsNan() can describe itself with Not.
+TEST(IsNan, CanDescribeSelfWithNot) {
+  Matcher<float> mf = Not(IsNan());
+  EXPECT_EQ("isn't NaN", Describe(mf));
+
+  Matcher<double> md = Not(IsNan());
+  EXPECT_EQ("isn't NaN", Describe(md));
+
+  Matcher<long double> mld = Not(IsNan());
+  EXPECT_EQ("isn't NaN", Describe(mld));
+}
+
+// Tests that FloatEq() matches a 2-tuple where
+// FloatEq(first field) matches the second field.
+TEST(FloatEq2Test, MatchesEqualArguments) {
+  typedef ::std::tuple<float, float> Tpl;
+  Matcher<const Tpl&> m = FloatEq();
+  EXPECT_TRUE(m.Matches(Tpl(1.0f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(0.3f, 0.1f + 0.1f + 0.1f)));
+  EXPECT_FALSE(m.Matches(Tpl(1.1f, 1.0f)));
+}
+
+// Tests that FloatEq() describes itself properly.
+TEST(FloatEq2Test, CanDescribeSelf) {
+  Matcher<const ::std::tuple<float, float>&> m = FloatEq();
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that NanSensitiveFloatEq() matches a 2-tuple where
+// NanSensitiveFloatEq(first field) matches the second field.
+TEST(NanSensitiveFloatEqTest, MatchesEqualArgumentsWithNaN) {
+  typedef ::std::tuple<float, float> Tpl;
+  Matcher<const Tpl&> m = NanSensitiveFloatEq();
+  EXPECT_TRUE(m.Matches(Tpl(1.0f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(std::numeric_limits<float>::quiet_NaN(),
+                            std::numeric_limits<float>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(1.1f, 1.0f)));
+  EXPECT_FALSE(m.Matches(Tpl(1.0f, std::numeric_limits<float>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(std::numeric_limits<float>::quiet_NaN(), 1.0f)));
+}
+
+// Tests that NanSensitiveFloatEq() describes itself properly.
+TEST(NanSensitiveFloatEqTest, CanDescribeSelfWithNaNs) {
+  Matcher<const ::std::tuple<float, float>&> m = NanSensitiveFloatEq();
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that DoubleEq() matches a 2-tuple where
+// DoubleEq(first field) matches the second field.
+TEST(DoubleEq2Test, MatchesEqualArguments) {
+  typedef ::std::tuple<double, double> Tpl;
+  Matcher<const Tpl&> m = DoubleEq();
+  EXPECT_TRUE(m.Matches(Tpl(1.0, 1.0)));
+  EXPECT_TRUE(m.Matches(Tpl(0.3, 0.1 + 0.1 + 0.1)));
+  EXPECT_FALSE(m.Matches(Tpl(1.1, 1.0)));
+}
+
+// Tests that DoubleEq() describes itself properly.
+TEST(DoubleEq2Test, CanDescribeSelf) {
+  Matcher<const ::std::tuple<double, double>&> m = DoubleEq();
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that NanSensitiveDoubleEq() matches a 2-tuple where
+// NanSensitiveDoubleEq(first field) matches the second field.
+TEST(NanSensitiveDoubleEqTest, MatchesEqualArgumentsWithNaN) {
+  typedef ::std::tuple<double, double> Tpl;
+  Matcher<const Tpl&> m = NanSensitiveDoubleEq();
+  EXPECT_TRUE(m.Matches(Tpl(1.0f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(std::numeric_limits<double>::quiet_NaN(),
+                            std::numeric_limits<double>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(1.1f, 1.0f)));
+  EXPECT_FALSE(m.Matches(Tpl(1.0f, std::numeric_limits<double>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(std::numeric_limits<double>::quiet_NaN(), 1.0f)));
+}
+
+// Tests that DoubleEq() describes itself properly.
+TEST(NanSensitiveDoubleEqTest, CanDescribeSelfWithNaNs) {
+  Matcher<const ::std::tuple<double, double>&> m = NanSensitiveDoubleEq();
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that FloatEq() matches a 2-tuple where
+// FloatNear(first field, max_abs_error) matches the second field.
+TEST(FloatNear2Test, MatchesEqualArguments) {
+  typedef ::std::tuple<float, float> Tpl;
+  Matcher<const Tpl&> m = FloatNear(0.5f);
+  EXPECT_TRUE(m.Matches(Tpl(1.0f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(1.3f, 1.0f)));
+  EXPECT_FALSE(m.Matches(Tpl(1.8f, 1.0f)));
+}
+
+// Tests that FloatNear() describes itself properly.
+TEST(FloatNear2Test, CanDescribeSelf) {
+  Matcher<const ::std::tuple<float, float>&> m = FloatNear(0.5f);
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that NanSensitiveFloatNear() matches a 2-tuple where
+// NanSensitiveFloatNear(first field) matches the second field.
+TEST(NanSensitiveFloatNearTest, MatchesNearbyArgumentsWithNaN) {
+  typedef ::std::tuple<float, float> Tpl;
+  Matcher<const Tpl&> m = NanSensitiveFloatNear(0.5f);
+  EXPECT_TRUE(m.Matches(Tpl(1.0f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(1.1f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(std::numeric_limits<float>::quiet_NaN(),
+                            std::numeric_limits<float>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(1.6f, 1.0f)));
+  EXPECT_FALSE(m.Matches(Tpl(1.0f, std::numeric_limits<float>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(std::numeric_limits<float>::quiet_NaN(), 1.0f)));
+}
+
+// Tests that NanSensitiveFloatNear() describes itself properly.
+TEST(NanSensitiveFloatNearTest, CanDescribeSelfWithNaNs) {
+  Matcher<const ::std::tuple<float, float>&> m = NanSensitiveFloatNear(0.5f);
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that FloatEq() matches a 2-tuple where
+// DoubleNear(first field, max_abs_error) matches the second field.
+TEST(DoubleNear2Test, MatchesEqualArguments) {
+  typedef ::std::tuple<double, double> Tpl;
+  Matcher<const Tpl&> m = DoubleNear(0.5);
+  EXPECT_TRUE(m.Matches(Tpl(1.0, 1.0)));
+  EXPECT_TRUE(m.Matches(Tpl(1.3, 1.0)));
+  EXPECT_FALSE(m.Matches(Tpl(1.8, 1.0)));
+}
+
+// Tests that DoubleNear() describes itself properly.
+TEST(DoubleNear2Test, CanDescribeSelf) {
+  Matcher<const ::std::tuple<double, double>&> m = DoubleNear(0.5);
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that NanSensitiveDoubleNear() matches a 2-tuple where
+// NanSensitiveDoubleNear(first field) matches the second field.
+TEST(NanSensitiveDoubleNearTest, MatchesNearbyArgumentsWithNaN) {
+  typedef ::std::tuple<double, double> Tpl;
+  Matcher<const Tpl&> m = NanSensitiveDoubleNear(0.5f);
+  EXPECT_TRUE(m.Matches(Tpl(1.0f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(1.1f, 1.0f)));
+  EXPECT_TRUE(m.Matches(Tpl(std::numeric_limits<double>::quiet_NaN(),
+                            std::numeric_limits<double>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(1.6f, 1.0f)));
+  EXPECT_FALSE(m.Matches(Tpl(1.0f, std::numeric_limits<double>::quiet_NaN())));
+  EXPECT_FALSE(m.Matches(Tpl(std::numeric_limits<double>::quiet_NaN(), 1.0f)));
+}
+
+// Tests that NanSensitiveDoubleNear() describes itself properly.
+TEST(NanSensitiveDoubleNearTest, CanDescribeSelfWithNaNs) {
+  Matcher<const ::std::tuple<double, double>&> m = NanSensitiveDoubleNear(0.5f);
+  EXPECT_EQ("are an almost-equal pair", Describe(m));
+}
+
+// Tests that Not(m) matches any value that doesn't match m.
+TEST(NotTest, NegatesMatcher) {
+  Matcher<int> m;
+  m = Not(Eq(2));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+}
+
+// Tests that Not(m) describes itself properly.
+TEST(NotTest, CanDescribeSelf) {
+  Matcher<int> m = Not(Eq(5));
+  EXPECT_EQ("isn't equal to 5", Describe(m));
+}
+
+// Tests that monomorphic matchers are safely cast by the Not matcher.
+TEST(NotTest, NotMatcherSafelyCastsMonomorphicMatchers) {
+  // greater_than_5 is a monomorphic matcher.
+  Matcher<int> greater_than_5 = Gt(5);
+
+  Matcher<const int&> m = Not(greater_than_5);
+  Matcher<int&> m2 = Not(greater_than_5);
+  Matcher<int&> m3 = Not(m);
+}
+
+// Helper to allow easy testing of AllOf matchers with num parameters.
+void AllOfMatches(int num, const Matcher<int>& m) {
+  SCOPED_TRACE(Describe(m));
+  EXPECT_TRUE(m.Matches(0));
+  for (int i = 1; i <= num; ++i) {
+    EXPECT_FALSE(m.Matches(i));
+  }
+  EXPECT_TRUE(m.Matches(num + 1));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(AllOfTest);
+
+// Tests that AllOf(m1, ..., mn) matches any value that matches all of
+// the given matchers.
+TEST(AllOfTest, MatchesWhenAllMatch) {
+  Matcher<int> m;
+  m = AllOf(Le(2), Ge(1));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(0));
+  EXPECT_FALSE(m.Matches(3));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2), Ne(3));
+  EXPECT_TRUE(m.Matches(4));
+  EXPECT_FALSE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AllOf(Ge(0), Lt(10), Ne(3), Ne(5), Ne(7));
+  EXPECT_TRUE(m.Matches(0));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(3));
+
+  // The following tests for varying number of sub-matchers. Due to the way
+  // the sub-matchers are handled it is enough to test every sub-matcher once
+  // with sub-matchers using the same matcher type. Varying matcher types are
+  // checked for above.
+  AllOfMatches(2, AllOf(Ne(1), Ne(2)));
+  AllOfMatches(3, AllOf(Ne(1), Ne(2), Ne(3)));
+  AllOfMatches(4, AllOf(Ne(1), Ne(2), Ne(3), Ne(4)));
+  AllOfMatches(5, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5)));
+  AllOfMatches(6, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6)));
+  AllOfMatches(7, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7)));
+  AllOfMatches(8,
+               AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8)));
+  AllOfMatches(
+      9, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), Ne(9)));
+  AllOfMatches(10, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8),
+                         Ne(9), Ne(10)));
+  AllOfMatches(
+      50, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), Ne(9),
+                Ne(10), Ne(11), Ne(12), Ne(13), Ne(14), Ne(15), Ne(16), Ne(17),
+                Ne(18), Ne(19), Ne(20), Ne(21), Ne(22), Ne(23), Ne(24), Ne(25),
+                Ne(26), Ne(27), Ne(28), Ne(29), Ne(30), Ne(31), Ne(32), Ne(33),
+                Ne(34), Ne(35), Ne(36), Ne(37), Ne(38), Ne(39), Ne(40), Ne(41),
+                Ne(42), Ne(43), Ne(44), Ne(45), Ne(46), Ne(47), Ne(48), Ne(49),
+                Ne(50)));
+}
+
+// Tests that AllOf(m1, ..., mn) describes itself properly.
+TEST(AllOfTest, CanDescribeSelf) {
+  Matcher<int> m;
+  m = AllOf(Le(2), Ge(1));
+  EXPECT_EQ("(is <= 2) and (is >= 1)", Describe(m));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2));
+  std::string expected_descr1 =
+      "(is > 0) and (isn't equal to 1) and (isn't equal to 2)";
+  EXPECT_EQ(expected_descr1, Describe(m));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2), Ne(3));
+  std::string expected_descr2 =
+      "(is > 0) and (isn't equal to 1) and (isn't equal to 2) and (isn't equal "
+      "to 3)";
+  EXPECT_EQ(expected_descr2, Describe(m));
+
+  m = AllOf(Ge(0), Lt(10), Ne(3), Ne(5), Ne(7));
+  std::string expected_descr3 =
+      "(is >= 0) and (is < 10) and (isn't equal to 3) and (isn't equal to 5) "
+      "and (isn't equal to 7)";
+  EXPECT_EQ(expected_descr3, Describe(m));
+}
+
+// Tests that AllOf(m1, ..., mn) describes its negation properly.
+TEST(AllOfTest, CanDescribeNegation) {
+  Matcher<int> m;
+  m = AllOf(Le(2), Ge(1));
+  std::string expected_descr4 = "(isn't <= 2) or (isn't >= 1)";
+  EXPECT_EQ(expected_descr4, DescribeNegation(m));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2));
+  std::string expected_descr5 =
+      "(isn't > 0) or (is equal to 1) or (is equal to 2)";
+  EXPECT_EQ(expected_descr5, DescribeNegation(m));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2), Ne(3));
+  std::string expected_descr6 =
+      "(isn't > 0) or (is equal to 1) or (is equal to 2) or (is equal to 3)";
+  EXPECT_EQ(expected_descr6, DescribeNegation(m));
+
+  m = AllOf(Ge(0), Lt(10), Ne(3), Ne(5), Ne(7));
+  std::string expected_desr7 =
+      "(isn't >= 0) or (isn't < 10) or (is equal to 3) or (is equal to 5) or "
+      "(is equal to 7)";
+  EXPECT_EQ(expected_desr7, DescribeNegation(m));
+
+  m = AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), Ne(9),
+            Ne(10), Ne(11));
+  AllOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+  EXPECT_THAT(Describe(m), EndsWith("and (isn't equal to 11)"));
+  AllOfMatches(11, m);
+}
+
+// Tests that monomorphic matchers are safely cast by the AllOf matcher.
+TEST(AllOfTest, AllOfMatcherSafelyCastsMonomorphicMatchers) {
+  // greater_than_5 and less_than_10 are monomorphic matchers.
+  Matcher<int> greater_than_5 = Gt(5);
+  Matcher<int> less_than_10 = Lt(10);
+
+  Matcher<const int&> m = AllOf(greater_than_5, less_than_10);
+  Matcher<int&> m2 = AllOf(greater_than_5, less_than_10);
+  Matcher<int&> m3 = AllOf(greater_than_5, m2);
+
+  // Tests that BothOf works when composing itself.
+  Matcher<const int&> m4 = AllOf(greater_than_5, less_than_10, less_than_10);
+  Matcher<int&> m5 = AllOf(greater_than_5, less_than_10, less_than_10);
+}
+
+TEST_P(AllOfTestP, ExplainsResult) {
+  Matcher<int> m;
+
+  // Successful match.  Both matchers need to explain.  The second
+  // matcher doesn't give an explanation, so the matcher description is used.
+  m = AllOf(GreaterThan(10), Lt(30));
+  EXPECT_EQ("which is 15 more than 10, and is < 30", Explain(m, 25));
+
+  // Successful match.  Both matchers need to explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 20 more than 10, and which is 10 more than 20",
+            Explain(m, 30));
+
+  // Successful match.  All matchers need to explain.  The second
+  // matcher doesn't given an explanation.
+  m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
+  EXPECT_EQ(
+      "which is 15 more than 10, and is < 30, and which is 5 more than 20",
+      Explain(m, 25));
+
+  // Successful match.  All matchers need to explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
+  EXPECT_EQ(
+      "which is 30 more than 10, and which is 20 more than 20, "
+      "and which is 10 more than 30",
+      Explain(m, 40));
+
+  // Failed match.  The first matcher, which failed, needs to
+  // explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
+
+  // Failed match.  The second matcher, which failed, needs to
+  // explain.  Since it doesn't given an explanation, the matcher text is
+  // printed.
+  m = AllOf(GreaterThan(10), Lt(30));
+  EXPECT_EQ("which doesn't match (is < 30)", Explain(m, 40));
+
+  // Failed match.  The second matcher, which failed, needs to
+  // explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 less than 20", Explain(m, 15));
+}
+
+// Helper to allow easy testing of AnyOf matchers with num parameters.
+static void AnyOfMatches(int num, const Matcher<int>& m) {
+  SCOPED_TRACE(Describe(m));
+  EXPECT_FALSE(m.Matches(0));
+  for (int i = 1; i <= num; ++i) {
+    EXPECT_TRUE(m.Matches(i));
+  }
+  EXPECT_FALSE(m.Matches(num + 1));
+}
+
+static void AnyOfStringMatches(int num, const Matcher<std::string>& m) {
+  SCOPED_TRACE(Describe(m));
+  EXPECT_FALSE(m.Matches(std::to_string(0)));
+
+  for (int i = 1; i <= num; ++i) {
+    EXPECT_TRUE(m.Matches(std::to_string(i)));
+  }
+  EXPECT_FALSE(m.Matches(std::to_string(num + 1)));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(AnyOfTest);
+
+// Tests that AnyOf(m1, ..., mn) matches any value that matches at
+// least one of the given matchers.
+TEST(AnyOfTest, MatchesWhenAnyMatches) {
+  Matcher<int> m;
+  m = AnyOf(Le(1), Ge(3));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(4));
+  EXPECT_FALSE(m.Matches(2));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2));
+  EXPECT_TRUE(m.Matches(-1));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2), Eq(3));
+  EXPECT_TRUE(m.Matches(-1));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AnyOf(Le(0), Gt(10), 3, 5, 7);
+  EXPECT_TRUE(m.Matches(0));
+  EXPECT_TRUE(m.Matches(11));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+
+  // The following tests for varying number of sub-matchers. Due to the way
+  // the sub-matchers are handled it is enough to test every sub-matcher once
+  // with sub-matchers using the same matcher type. Varying matcher types are
+  // checked for above.
+  AnyOfMatches(2, AnyOf(1, 2));
+  AnyOfMatches(3, AnyOf(1, 2, 3));
+  AnyOfMatches(4, AnyOf(1, 2, 3, 4));
+  AnyOfMatches(5, AnyOf(1, 2, 3, 4, 5));
+  AnyOfMatches(6, AnyOf(1, 2, 3, 4, 5, 6));
+  AnyOfMatches(7, AnyOf(1, 2, 3, 4, 5, 6, 7));
+  AnyOfMatches(8, AnyOf(1, 2, 3, 4, 5, 6, 7, 8));
+  AnyOfMatches(9, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9));
+  AnyOfMatches(10, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+}
+
+// Tests the variadic version of the AnyOfMatcher.
+TEST(AnyOfTest, VariadicMatchesWhenAnyMatches) {
+  // Also make sure AnyOf is defined in the right namespace and does not depend
+  // on ADL.
+  Matcher<int> m = ::testing::AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+
+  EXPECT_THAT(Describe(m), EndsWith("or (is equal to 11)"));
+  AnyOfMatches(11, m);
+  AnyOfMatches(50, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+                         31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+                         45, 46, 47, 48, 49, 50));
+  AnyOfStringMatches(
+      50, AnyOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
+                "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
+                "23", "24", "25", "26", "27", "28", "29", "30", "31", "32",
+                "33", "34", "35", "36", "37", "38", "39", "40", "41", "42",
+                "43", "44", "45", "46", "47", "48", "49", "50"));
+}
+
+TEST(ConditionalTest, MatchesFirstIfCondition) {
+  Matcher<std::string> eq_red = Eq("red");
+  Matcher<std::string> ne_red = Ne("red");
+  Matcher<std::string> m = Conditional(true, eq_red, ne_red);
+  EXPECT_TRUE(m.Matches("red"));
+  EXPECT_FALSE(m.Matches("green"));
+
+  StringMatchResultListener listener;
+  StringMatchResultListener expected;
+  EXPECT_FALSE(m.MatchAndExplain("green", &listener));
+  EXPECT_FALSE(eq_red.MatchAndExplain("green", &expected));
+  EXPECT_THAT(listener.str(), Eq(expected.str()));
+}
+
+TEST(ConditionalTest, MatchesSecondIfCondition) {
+  Matcher<std::string> eq_red = Eq("red");
+  Matcher<std::string> ne_red = Ne("red");
+  Matcher<std::string> m = Conditional(false, eq_red, ne_red);
+  EXPECT_FALSE(m.Matches("red"));
+  EXPECT_TRUE(m.Matches("green"));
+
+  StringMatchResultListener listener;
+  StringMatchResultListener expected;
+  EXPECT_FALSE(m.MatchAndExplain("red", &listener));
+  EXPECT_FALSE(ne_red.MatchAndExplain("red", &expected));
+  EXPECT_THAT(listener.str(), Eq(expected.str()));
+}
+
+// Tests that AnyOf(m1, ..., mn) describes itself properly.
+TEST(AnyOfTest, CanDescribeSelf) {
+  Matcher<int> m;
+  m = AnyOf(Le(1), Ge(3));
+
+  EXPECT_EQ("(is <= 1) or (is >= 3)", Describe(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2));
+  EXPECT_EQ("(is < 0) or (is equal to 1) or (is equal to 2)", Describe(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2), Eq(3));
+  EXPECT_EQ("(is < 0) or (is equal to 1) or (is equal to 2) or (is equal to 3)",
+            Describe(m));
+
+  m = AnyOf(Le(0), Gt(10), 3, 5, 7);
+  EXPECT_EQ(
+      "(is <= 0) or (is > 10) or (is equal to 3) or (is equal to 5) or (is "
+      "equal to 7)",
+      Describe(m));
+}
+
+// Tests that AnyOf(m1, ..., mn) describes its negation properly.
+TEST(AnyOfTest, CanDescribeNegation) {
+  Matcher<int> m;
+  m = AnyOf(Le(1), Ge(3));
+  EXPECT_EQ("(isn't <= 1) and (isn't >= 3)", DescribeNegation(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2));
+  EXPECT_EQ("(isn't < 0) and (isn't equal to 1) and (isn't equal to 2)",
+            DescribeNegation(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2), Eq(3));
+  EXPECT_EQ(
+      "(isn't < 0) and (isn't equal to 1) and (isn't equal to 2) and (isn't "
+      "equal to 3)",
+      DescribeNegation(m));
+
+  m = AnyOf(Le(0), Gt(10), 3, 5, 7);
+  EXPECT_EQ(
+      "(isn't <= 0) and (isn't > 10) and (isn't equal to 3) and (isn't equal "
+      "to 5) and (isn't equal to 7)",
+      DescribeNegation(m));
+}
+
+// Tests that monomorphic matchers are safely cast by the AnyOf matcher.
+TEST(AnyOfTest, AnyOfMatcherSafelyCastsMonomorphicMatchers) {
+  // greater_than_5 and less_than_10 are monomorphic matchers.
+  Matcher<int> greater_than_5 = Gt(5);
+  Matcher<int> less_than_10 = Lt(10);
+
+  Matcher<const int&> m = AnyOf(greater_than_5, less_than_10);
+  Matcher<int&> m2 = AnyOf(greater_than_5, less_than_10);
+  Matcher<int&> m3 = AnyOf(greater_than_5, m2);
+
+  // Tests that EitherOf works when composing itself.
+  Matcher<const int&> m4 = AnyOf(greater_than_5, less_than_10, less_than_10);
+  Matcher<int&> m5 = AnyOf(greater_than_5, less_than_10, less_than_10);
+}
+
+TEST_P(AnyOfTestP, ExplainsResult) {
+  Matcher<int> m;
+
+  // Failed match.  Both matchers need to explain.  The second
+  // matcher doesn't give an explanation, so only the first matcher's
+  // explanation is printed.
+  m = AnyOf(GreaterThan(10), Lt(0));
+  EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
+
+  // Failed match.  Both matchers need to explain.
+  m = AnyOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
+            Explain(m, 5));
+
+  // Failed match.  All matchers need to explain.  The second
+  // matcher doesn't given an explanation.
+  m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
+  EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30",
+            Explain(m, 5));
+
+  // Failed match.  All matchers need to explain.
+  m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
+  EXPECT_EQ(
+      "which is 5 less than 10, and which is 15 less than 20, "
+      "and which is 25 less than 30",
+      Explain(m, 5));
+
+  // Successful match.  The first matcher, which succeeded, needs to
+  // explain.
+  m = AnyOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
+
+  // Successful match.  The second matcher, which succeeded, needs to
+  // explain.  Since it doesn't given an explanation, nothing is
+  // printed.
+  m = AnyOf(GreaterThan(10), Lt(30));
+  EXPECT_EQ("", Explain(m, 0));
+
+  // Successful match.  The second matcher, which succeeded, needs to
+  // explain.
+  m = AnyOf(GreaterThan(30), GreaterThan(20));
+  EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
+}
+
+// The following predicate function and predicate functor are for
+// testing the Truly(predicate) matcher.
+
+// Returns non-zero if the input is positive.  Note that the return
+// type of this function is not bool.  It's OK as Truly() accepts any
+// unary function or functor whose return type can be implicitly
+// converted to bool.
+int IsPositive(double x) { return x > 0 ? 1 : 0; }
+
+// This functor returns true if the input is greater than the given
+// number.
+class IsGreaterThan {
+ public:
+  explicit IsGreaterThan(int threshold) : threshold_(threshold) {}
+
+  bool operator()(int n) const { return n > threshold_; }
+
+ private:
+  int threshold_;
+};
+
+// For testing Truly().
+const int foo = 0;
+
+// This predicate returns true if and only if the argument references foo and
+// has a zero value.
+bool ReferencesFooAndIsZero(const int& n) { return (&n == &foo) && (n == 0); }
+
+// Tests that Truly(predicate) matches what satisfies the given
+// predicate.
+TEST(TrulyTest, MatchesWhatSatisfiesThePredicate) {
+  Matcher<double> m = Truly(IsPositive);
+  EXPECT_TRUE(m.Matches(2.0));
+  EXPECT_FALSE(m.Matches(-1.5));
+}
+
+// Tests that Truly(predicate_functor) works too.
+TEST(TrulyTest, CanBeUsedWithFunctor) {
+  Matcher<int> m = Truly(IsGreaterThan(5));
+  EXPECT_TRUE(m.Matches(6));
+  EXPECT_FALSE(m.Matches(4));
+}
+
+// A class that can be implicitly converted to bool.
+class ConvertibleToBool {
+ public:
+  explicit ConvertibleToBool(int number) : number_(number) {}
+  operator bool() const { return number_ != 0; }
+
+ private:
+  int number_;
+};
+
+ConvertibleToBool IsNotZero(int number) { return ConvertibleToBool(number); }
+
+// Tests that the predicate used in Truly() may return a class that's
+// implicitly convertible to bool, even when the class has no
+// operator!().
+TEST(TrulyTest, PredicateCanReturnAClassConvertibleToBool) {
+  Matcher<int> m = Truly(IsNotZero);
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(0));
+}
+
+// Tests that Truly(predicate) can describe itself properly.
+TEST(TrulyTest, CanDescribeSelf) {
+  Matcher<double> m = Truly(IsPositive);
+  EXPECT_EQ("satisfies the given predicate", Describe(m));
+}
+
+// Tests that Truly(predicate) works when the matcher takes its
+// argument by reference.
+TEST(TrulyTest, WorksForByRefArguments) {
+  Matcher<const int&> m = Truly(ReferencesFooAndIsZero);
+  EXPECT_TRUE(m.Matches(foo));
+  int n = 0;
+  EXPECT_FALSE(m.Matches(n));
+}
+
+// Tests that Truly(predicate) provides a helpful reason when it fails.
+TEST(TrulyTest, ExplainsFailures) {
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(Truly(IsPositive), -1, &listener));
+  EXPECT_EQ(listener.str(), "didn't satisfy the given predicate");
+}
+
+// Tests that Matches(m) is a predicate satisfied by whatever that
+// matches matcher m.
+TEST(MatchesTest, IsSatisfiedByWhatMatchesTheMatcher) {
+  EXPECT_TRUE(Matches(Ge(0))(1));
+  EXPECT_FALSE(Matches(Eq('a'))('b'));
+}
+
+// Tests that Matches(m) works when the matcher takes its argument by
+// reference.
+TEST(MatchesTest, WorksOnByRefArguments) {
+  int m = 0, n = 0;
+  EXPECT_TRUE(Matches(AllOf(Ref(n), Eq(0)))(n));
+  EXPECT_FALSE(Matches(Ref(m))(n));
+}
+
+// Tests that a Matcher on non-reference type can be used in
+// Matches().
+TEST(MatchesTest, WorksWithMatcherOnNonRefType) {
+  Matcher<int> eq5 = Eq(5);
+  EXPECT_TRUE(Matches(eq5)(5));
+  EXPECT_FALSE(Matches(eq5)(2));
+}
+
+// Tests Value(value, matcher).  Since Value() is a simple wrapper for
+// Matches(), which has been tested already, we don't spend a lot of
+// effort on testing Value().
+TEST(ValueTest, WorksWithPolymorphicMatcher) {
+  EXPECT_TRUE(Value("hi", StartsWith("h")));
+  EXPECT_FALSE(Value(5, Gt(10)));
+}
+
+TEST(ValueTest, WorksWithMonomorphicMatcher) {
+  const Matcher<int> is_zero = Eq(0);
+  EXPECT_TRUE(Value(0, is_zero));
+  EXPECT_FALSE(Value('a', is_zero));
+
+  int n = 0;
+  const Matcher<const int&> ref_n = Ref(n);
+  EXPECT_TRUE(Value(n, ref_n));
+  EXPECT_FALSE(Value(1, ref_n));
+}
+
+TEST(AllArgsTest, WorksForTuple) {
+  EXPECT_THAT(std::make_tuple(1, 2L), AllArgs(Lt()));
+  EXPECT_THAT(std::make_tuple(2L, 1), Not(AllArgs(Lt())));
+}
+
+TEST(AllArgsTest, WorksForNonTuple) {
+  EXPECT_THAT(42, AllArgs(Gt(0)));
+  EXPECT_THAT('a', Not(AllArgs(Eq('b'))));
+}
+
+class AllArgsHelper {
+ public:
+  AllArgsHelper() = default;
+
+  MOCK_METHOD2(Helper, int(char x, int y));
+
+ private:
+  AllArgsHelper(const AllArgsHelper&) = delete;
+  AllArgsHelper& operator=(const AllArgsHelper&) = delete;
+};
+
+TEST(AllArgsTest, WorksInWithClause) {
+  AllArgsHelper helper;
+  ON_CALL(helper, Helper(_, _)).With(AllArgs(Lt())).WillByDefault(Return(1));
+  EXPECT_CALL(helper, Helper(_, _));
+  EXPECT_CALL(helper, Helper(_, _)).With(AllArgs(Gt())).WillOnce(Return(2));
+
+  EXPECT_EQ(1, helper.Helper('\1', 2));
+  EXPECT_EQ(2, helper.Helper('a', 1));
+}
+
+class OptionalMatchersHelper {
+ public:
+  OptionalMatchersHelper() = default;
+
+  MOCK_METHOD0(NoArgs, int());
+
+  MOCK_METHOD1(OneArg, int(int y));
+
+  MOCK_METHOD2(TwoArgs, int(char x, int y));
+
+  MOCK_METHOD1(Overloaded, int(char x));
+  MOCK_METHOD2(Overloaded, int(char x, int y));
+
+ private:
+  OptionalMatchersHelper(const OptionalMatchersHelper&) = delete;
+  OptionalMatchersHelper& operator=(const OptionalMatchersHelper&) = delete;
+};
+
+TEST(AllArgsTest, WorksWithoutMatchers) {
+  OptionalMatchersHelper helper;
+
+  ON_CALL(helper, NoArgs).WillByDefault(Return(10));
+  ON_CALL(helper, OneArg).WillByDefault(Return(20));
+  ON_CALL(helper, TwoArgs).WillByDefault(Return(30));
+
+  EXPECT_EQ(10, helper.NoArgs());
+  EXPECT_EQ(20, helper.OneArg(1));
+  EXPECT_EQ(30, helper.TwoArgs('\1', 2));
+
+  EXPECT_CALL(helper, NoArgs).Times(1);
+  EXPECT_CALL(helper, OneArg).WillOnce(Return(100));
+  EXPECT_CALL(helper, OneArg(17)).WillOnce(Return(200));
+  EXPECT_CALL(helper, TwoArgs).Times(0);
+
+  EXPECT_EQ(10, helper.NoArgs());
+  EXPECT_EQ(100, helper.OneArg(1));
+  EXPECT_EQ(200, helper.OneArg(17));
+}
+
+// Tests floating-point matchers.
+template <typename RawType>
+class FloatingPointTest : public testing::Test {
+ protected:
+  typedef testing::internal::FloatingPoint<RawType> Floating;
+  typedef typename Floating::Bits Bits;
+
+  FloatingPointTest()
+      : max_ulps_(Floating::kMaxUlps),
+        zero_bits_(Floating(0).bits()),
+        one_bits_(Floating(1).bits()),
+        infinity_bits_(Floating(Floating::Infinity()).bits()),
+        close_to_positive_zero_(
+            Floating::ReinterpretBits(zero_bits_ + max_ulps_ / 2)),
+        close_to_negative_zero_(
+            -Floating::ReinterpretBits(zero_bits_ + max_ulps_ - max_ulps_ / 2)),
+        further_from_negative_zero_(-Floating::ReinterpretBits(
+            zero_bits_ + max_ulps_ + 1 - max_ulps_ / 2)),
+        close_to_one_(Floating::ReinterpretBits(one_bits_ + max_ulps_)),
+        further_from_one_(Floating::ReinterpretBits(one_bits_ + max_ulps_ + 1)),
+        infinity_(Floating::Infinity()),
+        close_to_infinity_(
+            Floating::ReinterpretBits(infinity_bits_ - max_ulps_)),
+        further_from_infinity_(
+            Floating::ReinterpretBits(infinity_bits_ - max_ulps_ - 1)),
+        max_(std::numeric_limits<RawType>::max()),
+        nan1_(Floating::ReinterpretBits(Floating::kExponentBitMask | 1)),
+        nan2_(Floating::ReinterpretBits(Floating::kExponentBitMask | 200)) {}
+
+  void TestSize() { EXPECT_EQ(sizeof(RawType), sizeof(Bits)); }
+
+  // A battery of tests for FloatingEqMatcher::Matches.
+  // matcher_maker is a pointer to a function which creates a FloatingEqMatcher.
+  void TestMatches(
+      testing::internal::FloatingEqMatcher<RawType> (*matcher_maker)(RawType)) {
+    Matcher<RawType> m1 = matcher_maker(0.0);
+    EXPECT_TRUE(m1.Matches(-0.0));
+    EXPECT_TRUE(m1.Matches(close_to_positive_zero_));
+    EXPECT_TRUE(m1.Matches(close_to_negative_zero_));
+    EXPECT_FALSE(m1.Matches(1.0));
+
+    Matcher<RawType> m2 = matcher_maker(close_to_positive_zero_);
+    EXPECT_FALSE(m2.Matches(further_from_negative_zero_));
+
+    Matcher<RawType> m3 = matcher_maker(1.0);
+    EXPECT_TRUE(m3.Matches(close_to_one_));
+    EXPECT_FALSE(m3.Matches(further_from_one_));
+
+    // Test commutativity: matcher_maker(0.0).Matches(1.0) was tested above.
+    EXPECT_FALSE(m3.Matches(0.0));
+
+    Matcher<RawType> m4 = matcher_maker(-infinity_);
+    EXPECT_TRUE(m4.Matches(-close_to_infinity_));
+
+    Matcher<RawType> m5 = matcher_maker(infinity_);
+    EXPECT_TRUE(m5.Matches(close_to_infinity_));
+
+    // This is interesting as the representations of infinity_ and nan1_
+    // are only 1 DLP apart.
+    EXPECT_FALSE(m5.Matches(nan1_));
+
+    // matcher_maker can produce a Matcher<const RawType&>, which is needed in
+    // some cases.
+    Matcher<const RawType&> m6 = matcher_maker(0.0);
+    EXPECT_TRUE(m6.Matches(-0.0));
+    EXPECT_TRUE(m6.Matches(close_to_positive_zero_));
+    EXPECT_FALSE(m6.Matches(1.0));
+
+    // matcher_maker can produce a Matcher<RawType&>, which is needed in some
+    // cases.
+    Matcher<RawType&> m7 = matcher_maker(0.0);
+    RawType x = 0.0;
+    EXPECT_TRUE(m7.Matches(x));
+    x = 0.01f;
+    EXPECT_FALSE(m7.Matches(x));
+  }
+
+  // Pre-calculated numbers to be used by the tests.
+
+  const Bits max_ulps_;
+
+  const Bits zero_bits_;      // The bits that represent 0.0.
+  const Bits one_bits_;       // The bits that represent 1.0.
+  const Bits infinity_bits_;  // The bits that represent +infinity.
+
+  // Some numbers close to 0.0.
+  const RawType close_to_positive_zero_;
+  const RawType close_to_negative_zero_;
+  const RawType further_from_negative_zero_;
+
+  // Some numbers close to 1.0.
+  const RawType close_to_one_;
+  const RawType further_from_one_;
+
+  // Some numbers close to +infinity.
+  const RawType infinity_;
+  const RawType close_to_infinity_;
+  const RawType further_from_infinity_;
+
+  // Maximum representable value that's not infinity.
+  const RawType max_;
+
+  // Some NaNs.
+  const RawType nan1_;
+  const RawType nan2_;
+};
+
+// Tests floating-point matchers with fixed epsilons.
+template <typename RawType>
+class FloatingPointNearTest : public FloatingPointTest<RawType> {
+ protected:
+  typedef FloatingPointTest<RawType> ParentType;
+
+  // A battery of tests for FloatingEqMatcher::Matches with a fixed epsilon.
+  // matcher_maker is a pointer to a function which creates a FloatingEqMatcher.
+  void TestNearMatches(testing::internal::FloatingEqMatcher<RawType> (
+      *matcher_maker)(RawType, RawType)) {
+    Matcher<RawType> m1 = matcher_maker(0.0, 0.0);
+    EXPECT_TRUE(m1.Matches(0.0));
+    EXPECT_TRUE(m1.Matches(-0.0));
+    EXPECT_FALSE(m1.Matches(ParentType::close_to_positive_zero_));
+    EXPECT_FALSE(m1.Matches(ParentType::close_to_negative_zero_));
+    EXPECT_FALSE(m1.Matches(1.0));
+
+    Matcher<RawType> m2 = matcher_maker(0.0, 1.0);
+    EXPECT_TRUE(m2.Matches(0.0));
+    EXPECT_TRUE(m2.Matches(-0.0));
+    EXPECT_TRUE(m2.Matches(1.0));
+    EXPECT_TRUE(m2.Matches(-1.0));
+    EXPECT_FALSE(m2.Matches(ParentType::close_to_one_));
+    EXPECT_FALSE(m2.Matches(-ParentType::close_to_one_));
+
+    // Check that inf matches inf, regardless of the of the specified max
+    // absolute error.
+    Matcher<RawType> m3 = matcher_maker(ParentType::infinity_, 0.0);
+    EXPECT_TRUE(m3.Matches(ParentType::infinity_));
+    EXPECT_FALSE(m3.Matches(ParentType::close_to_infinity_));
+    EXPECT_FALSE(m3.Matches(-ParentType::infinity_));
+
+    Matcher<RawType> m4 = matcher_maker(-ParentType::infinity_, 0.0);
+    EXPECT_TRUE(m4.Matches(-ParentType::infinity_));
+    EXPECT_FALSE(m4.Matches(-ParentType::close_to_infinity_));
+    EXPECT_FALSE(m4.Matches(ParentType::infinity_));
+
+    // Test various overflow scenarios.
+    Matcher<RawType> m5 = matcher_maker(ParentType::max_, ParentType::max_);
+    EXPECT_TRUE(m5.Matches(ParentType::max_));
+    EXPECT_FALSE(m5.Matches(-ParentType::max_));
+
+    Matcher<RawType> m6 = matcher_maker(-ParentType::max_, ParentType::max_);
+    EXPECT_FALSE(m6.Matches(ParentType::max_));
+    EXPECT_TRUE(m6.Matches(-ParentType::max_));
+
+    Matcher<RawType> m7 = matcher_maker(ParentType::max_, 0);
+    EXPECT_TRUE(m7.Matches(ParentType::max_));
+    EXPECT_FALSE(m7.Matches(-ParentType::max_));
+
+    Matcher<RawType> m8 = matcher_maker(-ParentType::max_, 0);
+    EXPECT_FALSE(m8.Matches(ParentType::max_));
+    EXPECT_TRUE(m8.Matches(-ParentType::max_));
+
+    // The difference between max() and -max() normally overflows to infinity,
+    // but it should still match if the max_abs_error is also infinity.
+    Matcher<RawType> m9 =
+        matcher_maker(ParentType::max_, ParentType::infinity_);
+    EXPECT_TRUE(m8.Matches(-ParentType::max_));
+
+    // matcher_maker can produce a Matcher<const RawType&>, which is needed in
+    // some cases.
+    Matcher<const RawType&> m10 = matcher_maker(0.0, 1.0);
+    EXPECT_TRUE(m10.Matches(-0.0));
+    EXPECT_TRUE(m10.Matches(ParentType::close_to_positive_zero_));
+    EXPECT_FALSE(m10.Matches(ParentType::close_to_one_));
+
+    // matcher_maker can produce a Matcher<RawType&>, which is needed in some
+    // cases.
+    Matcher<RawType&> m11 = matcher_maker(0.0, 1.0);
+    RawType x = 0.0;
+    EXPECT_TRUE(m11.Matches(x));
+    x = 1.0f;
+    EXPECT_TRUE(m11.Matches(x));
+    x = -1.0f;
+    EXPECT_TRUE(m11.Matches(x));
+    x = 1.1f;
+    EXPECT_FALSE(m11.Matches(x));
+    x = -1.1f;
+    EXPECT_FALSE(m11.Matches(x));
+  }
+};
+
+// Instantiate FloatingPointTest for testing floats.
+typedef FloatingPointTest<float> FloatTest;
+
+TEST_F(FloatTest, FloatEqApproximatelyMatchesFloats) { TestMatches(&FloatEq); }
+
+TEST_F(FloatTest, NanSensitiveFloatEqApproximatelyMatchesFloats) {
+  TestMatches(&NanSensitiveFloatEq);
+}
+
+TEST_F(FloatTest, FloatEqCannotMatchNaN) {
+  // FloatEq never matches NaN.
+  Matcher<float> m = FloatEq(nan1_);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(FloatTest, NanSensitiveFloatEqCanMatchNaN) {
+  // NanSensitiveFloatEq will match NaN.
+  Matcher<float> m = NanSensitiveFloatEq(nan1_);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(FloatTest, FloatEqCanDescribeSelf) {
+  Matcher<float> m1 = FloatEq(2.0f);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<float> m2 = FloatEq(0.5f);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<float> m3 = FloatEq(nan1_);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(FloatTest, NanSensitiveFloatEqCanDescribeSelf) {
+  Matcher<float> m1 = NanSensitiveFloatEq(2.0f);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<float> m2 = NanSensitiveFloatEq(0.5f);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<float> m3 = NanSensitiveFloatEq(nan1_);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+// Instantiate FloatingPointTest for testing floats with a user-specified
+// max absolute error.
+typedef FloatingPointNearTest<float> FloatNearTest;
+
+TEST_F(FloatNearTest, FloatNearMatches) { TestNearMatches(&FloatNear); }
+
+TEST_F(FloatNearTest, NanSensitiveFloatNearApproximatelyMatchesFloats) {
+  TestNearMatches(&NanSensitiveFloatNear);
+}
+
+TEST_F(FloatNearTest, FloatNearCanDescribeSelf) {
+  Matcher<float> m1 = FloatNear(2.0f, 0.5f);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ("isn't approximately 2 (absolute error > 0.5)",
+            DescribeNegation(m1));
+
+  Matcher<float> m2 = FloatNear(0.5f, 0.5f);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5 (absolute error > 0.5)",
+            DescribeNegation(m2));
+
+  Matcher<float> m3 = FloatNear(nan1_, 0.0);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(FloatNearTest, NanSensitiveFloatNearCanDescribeSelf) {
+  Matcher<float> m1 = NanSensitiveFloatNear(2.0f, 0.5f);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ("isn't approximately 2 (absolute error > 0.5)",
+            DescribeNegation(m1));
+
+  Matcher<float> m2 = NanSensitiveFloatNear(0.5f, 0.5f);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5 (absolute error > 0.5)",
+            DescribeNegation(m2));
+
+  Matcher<float> m3 = NanSensitiveFloatNear(nan1_, 0.1f);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+TEST_F(FloatNearTest, FloatNearCannotMatchNaN) {
+  // FloatNear never matches NaN.
+  Matcher<float> m = FloatNear(ParentType::nan1_, 0.1f);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(FloatNearTest, NanSensitiveFloatNearCanMatchNaN) {
+  // NanSensitiveFloatNear will match NaN.
+  Matcher<float> m = NanSensitiveFloatNear(nan1_, 0.1f);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+// Instantiate FloatingPointTest for testing doubles.
+typedef FloatingPointTest<double> DoubleTest;
+
+TEST_F(DoubleTest, DoubleEqApproximatelyMatchesDoubles) {
+  TestMatches(&DoubleEq);
+}
+
+TEST_F(DoubleTest, NanSensitiveDoubleEqApproximatelyMatchesDoubles) {
+  TestMatches(&NanSensitiveDoubleEq);
+}
+
+TEST_F(DoubleTest, DoubleEqCannotMatchNaN) {
+  // DoubleEq never matches NaN.
+  Matcher<double> m = DoubleEq(nan1_);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(DoubleTest, NanSensitiveDoubleEqCanMatchNaN) {
+  // NanSensitiveDoubleEq will match NaN.
+  Matcher<double> m = NanSensitiveDoubleEq(nan1_);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(DoubleTest, DoubleEqCanDescribeSelf) {
+  Matcher<double> m1 = DoubleEq(2.0);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<double> m2 = DoubleEq(0.5);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<double> m3 = DoubleEq(nan1_);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(DoubleTest, NanSensitiveDoubleEqCanDescribeSelf) {
+  Matcher<double> m1 = NanSensitiveDoubleEq(2.0);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<double> m2 = NanSensitiveDoubleEq(0.5);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<double> m3 = NanSensitiveDoubleEq(nan1_);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+// Instantiate FloatingPointTest for testing floats with a user-specified
+// max absolute error.
+typedef FloatingPointNearTest<double> DoubleNearTest;
+
+TEST_F(DoubleNearTest, DoubleNearMatches) { TestNearMatches(&DoubleNear); }
+
+TEST_F(DoubleNearTest, NanSensitiveDoubleNearApproximatelyMatchesDoubles) {
+  TestNearMatches(&NanSensitiveDoubleNear);
+}
+
+TEST_F(DoubleNearTest, DoubleNearCanDescribeSelf) {
+  Matcher<double> m1 = DoubleNear(2.0, 0.5);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ("isn't approximately 2 (absolute error > 0.5)",
+            DescribeNegation(m1));
+
+  Matcher<double> m2 = DoubleNear(0.5, 0.5);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5 (absolute error > 0.5)",
+            DescribeNegation(m2));
+
+  Matcher<double> m3 = DoubleNear(nan1_, 0.0);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(DoubleNearTest, ExplainsResultWhenMatchFails) {
+  EXPECT_EQ("", Explain(DoubleNear(2.0, 0.1), 2.05));
+  EXPECT_EQ("which is 0.2 from 2", Explain(DoubleNear(2.0, 0.1), 2.2));
+  EXPECT_EQ("which is -0.3 from 2", Explain(DoubleNear(2.0, 0.1), 1.7));
+
+  const std::string explanation =
+      Explain(DoubleNear(2.1, 1e-10), 2.1 + 1.2e-10);
+  // Different C++ implementations may print floating-point numbers
+  // slightly differently.
+  EXPECT_TRUE(explanation == "which is 1.2e-10 from 2.1" ||  // GCC
+              explanation == "which is 1.2e-010 from 2.1")   // MSVC
+      << " where explanation is \"" << explanation << "\".";
+}
+
+TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanDescribeSelf) {
+  Matcher<double> m1 = NanSensitiveDoubleNear(2.0, 0.5);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ("isn't approximately 2 (absolute error > 0.5)",
+            DescribeNegation(m1));
+
+  Matcher<double> m2 = NanSensitiveDoubleNear(0.5, 0.5);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5 (absolute error > 0.5)",
+            DescribeNegation(m2));
+
+  Matcher<double> m3 = NanSensitiveDoubleNear(nan1_, 0.1);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+TEST_F(DoubleNearTest, DoubleNearCannotMatchNaN) {
+  // DoubleNear never matches NaN.
+  Matcher<double> m = DoubleNear(ParentType::nan1_, 0.1);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanMatchNaN) {
+  // NanSensitiveDoubleNear will match NaN.
+  Matcher<double> m = NanSensitiveDoubleNear(nan1_, 0.1);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST(NotTest, WorksOnMoveOnlyType) {
+  std::unique_ptr<int> p(new int(3));
+  EXPECT_THAT(p, Pointee(Eq(3)));
+  EXPECT_THAT(p, Not(Pointee(Eq(2))));
+}
+
+TEST(AllOfTest, HugeMatcher) {
+  // Verify that using AllOf with many arguments doesn't cause
+  // the compiler to exceed template instantiation depth limit.
+  EXPECT_THAT(0, testing::AllOf(_, _, _, _, _, _, _, _, _,
+                                testing::AllOf(_, _, _, _, _, _, _, _, _, _)));
+}
+
+TEST(AnyOfTest, HugeMatcher) {
+  // Verify that using AnyOf with many arguments doesn't cause
+  // the compiler to exceed template instantiation depth limit.
+  EXPECT_THAT(0, testing::AnyOf(_, _, _, _, _, _, _, _, _,
+                                testing::AnyOf(_, _, _, _, _, _, _, _, _, _)));
+}
+
+namespace adl_test {
+
+// Verifies that the implementation of ::testing::AllOf and ::testing::AnyOf
+// don't issue unqualified recursive calls.  If they do, the argument dependent
+// name lookup will cause AllOf/AnyOf in the 'adl_test' namespace to be found
+// as a candidate and the compilation will break due to an ambiguous overload.
+
+// The matcher must be in the same namespace as AllOf/AnyOf to make argument
+// dependent lookup find those.
+MATCHER(M, "") {
+  (void)arg;
+  return true;
+}
+
+template <typename T1, typename T2>
+bool AllOf(const T1& /*t1*/, const T2& /*t2*/) {
+  return true;
+}
+
+TEST(AllOfTest, DoesNotCallAllOfUnqualified) {
+  EXPECT_THAT(42,
+              testing::AllOf(M(), M(), M(), M(), M(), M(), M(), M(), M(), M()));
+}
+
+template <typename T1, typename T2>
+bool AnyOf(const T1&, const T2&) {
+  return true;
+}
+
+TEST(AnyOfTest, DoesNotCallAnyOfUnqualified) {
+  EXPECT_THAT(42,
+              testing::AnyOf(M(), M(), M(), M(), M(), M(), M(), M(), M(), M()));
+}
+
+}  // namespace adl_test
+
+TEST(AllOfTest, WorksOnMoveOnlyType) {
+  std::unique_ptr<int> p(new int(3));
+  EXPECT_THAT(p, AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(5))));
+  EXPECT_THAT(p, Not(AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(3)))));
+}
+
+TEST(AnyOfTest, WorksOnMoveOnlyType) {
+  std::unique_ptr<int> p(new int(3));
+  EXPECT_THAT(p, AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Lt(5))));
+  EXPECT_THAT(p, Not(AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Gt(5)))));
+}
+
+}  // namespace
+}  // namespace gmock_matchers_test
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4244 4100
diff --git a/3rd-party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc b/3rd-party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc
new file mode 100644
index 0000000..57c675f
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc
@@ -0,0 +1,2371 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests some commonly used argument matchers.
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "test/gmock-matchers_test.h"
+
+// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
+// possible loss of data and C4100, unreferenced local parameter
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
+
+namespace testing {
+namespace gmock_matchers_test {
+namespace {
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(MonotonicMatcherTest);
+
+TEST_P(MonotonicMatcherTestP, IsPrintable) {
+  stringstream ss;
+  ss << GreaterThan(5);
+  EXPECT_EQ("is > 5", ss.str());
+}
+
+TEST(MatchResultListenerTest, StreamingWorks) {
+  StringMatchResultListener listener;
+  listener << "hi" << 5;
+  EXPECT_EQ("hi5", listener.str());
+
+  listener.Clear();
+  EXPECT_EQ("", listener.str());
+
+  listener << 42;
+  EXPECT_EQ("42", listener.str());
+
+  // Streaming shouldn't crash when the underlying ostream is NULL.
+  DummyMatchResultListener dummy;
+  dummy << "hi" << 5;
+}
+
+TEST(MatchResultListenerTest, CanAccessUnderlyingStream) {
+  EXPECT_TRUE(DummyMatchResultListener().stream() == nullptr);
+  EXPECT_TRUE(StreamMatchResultListener(nullptr).stream() == nullptr);
+
+  EXPECT_EQ(&std::cout, StreamMatchResultListener(&std::cout).stream());
+}
+
+TEST(MatchResultListenerTest, IsInterestedWorks) {
+  EXPECT_TRUE(StringMatchResultListener().IsInterested());
+  EXPECT_TRUE(StreamMatchResultListener(&std::cout).IsInterested());
+
+  EXPECT_FALSE(DummyMatchResultListener().IsInterested());
+  EXPECT_FALSE(StreamMatchResultListener(nullptr).IsInterested());
+}
+
+// Makes sure that the MatcherInterface<T> interface doesn't
+// change.
+class EvenMatcherImpl : public MatcherInterface<int> {
+ public:
+  bool MatchAndExplain(int x,
+                       MatchResultListener* /* listener */) const override {
+    return x % 2 == 0;
+  }
+
+  void DescribeTo(ostream* os) const override { *os << "is an even number"; }
+
+  // We deliberately don't define DescribeNegationTo() and
+  // ExplainMatchResultTo() here, to make sure the definition of these
+  // two methods is optional.
+};
+
+// Makes sure that the MatcherInterface API doesn't change.
+TEST(MatcherInterfaceTest, CanBeImplementedUsingPublishedAPI) {
+  EvenMatcherImpl m;
+}
+
+// Tests implementing a monomorphic matcher using MatchAndExplain().
+
+class NewEvenMatcherImpl : public MatcherInterface<int> {
+ public:
+  bool MatchAndExplain(int x, MatchResultListener* listener) const override {
+    const bool match = x % 2 == 0;
+    // Verifies that we can stream to a listener directly.
+    *listener << "value % " << 2;
+    if (listener->stream() != nullptr) {
+      // Verifies that we can stream to a listener's underlying stream
+      // too.
+      *listener->stream() << " == " << (x % 2);
+    }
+    return match;
+  }
+
+  void DescribeTo(ostream* os) const override { *os << "is an even number"; }
+};
+
+TEST(MatcherInterfaceTest, CanBeImplementedUsingNewAPI) {
+  Matcher<int> m = MakeMatcher(new NewEvenMatcherImpl);
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(3));
+  EXPECT_EQ("value % 2 == 0", Explain(m, 2));
+  EXPECT_EQ("value % 2 == 1", Explain(m, 3));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(MatcherTest);
+
+// Tests default-constructing a matcher.
+TEST(MatcherTest, CanBeDefaultConstructed) { Matcher<double> m; }
+
+// Tests that Matcher<T> can be constructed from a MatcherInterface<T>*.
+TEST(MatcherTest, CanBeConstructedFromMatcherInterface) {
+  const MatcherInterface<int>* impl = new EvenMatcherImpl;
+  Matcher<int> m(impl);
+  EXPECT_TRUE(m.Matches(4));
+  EXPECT_FALSE(m.Matches(5));
+}
+
+// Tests that value can be used in place of Eq(value).
+TEST(MatcherTest, CanBeImplicitlyConstructedFromValue) {
+  Matcher<int> m1 = 5;
+  EXPECT_TRUE(m1.Matches(5));
+  EXPECT_FALSE(m1.Matches(6));
+}
+
+// Tests that NULL can be used in place of Eq(NULL).
+TEST(MatcherTest, CanBeImplicitlyConstructedFromNULL) {
+  Matcher<int*> m1 = nullptr;
+  EXPECT_TRUE(m1.Matches(nullptr));
+  int n = 0;
+  EXPECT_FALSE(m1.Matches(&n));
+}
+
+// Tests that matchers can be constructed from a variable that is not properly
+// defined. This should be illegal, but many users rely on this accidentally.
+struct Undefined {
+  virtual ~Undefined() = 0;
+  static const int kInt = 1;
+};
+
+TEST(MatcherTest, CanBeConstructedFromUndefinedVariable) {
+  Matcher<int> m1 = Undefined::kInt;
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_FALSE(m1.Matches(2));
+}
+
+// Test that a matcher parameterized with an abstract class compiles.
+TEST(MatcherTest, CanAcceptAbstractClass) { Matcher<const Undefined&> m = _; }
+
+// Tests that matchers are copyable.
+TEST(MatcherTest, IsCopyable) {
+  // Tests the copy constructor.
+  Matcher<bool> m1 = Eq(false);
+  EXPECT_TRUE(m1.Matches(false));
+  EXPECT_FALSE(m1.Matches(true));
+
+  // Tests the assignment operator.
+  m1 = Eq(true);
+  EXPECT_TRUE(m1.Matches(true));
+  EXPECT_FALSE(m1.Matches(false));
+}
+
+// Tests that Matcher<T>::DescribeTo() calls
+// MatcherInterface<T>::DescribeTo().
+TEST(MatcherTest, CanDescribeItself) {
+  EXPECT_EQ("is an even number", Describe(Matcher<int>(new EvenMatcherImpl)));
+}
+
+// Tests Matcher<T>::MatchAndExplain().
+TEST_P(MatcherTestP, MatchAndExplain) {
+  Matcher<int> m = GreaterThan(0);
+  StringMatchResultListener listener1;
+  EXPECT_TRUE(m.MatchAndExplain(42, &listener1));
+  EXPECT_EQ("which is 42 more than 0", listener1.str());
+
+  StringMatchResultListener listener2;
+  EXPECT_FALSE(m.MatchAndExplain(-9, &listener2));
+  EXPECT_EQ("which is 9 less than 0", listener2.str());
+}
+
+// Tests that a C-string literal can be implicitly converted to a
+// Matcher<std::string> or Matcher<const std::string&>.
+TEST(StringMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
+  Matcher<std::string> m1 = "hi";
+  EXPECT_TRUE(m1.Matches("hi"));
+  EXPECT_FALSE(m1.Matches("hello"));
+
+  Matcher<const std::string&> m2 = "hi";
+  EXPECT_TRUE(m2.Matches("hi"));
+  EXPECT_FALSE(m2.Matches("hello"));
+}
+
+// Tests that a string object can be implicitly converted to a
+// Matcher<std::string> or Matcher<const std::string&>.
+TEST(StringMatcherTest, CanBeImplicitlyConstructedFromString) {
+  Matcher<std::string> m1 = std::string("hi");
+  EXPECT_TRUE(m1.Matches("hi"));
+  EXPECT_FALSE(m1.Matches("hello"));
+
+  Matcher<const std::string&> m2 = std::string("hi");
+  EXPECT_TRUE(m2.Matches("hi"));
+  EXPECT_FALSE(m2.Matches("hello"));
+}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// Tests that a C-string literal can be implicitly converted to a
+// Matcher<StringView> or Matcher<const StringView&>.
+TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
+  Matcher<internal::StringView> m1 = "cats";
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const internal::StringView&> m2 = "cats";
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+
+// Tests that a std::string object can be implicitly converted to a
+// Matcher<StringView> or Matcher<const StringView&>.
+TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromString) {
+  Matcher<internal::StringView> m1 = std::string("cats");
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const internal::StringView&> m2 = std::string("cats");
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+
+// Tests that a StringView object can be implicitly converted to a
+// Matcher<StringView> or Matcher<const StringView&>.
+TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromStringView) {
+  Matcher<internal::StringView> m1 = internal::StringView("cats");
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const internal::StringView&> m2 = internal::StringView("cats");
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+// Tests that a std::reference_wrapper<std::string> object can be implicitly
+// converted to a Matcher<std::string> or Matcher<const std::string&> via Eq().
+TEST(StringMatcherTest,
+     CanBeImplicitlyConstructedFromEqReferenceWrapperString) {
+  std::string value = "cats";
+  Matcher<std::string> m1 = Eq(std::ref(value));
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const std::string&> m2 = Eq(std::ref(value));
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+
+// Tests that MakeMatcher() constructs a Matcher<T> from a
+// MatcherInterface* without requiring the user to explicitly
+// write the type.
+TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
+  const MatcherInterface<int>* dummy_impl = new EvenMatcherImpl;
+  Matcher<int> m = MakeMatcher(dummy_impl);
+}
+
+// Tests that MakePolymorphicMatcher() can construct a polymorphic
+// matcher from its implementation using the old API.
+const int g_bar = 1;
+class ReferencesBarOrIsZeroImpl {
+ public:
+  template <typename T>
+  bool MatchAndExplain(const T& x, MatchResultListener* /* listener */) const {
+    const void* p = &x;
+    return p == &g_bar || x == 0;
+  }
+
+  void DescribeTo(ostream* os) const { *os << "g_bar or zero"; }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "doesn't reference g_bar and is not zero";
+  }
+};
+
+// This function verifies that MakePolymorphicMatcher() returns a
+// PolymorphicMatcher<T> where T is the argument's type.
+PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() {
+  return MakePolymorphicMatcher(ReferencesBarOrIsZeroImpl());
+}
+
+TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) {
+  // Using a polymorphic matcher to match a reference type.
+  Matcher<const int&> m1 = ReferencesBarOrIsZero();
+  EXPECT_TRUE(m1.Matches(0));
+  // Verifies that the identity of a by-reference argument is preserved.
+  EXPECT_TRUE(m1.Matches(g_bar));
+  EXPECT_FALSE(m1.Matches(1));
+  EXPECT_EQ("g_bar or zero", Describe(m1));
+
+  // Using a polymorphic matcher to match a value type.
+  Matcher<double> m2 = ReferencesBarOrIsZero();
+  EXPECT_TRUE(m2.Matches(0.0));
+  EXPECT_FALSE(m2.Matches(0.1));
+  EXPECT_EQ("g_bar or zero", Describe(m2));
+}
+
+// Tests implementing a polymorphic matcher using MatchAndExplain().
+
+class PolymorphicIsEvenImpl {
+ public:
+  void DescribeTo(ostream* os) const { *os << "is even"; }
+
+  void DescribeNegationTo(ostream* os) const { *os << "is odd"; }
+
+  template <typename T>
+  bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
+    // Verifies that we can stream to the listener directly.
+    *listener << "% " << 2;
+    if (listener->stream() != nullptr) {
+      // Verifies that we can stream to the listener's underlying stream
+      // too.
+      *listener->stream() << " == " << (x % 2);
+    }
+    return (x % 2) == 0;
+  }
+};
+
+PolymorphicMatcher<PolymorphicIsEvenImpl> PolymorphicIsEven() {
+  return MakePolymorphicMatcher(PolymorphicIsEvenImpl());
+}
+
+TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingNewAPI) {
+  // Using PolymorphicIsEven() as a Matcher<int>.
+  const Matcher<int> m1 = PolymorphicIsEven();
+  EXPECT_TRUE(m1.Matches(42));
+  EXPECT_FALSE(m1.Matches(43));
+  EXPECT_EQ("is even", Describe(m1));
+
+  const Matcher<int> not_m1 = Not(m1);
+  EXPECT_EQ("is odd", Describe(not_m1));
+
+  EXPECT_EQ("% 2 == 0", Explain(m1, 42));
+
+  // Using PolymorphicIsEven() as a Matcher<char>.
+  const Matcher<char> m2 = PolymorphicIsEven();
+  EXPECT_TRUE(m2.Matches('\x42'));
+  EXPECT_FALSE(m2.Matches('\x43'));
+  EXPECT_EQ("is even", Describe(m2));
+
+  const Matcher<char> not_m2 = Not(m2);
+  EXPECT_EQ("is odd", Describe(not_m2));
+
+  EXPECT_EQ("% 2 == 0", Explain(m2, '\x42'));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(MatcherCastTest);
+
+// Tests that MatcherCast<T>(m) works when m is a polymorphic matcher.
+TEST_P(MatcherCastTestP, FromPolymorphicMatcher) {
+  Matcher<int16_t> m;
+  if (use_gtest_matcher_) {
+    m = MatcherCast<int16_t>(GtestGreaterThan(int64_t{5}));
+  } else {
+    m = MatcherCast<int16_t>(Gt(int64_t{5}));
+  }
+  EXPECT_TRUE(m.Matches(6));
+  EXPECT_FALSE(m.Matches(4));
+}
+
+// For testing casting matchers between compatible types.
+class IntValue {
+ public:
+  // An int can be statically (although not implicitly) cast to a
+  // IntValue.
+  explicit IntValue(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+// For testing casting matchers between compatible types.
+bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; }
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
+// can be statically converted to U.
+TEST(MatcherCastTest, FromCompatibleType) {
+  Matcher<double> m1 = Eq(2.0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(2));
+  EXPECT_FALSE(m2.Matches(3));
+
+  Matcher<IntValue> m3 = Truly(IsPositiveIntValue);
+  Matcher<int> m4 = MatcherCast<int>(m3);
+  // In the following, the arguments 1 and 0 are statically converted
+  // to IntValue objects, and then tested by the IsPositiveIntValue()
+  // predicate.
+  EXPECT_TRUE(m4.Matches(1));
+  EXPECT_FALSE(m4.Matches(0));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
+TEST(MatcherCastTest, FromConstReferenceToNonReference) {
+  Matcher<const int&> m1 = Eq(0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
+TEST(MatcherCastTest, FromReferenceToNonReference) {
+  Matcher<int&> m1 = Eq(0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
+TEST(MatcherCastTest, FromNonReferenceToConstReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<const int&> m2 = MatcherCast<const int&>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<T&>(m) works when m is a Matcher<T>.
+TEST(MatcherCastTest, FromNonReferenceToReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int&> m2 = MatcherCast<int&>(m1);
+  int n = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  n = 1;
+  EXPECT_FALSE(m2.Matches(n));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<T>.
+TEST(MatcherCastTest, FromSameType) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a value of the same type as the
+// value type of the Matcher.
+TEST(MatcherCastTest, FromAValue) {
+  Matcher<int> m = MatcherCast<int>(42);
+  EXPECT_TRUE(m.Matches(42));
+  EXPECT_FALSE(m.Matches(239));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a value of the type implicitly
+// convertible to the value type of the Matcher.
+TEST(MatcherCastTest, FromAnImplicitlyConvertibleValue) {
+  const int kExpected = 'c';
+  Matcher<int> m = MatcherCast<int>('c');
+  EXPECT_TRUE(m.Matches(kExpected));
+  EXPECT_FALSE(m.Matches(kExpected + 1));
+}
+
+struct NonImplicitlyConstructibleTypeWithOperatorEq {
+  friend bool operator==(
+      const NonImplicitlyConstructibleTypeWithOperatorEq& /* ignored */,
+      int rhs) {
+    return 42 == rhs;
+  }
+  friend bool operator==(
+      int lhs,
+      const NonImplicitlyConstructibleTypeWithOperatorEq& /* ignored */) {
+    return lhs == 42;
+  }
+};
+
+// Tests that MatcherCast<T>(m) works when m is a neither a matcher nor
+// implicitly convertible to the value type of the Matcher, but the value type
+// of the matcher has operator==() overload accepting m.
+TEST(MatcherCastTest, NonImplicitlyConstructibleTypeWithOperatorEq) {
+  Matcher<NonImplicitlyConstructibleTypeWithOperatorEq> m1 =
+      MatcherCast<NonImplicitlyConstructibleTypeWithOperatorEq>(42);
+  EXPECT_TRUE(m1.Matches(NonImplicitlyConstructibleTypeWithOperatorEq()));
+
+  Matcher<NonImplicitlyConstructibleTypeWithOperatorEq> m2 =
+      MatcherCast<NonImplicitlyConstructibleTypeWithOperatorEq>(239);
+  EXPECT_FALSE(m2.Matches(NonImplicitlyConstructibleTypeWithOperatorEq()));
+
+  // When updating the following lines please also change the comment to
+  // namespace convertible_from_any.
+  Matcher<int> m3 =
+      MatcherCast<int>(NonImplicitlyConstructibleTypeWithOperatorEq());
+  EXPECT_TRUE(m3.Matches(42));
+  EXPECT_FALSE(m3.Matches(239));
+}
+
+// ConvertibleFromAny does not work with MSVC. resulting in
+// error C2440: 'initializing': cannot convert from 'Eq' to 'M'
+// No constructor could take the source type, or constructor overload
+// resolution was ambiguous
+
+#if !defined _MSC_VER
+
+// The below ConvertibleFromAny struct is implicitly constructible from anything
+// and when in the same namespace can interact with other tests. In particular,
+// if it is in the same namespace as other tests and one removes
+//   NonImplicitlyConstructibleTypeWithOperatorEq::operator==(int lhs, ...);
+// then the corresponding test still compiles (and it should not!) by implicitly
+// converting NonImplicitlyConstructibleTypeWithOperatorEq to ConvertibleFromAny
+// in m3.Matcher().
+namespace convertible_from_any {
+// Implicitly convertible from any type.
+struct ConvertibleFromAny {
+  ConvertibleFromAny(int a_value) : value(a_value) {}
+  template <typename T>
+  ConvertibleFromAny(const T& /*a_value*/) : value(-1) {
+    ADD_FAILURE() << "Conversion constructor called";
+  }
+  int value;
+};
+
+bool operator==(const ConvertibleFromAny& a, const ConvertibleFromAny& b) {
+  return a.value == b.value;
+}
+
+ostream& operator<<(ostream& os, const ConvertibleFromAny& a) {
+  return os << a.value;
+}
+
+TEST(MatcherCastTest, ConversionConstructorIsUsed) {
+  Matcher<ConvertibleFromAny> m = MatcherCast<ConvertibleFromAny>(1);
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+
+TEST(MatcherCastTest, FromConvertibleFromAny) {
+  Matcher<ConvertibleFromAny> m =
+      MatcherCast<ConvertibleFromAny>(Eq(ConvertibleFromAny(1)));
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+}  // namespace convertible_from_any
+
+#endif  // !defined _MSC_VER
+
+struct IntReferenceWrapper {
+  IntReferenceWrapper(const int& a_value) : value(&a_value) {}
+  const int* value;
+};
+
+bool operator==(const IntReferenceWrapper& a, const IntReferenceWrapper& b) {
+  return a.value == b.value;
+}
+
+TEST(MatcherCastTest, ValueIsNotCopied) {
+  int n = 42;
+  Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(n);
+  // Verify that the matcher holds a reference to n, not to its temporary copy.
+  EXPECT_TRUE(m.Matches(n));
+}
+
+class Base {
+ public:
+  virtual ~Base() = default;
+  Base() = default;
+
+ private:
+  Base(const Base&) = delete;
+  Base& operator=(const Base&) = delete;
+};
+
+class Derived : public Base {
+ public:
+  Derived() : Base() {}
+  int i;
+};
+
+class OtherDerived : public Base {};
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(SafeMatcherCastTest);
+
+// Tests that SafeMatcherCast<T>(m) works when m is a polymorphic matcher.
+TEST_P(SafeMatcherCastTestP, FromPolymorphicMatcher) {
+  Matcher<char> m2;
+  if (use_gtest_matcher_) {
+    m2 = SafeMatcherCast<char>(GtestGreaterThan(32));
+  } else {
+    m2 = SafeMatcherCast<char>(Gt(32));
+  }
+  EXPECT_TRUE(m2.Matches('A'));
+  EXPECT_FALSE(m2.Matches('\n'));
+}
+
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<U> where
+// T and U are arithmetic types and T can be losslessly converted to
+// U.
+TEST(SafeMatcherCastTest, FromLosslesslyConvertibleArithmeticType) {
+  Matcher<double> m1 = DoubleEq(1.0);
+  Matcher<float> m2 = SafeMatcherCast<float>(m1);
+  EXPECT_TRUE(m2.Matches(1.0f));
+  EXPECT_FALSE(m2.Matches(2.0f));
+
+  Matcher<char> m3 = SafeMatcherCast<char>(TypedEq<int>('a'));
+  EXPECT_TRUE(m3.Matches('a'));
+  EXPECT_FALSE(m3.Matches('b'));
+}
+
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<U> where T and U
+// are pointers or references to a derived and a base class, correspondingly.
+TEST(SafeMatcherCastTest, FromBaseClass) {
+  Derived d, d2;
+  Matcher<Base*> m1 = Eq(&d);
+  Matcher<Derived*> m2 = SafeMatcherCast<Derived*>(m1);
+  EXPECT_TRUE(m2.Matches(&d));
+  EXPECT_FALSE(m2.Matches(&d2));
+
+  Matcher<Base&> m3 = Ref(d);
+  Matcher<Derived&> m4 = SafeMatcherCast<Derived&>(m3);
+  EXPECT_TRUE(m4.Matches(d));
+  EXPECT_FALSE(m4.Matches(d2));
+}
+
+// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
+TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
+  int n = 0;
+  Matcher<const int&> m1 = Ref(n);
+  Matcher<int&> m2 = SafeMatcherCast<int&>(m1);
+  int n1 = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  EXPECT_FALSE(m2.Matches(n1));
+}
+
+// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
+TEST(SafeMatcherCastTest, FromNonReferenceToConstReference) {
+  Matcher<std::unique_ptr<int>> m1 = IsNull();
+  Matcher<const std::unique_ptr<int>&> m2 =
+      SafeMatcherCast<const std::unique_ptr<int>&>(m1);
+  EXPECT_TRUE(m2.Matches(std::unique_ptr<int>()));
+  EXPECT_FALSE(m2.Matches(std::unique_ptr<int>(new int)));
+}
+
+// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<T>.
+TEST(SafeMatcherCastTest, FromNonReferenceToReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int&> m2 = SafeMatcherCast<int&>(m1);
+  int n = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  n = 1;
+  EXPECT_FALSE(m2.Matches(n));
+}
+
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<T>.
+TEST(SafeMatcherCastTest, FromSameType) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int> m2 = SafeMatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+#if !defined _MSC_VER
+
+namespace convertible_from_any {
+TEST(SafeMatcherCastTest, ConversionConstructorIsUsed) {
+  Matcher<ConvertibleFromAny> m = SafeMatcherCast<ConvertibleFromAny>(1);
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+
+TEST(SafeMatcherCastTest, FromConvertibleFromAny) {
+  Matcher<ConvertibleFromAny> m =
+      SafeMatcherCast<ConvertibleFromAny>(Eq(ConvertibleFromAny(1)));
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+}  // namespace convertible_from_any
+
+#endif  // !defined _MSC_VER
+
+TEST(SafeMatcherCastTest, ValueIsNotCopied) {
+  int n = 42;
+  Matcher<IntReferenceWrapper> m = SafeMatcherCast<IntReferenceWrapper>(n);
+  // Verify that the matcher holds a reference to n, not to its temporary copy.
+  EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(ExpectThat, TakesLiterals) {
+  EXPECT_THAT(1, 1);
+  EXPECT_THAT(1.0, 1.0);
+  EXPECT_THAT(std::string(), "");
+}
+
+TEST(ExpectThat, TakesFunctions) {
+  struct Helper {
+    static void Func() {}
+  };
+  void (*func)() = Helper::Func;
+  EXPECT_THAT(func, Helper::Func);
+  EXPECT_THAT(func, &Helper::Func);
+}
+
+// Tests that A<T>() matches any value of type T.
+TEST(ATest, MatchesAnyValue) {
+  // Tests a matcher for a value type.
+  Matcher<double> m1 = A<double>();
+  EXPECT_TRUE(m1.Matches(91.43));
+  EXPECT_TRUE(m1.Matches(-15.32));
+
+  // Tests a matcher for a reference type.
+  int a = 2;
+  int b = -6;
+  Matcher<int&> m2 = A<int&>();
+  EXPECT_TRUE(m2.Matches(a));
+  EXPECT_TRUE(m2.Matches(b));
+}
+
+TEST(ATest, WorksForDerivedClass) {
+  Base base;
+  Derived derived;
+  EXPECT_THAT(&base, A<Base*>());
+  // This shouldn't compile: EXPECT_THAT(&base, A<Derived*>());
+  EXPECT_THAT(&derived, A<Base*>());
+  EXPECT_THAT(&derived, A<Derived*>());
+}
+
+// Tests that A<T>() describes itself properly.
+TEST(ATest, CanDescribeSelf) { EXPECT_EQ("is anything", Describe(A<bool>())); }
+
+// Tests that An<T>() matches any value of type T.
+TEST(AnTest, MatchesAnyValue) {
+  // Tests a matcher for a value type.
+  Matcher<int> m1 = An<int>();
+  EXPECT_TRUE(m1.Matches(9143));
+  EXPECT_TRUE(m1.Matches(-1532));
+
+  // Tests a matcher for a reference type.
+  int a = 2;
+  int b = -6;
+  Matcher<int&> m2 = An<int&>();
+  EXPECT_TRUE(m2.Matches(a));
+  EXPECT_TRUE(m2.Matches(b));
+}
+
+// Tests that An<T>() describes itself properly.
+TEST(AnTest, CanDescribeSelf) { EXPECT_EQ("is anything", Describe(An<int>())); }
+
+// Tests that _ can be used as a matcher for any type and matches any
+// value of that type.
+TEST(UnderscoreTest, MatchesAnyValue) {
+  // Uses _ as a matcher for a value type.
+  Matcher<int> m1 = _;
+  EXPECT_TRUE(m1.Matches(123));
+  EXPECT_TRUE(m1.Matches(-242));
+
+  // Uses _ as a matcher for a reference type.
+  bool a = false;
+  const bool b = true;
+  Matcher<const bool&> m2 = _;
+  EXPECT_TRUE(m2.Matches(a));
+  EXPECT_TRUE(m2.Matches(b));
+}
+
+// Tests that _ describes itself properly.
+TEST(UnderscoreTest, CanDescribeSelf) {
+  Matcher<int> m = _;
+  EXPECT_EQ("is anything", Describe(m));
+}
+
+// Tests that Eq(x) matches any value equal to x.
+TEST(EqTest, MatchesEqualValue) {
+  // 2 C-strings with same content but different addresses.
+  const char a1[] = "hi";
+  const char a2[] = "hi";
+
+  Matcher<const char*> m1 = Eq(a1);
+  EXPECT_TRUE(m1.Matches(a1));
+  EXPECT_FALSE(m1.Matches(a2));
+}
+
+// Tests that Eq(v) describes itself properly.
+
+class Unprintable {
+ public:
+  Unprintable() : c_('a') {}
+
+  bool operator==(const Unprintable& /* rhs */) const { return true; }
+  // -Wunused-private-field: dummy accessor for `c_`.
+  char dummy_c() { return c_; }
+
+ private:
+  char c_;
+};
+
+TEST(EqTest, CanDescribeSelf) {
+  Matcher<Unprintable> m = Eq(Unprintable());
+  EXPECT_EQ("is equal to 1-byte object <61>", Describe(m));
+}
+
+// Tests that Eq(v) can be used to match any type that supports
+// comparing with type T, where T is v's type.
+TEST(EqTest, IsPolymorphic) {
+  Matcher<int> m1 = Eq(1);
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_FALSE(m1.Matches(2));
+
+  Matcher<char> m2 = Eq(1);
+  EXPECT_TRUE(m2.Matches('\1'));
+  EXPECT_FALSE(m2.Matches('a'));
+}
+
+// Tests that TypedEq<T>(v) matches values of type T that's equal to v.
+TEST(TypedEqTest, ChecksEqualityForGivenType) {
+  Matcher<char> m1 = TypedEq<char>('a');
+  EXPECT_TRUE(m1.Matches('a'));
+  EXPECT_FALSE(m1.Matches('b'));
+
+  Matcher<int> m2 = TypedEq<int>(6);
+  EXPECT_TRUE(m2.Matches(6));
+  EXPECT_FALSE(m2.Matches(7));
+}
+
+// Tests that TypedEq(v) describes itself properly.
+TEST(TypedEqTest, CanDescribeSelf) {
+  EXPECT_EQ("is equal to 2", Describe(TypedEq<int>(2)));
+}
+
+// Tests that TypedEq<T>(v) has type Matcher<T>.
+
+// Type<T>::IsTypeOf(v) compiles if and only if the type of value v is T, where
+// T is a "bare" type (i.e. not in the form of const U or U&).  If v's type is
+// not T, the compiler will generate a message about "undefined reference".
+template <typename T>
+struct Type {
+  static bool IsTypeOf(const T& /* v */) { return true; }
+
+  template <typename T2>
+  static void IsTypeOf(T2 v);
+};
+
+TEST(TypedEqTest, HasSpecifiedType) {
+  // Verifies that the type of TypedEq<T>(v) is Matcher<T>.
+  Type<Matcher<int>>::IsTypeOf(TypedEq<int>(5));
+  Type<Matcher<double>>::IsTypeOf(TypedEq<double>(5));
+}
+
+// Tests that Ge(v) matches anything >= v.
+TEST(GeTest, ImplementsGreaterThanOrEqual) {
+  Matcher<int> m1 = Ge(0);
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_TRUE(m1.Matches(0));
+  EXPECT_FALSE(m1.Matches(-1));
+}
+
+// Tests that Ge(v) describes itself properly.
+TEST(GeTest, CanDescribeSelf) {
+  Matcher<int> m = Ge(5);
+  EXPECT_EQ("is >= 5", Describe(m));
+}
+
+// Tests that Gt(v) matches anything > v.
+TEST(GtTest, ImplementsGreaterThan) {
+  Matcher<double> m1 = Gt(0);
+  EXPECT_TRUE(m1.Matches(1.0));
+  EXPECT_FALSE(m1.Matches(0.0));
+  EXPECT_FALSE(m1.Matches(-1.0));
+}
+
+// Tests that Gt(v) describes itself properly.
+TEST(GtTest, CanDescribeSelf) {
+  Matcher<int> m = Gt(5);
+  EXPECT_EQ("is > 5", Describe(m));
+}
+
+// Tests that Le(v) matches anything <= v.
+TEST(LeTest, ImplementsLessThanOrEqual) {
+  Matcher<char> m1 = Le('b');
+  EXPECT_TRUE(m1.Matches('a'));
+  EXPECT_TRUE(m1.Matches('b'));
+  EXPECT_FALSE(m1.Matches('c'));
+}
+
+// Tests that Le(v) describes itself properly.
+TEST(LeTest, CanDescribeSelf) {
+  Matcher<int> m = Le(5);
+  EXPECT_EQ("is <= 5", Describe(m));
+}
+
+// Tests that Lt(v) matches anything < v.
+TEST(LtTest, ImplementsLessThan) {
+  Matcher<const std::string&> m1 = Lt("Hello");
+  EXPECT_TRUE(m1.Matches("Abc"));
+  EXPECT_FALSE(m1.Matches("Hello"));
+  EXPECT_FALSE(m1.Matches("Hello, world!"));
+}
+
+// Tests that Lt(v) describes itself properly.
+TEST(LtTest, CanDescribeSelf) {
+  Matcher<int> m = Lt(5);
+  EXPECT_EQ("is < 5", Describe(m));
+}
+
+// Tests that Ne(v) matches anything != v.
+TEST(NeTest, ImplementsNotEqual) {
+  Matcher<int> m1 = Ne(0);
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_TRUE(m1.Matches(-1));
+  EXPECT_FALSE(m1.Matches(0));
+}
+
+// Tests that Ne(v) describes itself properly.
+TEST(NeTest, CanDescribeSelf) {
+  Matcher<int> m = Ne(5);
+  EXPECT_EQ("isn't equal to 5", Describe(m));
+}
+
+class MoveOnly {
+ public:
+  explicit MoveOnly(int i) : i_(i) {}
+  MoveOnly(const MoveOnly&) = delete;
+  MoveOnly(MoveOnly&&) = default;
+  MoveOnly& operator=(const MoveOnly&) = delete;
+  MoveOnly& operator=(MoveOnly&&) = default;
+
+  bool operator==(const MoveOnly& other) const { return i_ == other.i_; }
+  bool operator!=(const MoveOnly& other) const { return i_ != other.i_; }
+  bool operator<(const MoveOnly& other) const { return i_ < other.i_; }
+  bool operator<=(const MoveOnly& other) const { return i_ <= other.i_; }
+  bool operator>(const MoveOnly& other) const { return i_ > other.i_; }
+  bool operator>=(const MoveOnly& other) const { return i_ >= other.i_; }
+
+ private:
+  int i_;
+};
+
+struct MoveHelper {
+  MOCK_METHOD1(Call, void(MoveOnly));
+};
+
+// Disable this test in VS 2015 (version 14), where it fails when SEH is enabled
+#if defined(_MSC_VER) && (_MSC_VER < 1910)
+TEST(ComparisonBaseTest, DISABLED_WorksWithMoveOnly) {
+#else
+TEST(ComparisonBaseTest, WorksWithMoveOnly) {
+#endif
+  MoveOnly m{0};
+  MoveHelper helper;
+
+  EXPECT_CALL(helper, Call(Eq(ByRef(m))));
+  helper.Call(MoveOnly(0));
+  EXPECT_CALL(helper, Call(Ne(ByRef(m))));
+  helper.Call(MoveOnly(1));
+  EXPECT_CALL(helper, Call(Le(ByRef(m))));
+  helper.Call(MoveOnly(0));
+  EXPECT_CALL(helper, Call(Lt(ByRef(m))));
+  helper.Call(MoveOnly(-1));
+  EXPECT_CALL(helper, Call(Ge(ByRef(m))));
+  helper.Call(MoveOnly(0));
+  EXPECT_CALL(helper, Call(Gt(ByRef(m))));
+  helper.Call(MoveOnly(1));
+}
+
+TEST(IsEmptyTest, MatchesContainer) {
+  const Matcher<std::vector<int>> m = IsEmpty();
+  std::vector<int> a = {};
+  std::vector<int> b = {1};
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_FALSE(m.Matches(b));
+}
+
+TEST(IsEmptyTest, MatchesStdString) {
+  const Matcher<std::string> m = IsEmpty();
+  std::string a = "z";
+  std::string b = "";
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_TRUE(m.Matches(b));
+}
+
+TEST(IsEmptyTest, MatchesCString) {
+  const Matcher<const char*> m = IsEmpty();
+  const char a[] = "";
+  const char b[] = "x";
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_FALSE(m.Matches(b));
+}
+
+// Tests that IsNull() matches any NULL pointer of any type.
+TEST(IsNullTest, MatchesNullPointer) {
+  Matcher<int*> m1 = IsNull();
+  int* p1 = nullptr;
+  int n = 0;
+  EXPECT_TRUE(m1.Matches(p1));
+  EXPECT_FALSE(m1.Matches(&n));
+
+  Matcher<const char*> m2 = IsNull();
+  const char* p2 = nullptr;
+  EXPECT_TRUE(m2.Matches(p2));
+  EXPECT_FALSE(m2.Matches("hi"));
+
+  Matcher<void*> m3 = IsNull();
+  void* p3 = nullptr;
+  EXPECT_TRUE(m3.Matches(p3));
+  EXPECT_FALSE(m3.Matches(reinterpret_cast<void*>(0xbeef)));
+}
+
+TEST(IsNullTest, StdFunction) {
+  const Matcher<std::function<void()>> m = IsNull();
+
+  EXPECT_TRUE(m.Matches(std::function<void()>()));
+  EXPECT_FALSE(m.Matches([] {}));
+}
+
+// Tests that IsNull() describes itself properly.
+TEST(IsNullTest, CanDescribeSelf) {
+  Matcher<int*> m = IsNull();
+  EXPECT_EQ("is NULL", Describe(m));
+  EXPECT_EQ("isn't NULL", DescribeNegation(m));
+}
+
+// Tests that NotNull() matches any non-NULL pointer of any type.
+TEST(NotNullTest, MatchesNonNullPointer) {
+  Matcher<int*> m1 = NotNull();
+  int* p1 = nullptr;
+  int n = 0;
+  EXPECT_FALSE(m1.Matches(p1));
+  EXPECT_TRUE(m1.Matches(&n));
+
+  Matcher<const char*> m2 = NotNull();
+  const char* p2 = nullptr;
+  EXPECT_FALSE(m2.Matches(p2));
+  EXPECT_TRUE(m2.Matches("hi"));
+}
+
+TEST(NotNullTest, LinkedPtr) {
+  const Matcher<std::shared_ptr<int>> m = NotNull();
+  const std::shared_ptr<int> null_p;
+  const std::shared_ptr<int> non_null_p(new int);
+
+  EXPECT_FALSE(m.Matches(null_p));
+  EXPECT_TRUE(m.Matches(non_null_p));
+}
+
+TEST(NotNullTest, ReferenceToConstLinkedPtr) {
+  const Matcher<const std::shared_ptr<double>&> m = NotNull();
+  const std::shared_ptr<double> null_p;
+  const std::shared_ptr<double> non_null_p(new double);
+
+  EXPECT_FALSE(m.Matches(null_p));
+  EXPECT_TRUE(m.Matches(non_null_p));
+}
+
+TEST(NotNullTest, StdFunction) {
+  const Matcher<std::function<void()>> m = NotNull();
+
+  EXPECT_TRUE(m.Matches([] {}));
+  EXPECT_FALSE(m.Matches(std::function<void()>()));
+}
+
+// Tests that NotNull() describes itself properly.
+TEST(NotNullTest, CanDescribeSelf) {
+  Matcher<int*> m = NotNull();
+  EXPECT_EQ("isn't NULL", Describe(m));
+}
+
+// Tests that Ref(variable) matches an argument that references
+// 'variable'.
+TEST(RefTest, MatchesSameVariable) {
+  int a = 0;
+  int b = 0;
+  Matcher<int&> m = Ref(a);
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_FALSE(m.Matches(b));
+}
+
+// Tests that Ref(variable) describes itself properly.
+TEST(RefTest, CanDescribeSelf) {
+  int n = 5;
+  Matcher<int&> m = Ref(n);
+  stringstream ss;
+  ss << "references the variable @" << &n << " 5";
+  EXPECT_EQ(ss.str(), Describe(m));
+}
+
+// Test that Ref(non_const_varialbe) can be used as a matcher for a
+// const reference.
+TEST(RefTest, CanBeUsedAsMatcherForConstReference) {
+  int a = 0;
+  int b = 0;
+  Matcher<const int&> m = Ref(a);
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_FALSE(m.Matches(b));
+}
+
+// Tests that Ref(variable) is covariant, i.e. Ref(derived) can be
+// used wherever Ref(base) can be used (Ref(derived) is a sub-type
+// of Ref(base), but not vice versa.
+
+TEST(RefTest, IsCovariant) {
+  Base base, base2;
+  Derived derived;
+  Matcher<const Base&> m1 = Ref(base);
+  EXPECT_TRUE(m1.Matches(base));
+  EXPECT_FALSE(m1.Matches(base2));
+  EXPECT_FALSE(m1.Matches(derived));
+
+  m1 = Ref(derived);
+  EXPECT_TRUE(m1.Matches(derived));
+  EXPECT_FALSE(m1.Matches(base));
+  EXPECT_FALSE(m1.Matches(base2));
+}
+
+TEST(RefTest, ExplainsResult) {
+  int n = 0;
+  EXPECT_THAT(Explain(Matcher<const int&>(Ref(n)), n),
+              StartsWith("which is located @"));
+
+  int m = 0;
+  EXPECT_THAT(Explain(Matcher<const int&>(Ref(n)), m),
+              StartsWith("which is located @"));
+}
+
+// Tests string comparison matchers.
+
+template <typename T = std::string>
+std::string FromStringLike(internal::StringLike<T> str) {
+  return std::string(str);
+}
+
+TEST(StringLike, TestConversions) {
+  EXPECT_EQ("foo", FromStringLike("foo"));
+  EXPECT_EQ("foo", FromStringLike(std::string("foo")));
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  EXPECT_EQ("foo", FromStringLike(internal::StringView("foo")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Non deducible types.
+  EXPECT_EQ("", FromStringLike({}));
+  EXPECT_EQ("foo", FromStringLike({'f', 'o', 'o'}));
+  const char buf[] = "foo";
+  EXPECT_EQ("foo", FromStringLike({buf, buf + 3}));
+}
+
+TEST(StrEqTest, MatchesEqualString) {
+  Matcher<const char*> m = StrEq(std::string("Hello"));
+  EXPECT_TRUE(m.Matches("Hello"));
+  EXPECT_FALSE(m.Matches("hello"));
+  EXPECT_FALSE(m.Matches(nullptr));
+
+  Matcher<const std::string&> m2 = StrEq("Hello");
+  EXPECT_TRUE(m2.Matches("Hello"));
+  EXPECT_FALSE(m2.Matches("Hi"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  Matcher<const internal::StringView&> m3 =
+      StrEq(internal::StringView("Hello"));
+  EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
+  EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
+  EXPECT_FALSE(m3.Matches(internal::StringView()));
+
+  Matcher<const internal::StringView&> m_empty = StrEq("");
+  EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
+  EXPECT_TRUE(m_empty.Matches(internal::StringView()));
+  EXPECT_FALSE(m_empty.Matches(internal::StringView("hello")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(StrEqTest, CanDescribeSelf) {
+  Matcher<std::string> m = StrEq("Hi-\'\"?\\\a\b\f\n\r\t\v\xD3");
+  EXPECT_EQ("is equal to \"Hi-\'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\xD3\"",
+            Describe(m));
+
+  std::string str("01204500800");
+  str[3] = '\0';
+  Matcher<std::string> m2 = StrEq(str);
+  EXPECT_EQ("is equal to \"012\\04500800\"", Describe(m2));
+  str[0] = str[6] = str[7] = str[9] = str[10] = '\0';
+  Matcher<std::string> m3 = StrEq(str);
+  EXPECT_EQ("is equal to \"\\012\\045\\0\\08\\0\\0\"", Describe(m3));
+}
+
+TEST(StrNeTest, MatchesUnequalString) {
+  Matcher<const char*> m = StrNe("Hello");
+  EXPECT_TRUE(m.Matches(""));
+  EXPECT_TRUE(m.Matches(nullptr));
+  EXPECT_FALSE(m.Matches("Hello"));
+
+  Matcher<std::string> m2 = StrNe(std::string("Hello"));
+  EXPECT_TRUE(m2.Matches("hello"));
+  EXPECT_FALSE(m2.Matches("Hello"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  Matcher<const internal::StringView> m3 = StrNe(internal::StringView("Hello"));
+  EXPECT_TRUE(m3.Matches(internal::StringView("")));
+  EXPECT_TRUE(m3.Matches(internal::StringView()));
+  EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(StrNeTest, CanDescribeSelf) {
+  Matcher<const char*> m = StrNe("Hi");
+  EXPECT_EQ("isn't equal to \"Hi\"", Describe(m));
+}
+
+TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) {
+  Matcher<const char*> m = StrCaseEq(std::string("Hello"));
+  EXPECT_TRUE(m.Matches("Hello"));
+  EXPECT_TRUE(m.Matches("hello"));
+  EXPECT_FALSE(m.Matches("Hi"));
+  EXPECT_FALSE(m.Matches(nullptr));
+
+  Matcher<const std::string&> m2 = StrCaseEq("Hello");
+  EXPECT_TRUE(m2.Matches("hello"));
+  EXPECT_FALSE(m2.Matches("Hi"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  Matcher<const internal::StringView&> m3 =
+      StrCaseEq(internal::StringView("Hello"));
+  EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
+  EXPECT_TRUE(m3.Matches(internal::StringView("hello")));
+  EXPECT_FALSE(m3.Matches(internal::StringView("Hi")));
+  EXPECT_FALSE(m3.Matches(internal::StringView()));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(StrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
+  std::string str1("oabocdooeoo");
+  std::string str2("OABOCDOOEOO");
+  Matcher<const std::string&> m0 = StrCaseEq(str1);
+  EXPECT_FALSE(m0.Matches(str2 + std::string(1, '\0')));
+
+  str1[3] = str2[3] = '\0';
+  Matcher<const std::string&> m1 = StrCaseEq(str1);
+  EXPECT_TRUE(m1.Matches(str2));
+
+  str1[0] = str1[6] = str1[7] = str1[10] = '\0';
+  str2[0] = str2[6] = str2[7] = str2[10] = '\0';
+  Matcher<const std::string&> m2 = StrCaseEq(str1);
+  str1[9] = str2[9] = '\0';
+  EXPECT_FALSE(m2.Matches(str2));
+
+  Matcher<const std::string&> m3 = StrCaseEq(str1);
+  EXPECT_TRUE(m3.Matches(str2));
+
+  EXPECT_FALSE(m3.Matches(str2 + "x"));
+  str2.append(1, '\0');
+  EXPECT_FALSE(m3.Matches(str2));
+  EXPECT_FALSE(m3.Matches(std::string(str2, 0, 9)));
+}
+
+TEST(StrCaseEqTest, CanDescribeSelf) {
+  Matcher<std::string> m = StrCaseEq("Hi");
+  EXPECT_EQ("is equal to (ignoring case) \"Hi\"", Describe(m));
+}
+
+TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) {
+  Matcher<const char*> m = StrCaseNe("Hello");
+  EXPECT_TRUE(m.Matches("Hi"));
+  EXPECT_TRUE(m.Matches(nullptr));
+  EXPECT_FALSE(m.Matches("Hello"));
+  EXPECT_FALSE(m.Matches("hello"));
+
+  Matcher<std::string> m2 = StrCaseNe(std::string("Hello"));
+  EXPECT_TRUE(m2.Matches(""));
+  EXPECT_FALSE(m2.Matches("Hello"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  Matcher<const internal::StringView> m3 =
+      StrCaseNe(internal::StringView("Hello"));
+  EXPECT_TRUE(m3.Matches(internal::StringView("Hi")));
+  EXPECT_TRUE(m3.Matches(internal::StringView()));
+  EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
+  EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(StrCaseNeTest, CanDescribeSelf) {
+  Matcher<const char*> m = StrCaseNe("Hi");
+  EXPECT_EQ("isn't equal to (ignoring case) \"Hi\"", Describe(m));
+}
+
+// Tests that HasSubstr() works for matching string-typed values.
+TEST(HasSubstrTest, WorksForStringClasses) {
+  const Matcher<std::string> m1 = HasSubstr("foo");
+  EXPECT_TRUE(m1.Matches(std::string("I love food.")));
+  EXPECT_FALSE(m1.Matches(std::string("tofo")));
+
+  const Matcher<const std::string&> m2 = HasSubstr("foo");
+  EXPECT_TRUE(m2.Matches(std::string("I love food.")));
+  EXPECT_FALSE(m2.Matches(std::string("tofo")));
+
+  const Matcher<std::string> m_empty = HasSubstr("");
+  EXPECT_TRUE(m_empty.Matches(std::string()));
+  EXPECT_TRUE(m_empty.Matches(std::string("not empty")));
+}
+
+// Tests that HasSubstr() works for matching C-string-typed values.
+TEST(HasSubstrTest, WorksForCStrings) {
+  const Matcher<char*> m1 = HasSubstr("foo");
+  EXPECT_TRUE(m1.Matches(const_cast<char*>("I love food.")));
+  EXPECT_FALSE(m1.Matches(const_cast<char*>("tofo")));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const char*> m2 = HasSubstr("foo");
+  EXPECT_TRUE(m2.Matches("I love food."));
+  EXPECT_FALSE(m2.Matches("tofo"));
+  EXPECT_FALSE(m2.Matches(nullptr));
+
+  const Matcher<const char*> m_empty = HasSubstr("");
+  EXPECT_TRUE(m_empty.Matches("not empty"));
+  EXPECT_TRUE(m_empty.Matches(""));
+  EXPECT_FALSE(m_empty.Matches(nullptr));
+}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// Tests that HasSubstr() works for matching StringView-typed values.
+TEST(HasSubstrTest, WorksForStringViewClasses) {
+  const Matcher<internal::StringView> m1 =
+      HasSubstr(internal::StringView("foo"));
+  EXPECT_TRUE(m1.Matches(internal::StringView("I love food.")));
+  EXPECT_FALSE(m1.Matches(internal::StringView("tofo")));
+  EXPECT_FALSE(m1.Matches(internal::StringView()));
+
+  const Matcher<const internal::StringView&> m2 = HasSubstr("foo");
+  EXPECT_TRUE(m2.Matches(internal::StringView("I love food.")));
+  EXPECT_FALSE(m2.Matches(internal::StringView("tofo")));
+  EXPECT_FALSE(m2.Matches(internal::StringView()));
+
+  const Matcher<const internal::StringView&> m3 = HasSubstr("");
+  EXPECT_TRUE(m3.Matches(internal::StringView("foo")));
+  EXPECT_TRUE(m3.Matches(internal::StringView("")));
+  EXPECT_TRUE(m3.Matches(internal::StringView()));
+}
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+// Tests that HasSubstr(s) describes itself properly.
+TEST(HasSubstrTest, CanDescribeSelf) {
+  Matcher<std::string> m = HasSubstr("foo\n\"");
+  EXPECT_EQ("has substring \"foo\\n\\\"\"", Describe(m));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(KeyTest);
+
+TEST(KeyTest, CanDescribeSelf) {
+  Matcher<const pair<std::string, int>&> m = Key("foo");
+  EXPECT_EQ("has a key that is equal to \"foo\"", Describe(m));
+  EXPECT_EQ("doesn't have a key that is equal to \"foo\"", DescribeNegation(m));
+}
+
+TEST_P(KeyTestP, ExplainsResult) {
+  Matcher<pair<int, bool>> m = Key(GreaterThan(10));
+  EXPECT_EQ("whose first field is a value which is 5 less than 10",
+            Explain(m, make_pair(5, true)));
+  EXPECT_EQ("whose first field is a value which is 5 more than 10",
+            Explain(m, make_pair(15, true)));
+}
+
+TEST(KeyTest, MatchesCorrectly) {
+  pair<int, std::string> p(25, "foo");
+  EXPECT_THAT(p, Key(25));
+  EXPECT_THAT(p, Not(Key(42)));
+  EXPECT_THAT(p, Key(Ge(20)));
+  EXPECT_THAT(p, Not(Key(Lt(25))));
+}
+
+TEST(KeyTest, WorksWithMoveOnly) {
+  pair<std::unique_ptr<int>, std::unique_ptr<int>> p;
+  EXPECT_THAT(p, Key(Eq(nullptr)));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(PairTest);
+
+template <size_t I>
+struct Tag {};
+
+struct PairWithGet {
+  int member_1;
+  std::string member_2;
+  using first_type = int;
+  using second_type = std::string;
+
+  const int& GetImpl(Tag<0>) const { return member_1; }
+  const std::string& GetImpl(Tag<1>) const { return member_2; }
+};
+template <size_t I>
+auto get(const PairWithGet& value) -> decltype(value.GetImpl(Tag<I>())) {
+  return value.GetImpl(Tag<I>());
+}
+TEST(PairTest, MatchesPairWithGetCorrectly) {
+  PairWithGet p{25, "foo"};
+  EXPECT_THAT(p, Key(25));
+  EXPECT_THAT(p, Not(Key(42)));
+  EXPECT_THAT(p, Key(Ge(20)));
+  EXPECT_THAT(p, Not(Key(Lt(25))));
+
+  std::vector<PairWithGet> v = {{11, "Foo"}, {29, "gMockIsBestMock"}};
+  EXPECT_THAT(v, Contains(Key(29)));
+}
+
+TEST(KeyTest, SafelyCastsInnerMatcher) {
+  Matcher<int> is_positive = Gt(0);
+  Matcher<int> is_negative = Lt(0);
+  pair<char, bool> p('a', true);
+  EXPECT_THAT(p, Key(is_positive));
+  EXPECT_THAT(p, Not(Key(is_negative)));
+}
+
+TEST(KeyTest, InsideContainsUsingMap) {
+  map<int, char> container;
+  container.insert(make_pair(1, 'a'));
+  container.insert(make_pair(2, 'b'));
+  container.insert(make_pair(4, 'c'));
+  EXPECT_THAT(container, Contains(Key(1)));
+  EXPECT_THAT(container, Not(Contains(Key(3))));
+}
+
+TEST(KeyTest, InsideContainsUsingMultimap) {
+  multimap<int, char> container;
+  container.insert(make_pair(1, 'a'));
+  container.insert(make_pair(2, 'b'));
+  container.insert(make_pair(4, 'c'));
+
+  EXPECT_THAT(container, Not(Contains(Key(25))));
+  container.insert(make_pair(25, 'd'));
+  EXPECT_THAT(container, Contains(Key(25)));
+  container.insert(make_pair(25, 'e'));
+  EXPECT_THAT(container, Contains(Key(25)));
+
+  EXPECT_THAT(container, Contains(Key(1)));
+  EXPECT_THAT(container, Not(Contains(Key(3))));
+}
+
+TEST(PairTest, Typing) {
+  // Test verifies the following type conversions can be compiled.
+  Matcher<const pair<const char*, int>&> m1 = Pair("foo", 42);
+  Matcher<const pair<const char*, int>> m2 = Pair("foo", 42);
+  Matcher<pair<const char*, int>> m3 = Pair("foo", 42);
+
+  Matcher<pair<int, const std::string>> m4 = Pair(25, "42");
+  Matcher<pair<const std::string, int>> m5 = Pair("25", 42);
+}
+
+TEST(PairTest, CanDescribeSelf) {
+  Matcher<const pair<std::string, int>&> m1 = Pair("foo", 42);
+  EXPECT_EQ(
+      "has a first field that is equal to \"foo\""
+      ", and has a second field that is equal to 42",
+      Describe(m1));
+  EXPECT_EQ(
+      "has a first field that isn't equal to \"foo\""
+      ", or has a second field that isn't equal to 42",
+      DescribeNegation(m1));
+  // Double and triple negation (1 or 2 times not and description of negation).
+  Matcher<const pair<int, int>&> m2 = Not(Pair(Not(13), 42));
+  EXPECT_EQ(
+      "has a first field that isn't equal to 13"
+      ", and has a second field that is equal to 42",
+      DescribeNegation(m2));
+}
+
+TEST_P(PairTestP, CanExplainMatchResultTo) {
+  // If neither field matches, Pair() should explain about the first
+  // field.
+  const Matcher<pair<int, int>> m = Pair(GreaterThan(0), GreaterThan(0));
+  EXPECT_EQ("whose first field does not match, which is 1 less than 0",
+            Explain(m, make_pair(-1, -2)));
+
+  // If the first field matches but the second doesn't, Pair() should
+  // explain about the second field.
+  EXPECT_EQ("whose second field does not match, which is 2 less than 0",
+            Explain(m, make_pair(1, -2)));
+
+  // If the first field doesn't match but the second does, Pair()
+  // should explain about the first field.
+  EXPECT_EQ("whose first field does not match, which is 1 less than 0",
+            Explain(m, make_pair(-1, 2)));
+
+  // If both fields match, Pair() should explain about them both.
+  EXPECT_EQ(
+      "whose both fields match, where the first field is a value "
+      "which is 1 more than 0, and the second field is a value "
+      "which is 2 more than 0",
+      Explain(m, make_pair(1, 2)));
+
+  // If only the first match has an explanation, only this explanation should
+  // be printed.
+  const Matcher<pair<int, int>> explain_first = Pair(GreaterThan(0), 0);
+  EXPECT_EQ(
+      "whose both fields match, where the first field is a value "
+      "which is 1 more than 0",
+      Explain(explain_first, make_pair(1, 0)));
+
+  // If only the second match has an explanation, only this explanation should
+  // be printed.
+  const Matcher<pair<int, int>> explain_second = Pair(0, GreaterThan(0));
+  EXPECT_EQ(
+      "whose both fields match, where the second field is a value "
+      "which is 1 more than 0",
+      Explain(explain_second, make_pair(0, 1)));
+}
+
+TEST(PairTest, MatchesCorrectly) {
+  pair<int, std::string> p(25, "foo");
+
+  // Both fields match.
+  EXPECT_THAT(p, Pair(25, "foo"));
+  EXPECT_THAT(p, Pair(Ge(20), HasSubstr("o")));
+
+  // 'first' doesn't match, but 'second' matches.
+  EXPECT_THAT(p, Not(Pair(42, "foo")));
+  EXPECT_THAT(p, Not(Pair(Lt(25), "foo")));
+
+  // 'first' matches, but 'second' doesn't match.
+  EXPECT_THAT(p, Not(Pair(25, "bar")));
+  EXPECT_THAT(p, Not(Pair(25, Not("foo"))));
+
+  // Neither field matches.
+  EXPECT_THAT(p, Not(Pair(13, "bar")));
+  EXPECT_THAT(p, Not(Pair(Lt(13), HasSubstr("a"))));
+}
+
+TEST(PairTest, WorksWithMoveOnly) {
+  pair<std::unique_ptr<int>, std::unique_ptr<int>> p;
+  p.second = std::make_unique<int>(7);
+  EXPECT_THAT(p, Pair(Eq(nullptr), Ne(nullptr)));
+}
+
+TEST(PairTest, SafelyCastsInnerMatchers) {
+  Matcher<int> is_positive = Gt(0);
+  Matcher<int> is_negative = Lt(0);
+  pair<char, bool> p('a', true);
+  EXPECT_THAT(p, Pair(is_positive, _));
+  EXPECT_THAT(p, Not(Pair(is_negative, _)));
+  EXPECT_THAT(p, Pair(_, is_positive));
+  EXPECT_THAT(p, Not(Pair(_, is_negative)));
+}
+
+TEST(PairTest, InsideContainsUsingMap) {
+  map<int, char> container;
+  container.insert(make_pair(1, 'a'));
+  container.insert(make_pair(2, 'b'));
+  container.insert(make_pair(4, 'c'));
+  EXPECT_THAT(container, Contains(Pair(1, 'a')));
+  EXPECT_THAT(container, Contains(Pair(1, _)));
+  EXPECT_THAT(container, Contains(Pair(_, 'a')));
+  EXPECT_THAT(container, Not(Contains(Pair(3, _))));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(FieldsAreTest);
+
+TEST(FieldsAreTest, MatchesCorrectly) {
+  std::tuple<int, std::string, double> p(25, "foo", .5);
+
+  // All fields match.
+  EXPECT_THAT(p, FieldsAre(25, "foo", .5));
+  EXPECT_THAT(p, FieldsAre(Ge(20), HasSubstr("o"), DoubleEq(.5)));
+
+  // Some don't match.
+  EXPECT_THAT(p, Not(FieldsAre(26, "foo", .5)));
+  EXPECT_THAT(p, Not(FieldsAre(25, "fo", .5)));
+  EXPECT_THAT(p, Not(FieldsAre(25, "foo", .6)));
+}
+
+TEST(FieldsAreTest, CanDescribeSelf) {
+  Matcher<const pair<std::string, int>&> m1 = FieldsAre("foo", 42);
+  EXPECT_EQ(
+      "has field #0 that is equal to \"foo\""
+      ", and has field #1 that is equal to 42",
+      Describe(m1));
+  EXPECT_EQ(
+      "has field #0 that isn't equal to \"foo\""
+      ", or has field #1 that isn't equal to 42",
+      DescribeNegation(m1));
+}
+
+TEST_P(FieldsAreTestP, CanExplainMatchResultTo) {
+  // The first one that fails is the one that gives the error.
+  Matcher<std::tuple<int, int, int>> m =
+      FieldsAre(GreaterThan(0), GreaterThan(0), GreaterThan(0));
+
+  EXPECT_EQ("whose field #0 does not match, which is 1 less than 0",
+            Explain(m, std::make_tuple(-1, -2, -3)));
+  EXPECT_EQ("whose field #1 does not match, which is 2 less than 0",
+            Explain(m, std::make_tuple(1, -2, -3)));
+  EXPECT_EQ("whose field #2 does not match, which is 3 less than 0",
+            Explain(m, std::make_tuple(1, 2, -3)));
+
+  // If they all match, we get a long explanation of success.
+  EXPECT_EQ(
+      "whose all elements match, "
+      "where field #0 is a value which is 1 more than 0"
+      ", and field #1 is a value which is 2 more than 0"
+      ", and field #2 is a value which is 3 more than 0",
+      Explain(m, std::make_tuple(1, 2, 3)));
+
+  // Only print those that have an explanation.
+  m = FieldsAre(GreaterThan(0), 0, GreaterThan(0));
+  EXPECT_EQ(
+      "whose all elements match, "
+      "where field #0 is a value which is 1 more than 0"
+      ", and field #2 is a value which is 3 more than 0",
+      Explain(m, std::make_tuple(1, 0, 3)));
+
+  // If only one has an explanation, then print that one.
+  m = FieldsAre(0, GreaterThan(0), 0);
+  EXPECT_EQ(
+      "whose all elements match, "
+      "where field #1 is a value which is 1 more than 0",
+      Explain(m, std::make_tuple(0, 1, 0)));
+}
+
+#if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606
+TEST(FieldsAreTest, StructuredBindings) {
+  // testing::FieldsAre can also match aggregates and such with C++17 and up.
+  struct MyType {
+    int i;
+    std::string str;
+  };
+  EXPECT_THAT((MyType{17, "foo"}), FieldsAre(Eq(17), HasSubstr("oo")));
+
+  // Test all the supported arities.
+  struct MyVarType1 {
+    int a;
+  };
+  EXPECT_THAT(MyVarType1{}, FieldsAre(0));
+  struct MyVarType2 {
+    int a, b;
+  };
+  EXPECT_THAT(MyVarType2{}, FieldsAre(0, 0));
+  struct MyVarType3 {
+    int a, b, c;
+  };
+  EXPECT_THAT(MyVarType3{}, FieldsAre(0, 0, 0));
+  struct MyVarType4 {
+    int a, b, c, d;
+  };
+  EXPECT_THAT(MyVarType4{}, FieldsAre(0, 0, 0, 0));
+  struct MyVarType5 {
+    int a, b, c, d, e;
+  };
+  EXPECT_THAT(MyVarType5{}, FieldsAre(0, 0, 0, 0, 0));
+  struct MyVarType6 {
+    int a, b, c, d, e, f;
+  };
+  EXPECT_THAT(MyVarType6{}, FieldsAre(0, 0, 0, 0, 0, 0));
+  struct MyVarType7 {
+    int a, b, c, d, e, f, g;
+  };
+  EXPECT_THAT(MyVarType7{}, FieldsAre(0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType8 {
+    int a, b, c, d, e, f, g, h;
+  };
+  EXPECT_THAT(MyVarType8{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType9 {
+    int a, b, c, d, e, f, g, h, i;
+  };
+  EXPECT_THAT(MyVarType9{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType10 {
+    int a, b, c, d, e, f, g, h, i, j;
+  };
+  EXPECT_THAT(MyVarType10{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType11 {
+    int a, b, c, d, e, f, g, h, i, j, k;
+  };
+  EXPECT_THAT(MyVarType11{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType12 {
+    int a, b, c, d, e, f, g, h, i, j, k, l;
+  };
+  EXPECT_THAT(MyVarType12{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType13 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m;
+  };
+  EXPECT_THAT(MyVarType13{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType14 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m, n;
+  };
+  EXPECT_THAT(MyVarType14{},
+              FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType15 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o;
+  };
+  EXPECT_THAT(MyVarType15{},
+              FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType16 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
+  };
+  EXPECT_THAT(MyVarType16{},
+              FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType17 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q;
+  };
+  EXPECT_THAT(MyVarType17{},
+              FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType18 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r;
+  };
+  EXPECT_THAT(MyVarType18{},
+              FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+  struct MyVarType19 {
+    int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s;
+  };
+  EXPECT_THAT(MyVarType19{}, FieldsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0));
+}
+#endif
+
+TEST(PairTest, UseGetInsteadOfMembers) {
+  PairWithGet pair{7, "ABC"};
+  EXPECT_THAT(pair, Pair(7, "ABC"));
+  EXPECT_THAT(pair, Pair(Ge(7), HasSubstr("AB")));
+  EXPECT_THAT(pair, Not(Pair(Lt(7), "ABC")));
+
+  std::vector<PairWithGet> v = {{11, "Foo"}, {29, "gMockIsBestMock"}};
+  EXPECT_THAT(v,
+              ElementsAre(Pair(11, std::string("Foo")), Pair(Ge(10), Not(""))));
+}
+
+// Tests StartsWith(s).
+
+TEST(StartsWithTest, MatchesStringWithGivenPrefix) {
+  const Matcher<const char*> m1 = StartsWith(std::string(""));
+  EXPECT_TRUE(m1.Matches("Hi"));
+  EXPECT_TRUE(m1.Matches(""));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const std::string&> m2 = StartsWith("Hi");
+  EXPECT_TRUE(m2.Matches("Hi"));
+  EXPECT_TRUE(m2.Matches("Hi Hi!"));
+  EXPECT_TRUE(m2.Matches("High"));
+  EXPECT_FALSE(m2.Matches("H"));
+  EXPECT_FALSE(m2.Matches(" Hi"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  const Matcher<internal::StringView> m_empty =
+      StartsWith(internal::StringView(""));
+  EXPECT_TRUE(m_empty.Matches(internal::StringView()));
+  EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
+  EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(StartsWithTest, CanDescribeSelf) {
+  Matcher<const std::string> m = StartsWith("Hi");
+  EXPECT_EQ("starts with \"Hi\"", Describe(m));
+}
+
+TEST(StartsWithTest, WorksWithStringMatcherOnStringViewMatchee) {
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  EXPECT_THAT(internal::StringView("talk to me goose"),
+              StartsWith(std::string("talk")));
+#else
+  GTEST_SKIP() << "Not applicable without internal::StringView.";
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+// Tests EndsWith(s).
+
+TEST(EndsWithTest, MatchesStringWithGivenSuffix) {
+  const Matcher<const char*> m1 = EndsWith("");
+  EXPECT_TRUE(m1.Matches("Hi"));
+  EXPECT_TRUE(m1.Matches(""));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const std::string&> m2 = EndsWith(std::string("Hi"));
+  EXPECT_TRUE(m2.Matches("Hi"));
+  EXPECT_TRUE(m2.Matches("Wow Hi Hi"));
+  EXPECT_TRUE(m2.Matches("Super Hi"));
+  EXPECT_FALSE(m2.Matches("i"));
+  EXPECT_FALSE(m2.Matches("Hi "));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  const Matcher<const internal::StringView&> m4 =
+      EndsWith(internal::StringView(""));
+  EXPECT_TRUE(m4.Matches("Hi"));
+  EXPECT_TRUE(m4.Matches(""));
+  EXPECT_TRUE(m4.Matches(internal::StringView()));
+  EXPECT_TRUE(m4.Matches(internal::StringView("")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(EndsWithTest, CanDescribeSelf) {
+  Matcher<const std::string> m = EndsWith("Hi");
+  EXPECT_EQ("ends with \"Hi\"", Describe(m));
+}
+
+// Tests WhenBase64Unescaped.
+
+TEST(WhenBase64UnescapedTest, MatchesUnescapedBase64Strings) {
+  const Matcher<const char*> m1 = WhenBase64Unescaped(EndsWith("!"));
+  EXPECT_FALSE(m1.Matches("invalid base64"));
+  EXPECT_FALSE(m1.Matches("aGVsbG8gd29ybGQ="));  // hello world
+  EXPECT_TRUE(m1.Matches("aGVsbG8gd29ybGQh"));   // hello world!
+  EXPECT_TRUE(m1.Matches("+/-_IQ"));             // \xfb\xff\xbf!
+
+  const Matcher<const std::string&> m2 = WhenBase64Unescaped(EndsWith("!"));
+  EXPECT_FALSE(m2.Matches("invalid base64"));
+  EXPECT_FALSE(m2.Matches("aGVsbG8gd29ybGQ="));  // hello world
+  EXPECT_TRUE(m2.Matches("aGVsbG8gd29ybGQh"));   // hello world!
+  EXPECT_TRUE(m2.Matches("+/-_IQ"));             // \xfb\xff\xbf!
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  const Matcher<const internal::StringView&> m3 =
+      WhenBase64Unescaped(EndsWith("!"));
+  EXPECT_FALSE(m3.Matches("invalid base64"));
+  EXPECT_FALSE(m3.Matches("aGVsbG8gd29ybGQ="));  // hello world
+  EXPECT_TRUE(m3.Matches("aGVsbG8gd29ybGQh"));   // hello world!
+  EXPECT_TRUE(m3.Matches("+/-_IQ"));             // \xfb\xff\xbf!
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(WhenBase64UnescapedTest, CanDescribeSelf) {
+  const Matcher<const char*> m = WhenBase64Unescaped(EndsWith("!"));
+  EXPECT_EQ("matches after Base64Unescape ends with \"!\"", Describe(m));
+}
+
+// Tests MatchesRegex().
+
+TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) {
+  const Matcher<const char*> m1 = MatchesRegex("a.*z");
+  EXPECT_TRUE(m1.Matches("az"));
+  EXPECT_TRUE(m1.Matches("abcz"));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const std::string&> m2 = MatchesRegex(new RE("a.*z"));
+  EXPECT_TRUE(m2.Matches("azbz"));
+  EXPECT_FALSE(m2.Matches("az1"));
+  EXPECT_FALSE(m2.Matches("1az"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  const Matcher<const internal::StringView&> m3 = MatchesRegex("a.*z");
+  EXPECT_TRUE(m3.Matches(internal::StringView("az")));
+  EXPECT_TRUE(m3.Matches(internal::StringView("abcz")));
+  EXPECT_FALSE(m3.Matches(internal::StringView("1az")));
+  EXPECT_FALSE(m3.Matches(internal::StringView()));
+  const Matcher<const internal::StringView&> m4 =
+      MatchesRegex(internal::StringView(""));
+  EXPECT_TRUE(m4.Matches(internal::StringView("")));
+  EXPECT_TRUE(m4.Matches(internal::StringView()));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(MatchesRegexTest, CanDescribeSelf) {
+  Matcher<const std::string> m1 = MatchesRegex(std::string("Hi.*"));
+  EXPECT_EQ("matches regular expression \"Hi.*\"", Describe(m1));
+
+  Matcher<const char*> m2 = MatchesRegex(new RE("a.*"));
+  EXPECT_EQ("matches regular expression \"a.*\"", Describe(m2));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  Matcher<const internal::StringView> m3 = MatchesRegex(new RE("0.*"));
+  EXPECT_EQ("matches regular expression \"0.*\"", Describe(m3));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+// Tests ContainsRegex().
+
+TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) {
+  const Matcher<const char*> m1 = ContainsRegex(std::string("a.*z"));
+  EXPECT_TRUE(m1.Matches("az"));
+  EXPECT_TRUE(m1.Matches("0abcz1"));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const std::string&> m2 = ContainsRegex(new RE("a.*z"));
+  EXPECT_TRUE(m2.Matches("azbz"));
+  EXPECT_TRUE(m2.Matches("az1"));
+  EXPECT_FALSE(m2.Matches("1a"));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  const Matcher<const internal::StringView&> m3 = ContainsRegex(new RE("a.*z"));
+  EXPECT_TRUE(m3.Matches(internal::StringView("azbz")));
+  EXPECT_TRUE(m3.Matches(internal::StringView("az1")));
+  EXPECT_FALSE(m3.Matches(internal::StringView("1a")));
+  EXPECT_FALSE(m3.Matches(internal::StringView()));
+  const Matcher<const internal::StringView&> m4 =
+      ContainsRegex(internal::StringView(""));
+  EXPECT_TRUE(m4.Matches(internal::StringView("")));
+  EXPECT_TRUE(m4.Matches(internal::StringView()));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+TEST(ContainsRegexTest, CanDescribeSelf) {
+  Matcher<const std::string> m1 = ContainsRegex("Hi.*");
+  EXPECT_EQ("contains regular expression \"Hi.*\"", Describe(m1));
+
+  Matcher<const char*> m2 = ContainsRegex(new RE("a.*"));
+  EXPECT_EQ("contains regular expression \"a.*\"", Describe(m2));
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  Matcher<const internal::StringView> m3 = ContainsRegex(new RE("0.*"));
+  EXPECT_EQ("contains regular expression \"0.*\"", Describe(m3));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
+// Tests for wide strings.
+#if GTEST_HAS_STD_WSTRING
+TEST(StdWideStrEqTest, MatchesEqual) {
+  Matcher<const wchar_t*> m = StrEq(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"Hello"));
+  EXPECT_FALSE(m.Matches(L"hello"));
+  EXPECT_FALSE(m.Matches(nullptr));
+
+  Matcher<const ::std::wstring&> m2 = StrEq(L"Hello");
+  EXPECT_TRUE(m2.Matches(L"Hello"));
+  EXPECT_FALSE(m2.Matches(L"Hi"));
+
+  Matcher<const ::std::wstring&> m3 = StrEq(L"\xD3\x576\x8D3\xC74D");
+  EXPECT_TRUE(m3.Matches(L"\xD3\x576\x8D3\xC74D"));
+  EXPECT_FALSE(m3.Matches(L"\xD3\x576\x8D3\xC74E"));
+
+  ::std::wstring str(L"01204500800");
+  str[3] = L'\0';
+  Matcher<const ::std::wstring&> m4 = StrEq(str);
+  EXPECT_TRUE(m4.Matches(str));
+  str[0] = str[6] = str[7] = str[9] = str[10] = L'\0';
+  Matcher<const ::std::wstring&> m5 = StrEq(str);
+  EXPECT_TRUE(m5.Matches(str));
+}
+
+TEST(StdWideStrEqTest, CanDescribeSelf) {
+  Matcher<::std::wstring> m = StrEq(L"Hi-\'\"?\\\a\b\f\n\r\t\v");
+  EXPECT_EQ("is equal to L\"Hi-\'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\"",
+            Describe(m));
+
+  Matcher<::std::wstring> m2 = StrEq(L"\xD3\x576\x8D3\xC74D");
+  EXPECT_EQ("is equal to L\"\\xD3\\x576\\x8D3\\xC74D\"", Describe(m2));
+
+  ::std::wstring str(L"01204500800");
+  str[3] = L'\0';
+  Matcher<const ::std::wstring&> m4 = StrEq(str);
+  EXPECT_EQ("is equal to L\"012\\04500800\"", Describe(m4));
+  str[0] = str[6] = str[7] = str[9] = str[10] = L'\0';
+  Matcher<const ::std::wstring&> m5 = StrEq(str);
+  EXPECT_EQ("is equal to L\"\\012\\045\\0\\08\\0\\0\"", Describe(m5));
+}
+
+TEST(StdWideStrNeTest, MatchesUnequalString) {
+  Matcher<const wchar_t*> m = StrNe(L"Hello");
+  EXPECT_TRUE(m.Matches(L""));
+  EXPECT_TRUE(m.Matches(nullptr));
+  EXPECT_FALSE(m.Matches(L"Hello"));
+
+  Matcher<::std::wstring> m2 = StrNe(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m2.Matches(L"hello"));
+  EXPECT_FALSE(m2.Matches(L"Hello"));
+}
+
+TEST(StdWideStrNeTest, CanDescribeSelf) {
+  Matcher<const wchar_t*> m = StrNe(L"Hi");
+  EXPECT_EQ("isn't equal to L\"Hi\"", Describe(m));
+}
+
+TEST(StdWideStrCaseEqTest, MatchesEqualStringIgnoringCase) {
+  Matcher<const wchar_t*> m = StrCaseEq(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"hello"));
+  EXPECT_FALSE(m.Matches(L"Hi"));
+  EXPECT_FALSE(m.Matches(nullptr));
+
+  Matcher<const ::std::wstring&> m2 = StrCaseEq(L"Hello");
+  EXPECT_TRUE(m2.Matches(L"hello"));
+  EXPECT_FALSE(m2.Matches(L"Hi"));
+}
+
+TEST(StdWideStrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
+  ::std::wstring str1(L"oabocdooeoo");
+  ::std::wstring str2(L"OABOCDOOEOO");
+  Matcher<const ::std::wstring&> m0 = StrCaseEq(str1);
+  EXPECT_FALSE(m0.Matches(str2 + ::std::wstring(1, L'\0')));
+
+  str1[3] = str2[3] = L'\0';
+  Matcher<const ::std::wstring&> m1 = StrCaseEq(str1);
+  EXPECT_TRUE(m1.Matches(str2));
+
+  str1[0] = str1[6] = str1[7] = str1[10] = L'\0';
+  str2[0] = str2[6] = str2[7] = str2[10] = L'\0';
+  Matcher<const ::std::wstring&> m2 = StrCaseEq(str1);
+  str1[9] = str2[9] = L'\0';
+  EXPECT_FALSE(m2.Matches(str2));
+
+  Matcher<const ::std::wstring&> m3 = StrCaseEq(str1);
+  EXPECT_TRUE(m3.Matches(str2));
+
+  EXPECT_FALSE(m3.Matches(str2 + L"x"));
+  str2.append(1, L'\0');
+  EXPECT_FALSE(m3.Matches(str2));
+  EXPECT_FALSE(m3.Matches(::std::wstring(str2, 0, 9)));
+}
+
+TEST(StdWideStrCaseEqTest, CanDescribeSelf) {
+  Matcher<::std::wstring> m = StrCaseEq(L"Hi");
+  EXPECT_EQ("is equal to (ignoring case) L\"Hi\"", Describe(m));
+}
+
+TEST(StdWideStrCaseNeTest, MatchesUnequalStringIgnoringCase) {
+  Matcher<const wchar_t*> m = StrCaseNe(L"Hello");
+  EXPECT_TRUE(m.Matches(L"Hi"));
+  EXPECT_TRUE(m.Matches(nullptr));
+  EXPECT_FALSE(m.Matches(L"Hello"));
+  EXPECT_FALSE(m.Matches(L"hello"));
+
+  Matcher<::std::wstring> m2 = StrCaseNe(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m2.Matches(L""));
+  EXPECT_FALSE(m2.Matches(L"Hello"));
+}
+
+TEST(StdWideStrCaseNeTest, CanDescribeSelf) {
+  Matcher<const wchar_t*> m = StrCaseNe(L"Hi");
+  EXPECT_EQ("isn't equal to (ignoring case) L\"Hi\"", Describe(m));
+}
+
+// Tests that HasSubstr() works for matching wstring-typed values.
+TEST(StdWideHasSubstrTest, WorksForStringClasses) {
+  const Matcher<::std::wstring> m1 = HasSubstr(L"foo");
+  EXPECT_TRUE(m1.Matches(::std::wstring(L"I love food.")));
+  EXPECT_FALSE(m1.Matches(::std::wstring(L"tofo")));
+
+  const Matcher<const ::std::wstring&> m2 = HasSubstr(L"foo");
+  EXPECT_TRUE(m2.Matches(::std::wstring(L"I love food.")));
+  EXPECT_FALSE(m2.Matches(::std::wstring(L"tofo")));
+}
+
+// Tests that HasSubstr() works for matching C-wide-string-typed values.
+TEST(StdWideHasSubstrTest, WorksForCStrings) {
+  const Matcher<wchar_t*> m1 = HasSubstr(L"foo");
+  EXPECT_TRUE(m1.Matches(const_cast<wchar_t*>(L"I love food.")));
+  EXPECT_FALSE(m1.Matches(const_cast<wchar_t*>(L"tofo")));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const wchar_t*> m2 = HasSubstr(L"foo");
+  EXPECT_TRUE(m2.Matches(L"I love food."));
+  EXPECT_FALSE(m2.Matches(L"tofo"));
+  EXPECT_FALSE(m2.Matches(nullptr));
+}
+
+// Tests that HasSubstr(s) describes itself properly.
+TEST(StdWideHasSubstrTest, CanDescribeSelf) {
+  Matcher<::std::wstring> m = HasSubstr(L"foo\n\"");
+  EXPECT_EQ("has substring L\"foo\\n\\\"\"", Describe(m));
+}
+
+// Tests StartsWith(s).
+
+TEST(StdWideStartsWithTest, MatchesStringWithGivenPrefix) {
+  const Matcher<const wchar_t*> m1 = StartsWith(::std::wstring(L""));
+  EXPECT_TRUE(m1.Matches(L"Hi"));
+  EXPECT_TRUE(m1.Matches(L""));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const ::std::wstring&> m2 = StartsWith(L"Hi");
+  EXPECT_TRUE(m2.Matches(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Hi Hi!"));
+  EXPECT_TRUE(m2.Matches(L"High"));
+  EXPECT_FALSE(m2.Matches(L"H"));
+  EXPECT_FALSE(m2.Matches(L" Hi"));
+}
+
+TEST(StdWideStartsWithTest, CanDescribeSelf) {
+  Matcher<const ::std::wstring> m = StartsWith(L"Hi");
+  EXPECT_EQ("starts with L\"Hi\"", Describe(m));
+}
+
+// Tests EndsWith(s).
+
+TEST(StdWideEndsWithTest, MatchesStringWithGivenSuffix) {
+  const Matcher<const wchar_t*> m1 = EndsWith(L"");
+  EXPECT_TRUE(m1.Matches(L"Hi"));
+  EXPECT_TRUE(m1.Matches(L""));
+  EXPECT_FALSE(m1.Matches(nullptr));
+
+  const Matcher<const ::std::wstring&> m2 = EndsWith(::std::wstring(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Wow Hi Hi"));
+  EXPECT_TRUE(m2.Matches(L"Super Hi"));
+  EXPECT_FALSE(m2.Matches(L"i"));
+  EXPECT_FALSE(m2.Matches(L"Hi "));
+}
+
+TEST(StdWideEndsWithTest, CanDescribeSelf) {
+  Matcher<const ::std::wstring> m = EndsWith(L"Hi");
+  EXPECT_EQ("ends with L\"Hi\"", Describe(m));
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+TEST(ExplainMatchResultTest, WorksWithPolymorphicMatcher) {
+  StringMatchResultListener listener1;
+  EXPECT_TRUE(ExplainMatchResult(PolymorphicIsEven(), 42, &listener1));
+  EXPECT_EQ("% 2 == 0", listener1.str());
+
+  StringMatchResultListener listener2;
+  EXPECT_FALSE(ExplainMatchResult(Ge(42), 1.5, &listener2));
+  EXPECT_EQ("", listener2.str());
+}
+
+TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) {
+  const Matcher<int> is_even = PolymorphicIsEven();
+  StringMatchResultListener listener1;
+  EXPECT_TRUE(ExplainMatchResult(is_even, 42, &listener1));
+  EXPECT_EQ("% 2 == 0", listener1.str());
+
+  const Matcher<const double&> is_zero = Eq(0);
+  StringMatchResultListener listener2;
+  EXPECT_FALSE(ExplainMatchResult(is_zero, 1.5, &listener2));
+  EXPECT_EQ("", listener2.str());
+}
+
+MATCHER(ConstructNoArg, "") { return true; }
+MATCHER_P(Construct1Arg, arg1, "") { return true; }
+MATCHER_P2(Construct2Args, arg1, arg2, "") { return true; }
+
+TEST(MatcherConstruct, ExplicitVsImplicit) {
+  {
+    // No arg constructor can be constructed with empty brace.
+    ConstructNoArgMatcher m = {};
+    (void)m;
+    // And with no args
+    ConstructNoArgMatcher m2;
+    (void)m2;
+  }
+  {
+    // The one arg constructor has an explicit constructor.
+    // This is to prevent the implicit conversion.
+    using M = Construct1ArgMatcherP<int>;
+    EXPECT_TRUE((std::is_constructible<M, int>::value));
+    EXPECT_FALSE((std::is_convertible<int, M>::value));
+  }
+  {
+    // Multiple arg matchers can be constructed with an implicit construction.
+    Construct2ArgsMatcherP2<int, double> m = {1, 2.2};
+    (void)m;
+  }
+}
+
+MATCHER_P(Really, inner_matcher, "") {
+  return ExplainMatchResult(inner_matcher, arg, result_listener);
+}
+
+TEST(ExplainMatchResultTest, WorksInsideMATCHER) {
+  EXPECT_THAT(0, Really(Eq(0)));
+}
+
+TEST(DescribeMatcherTest, WorksWithValue) {
+  EXPECT_EQ("is equal to 42", DescribeMatcher<int>(42));
+  EXPECT_EQ("isn't equal to 42", DescribeMatcher<int>(42, true));
+}
+
+TEST(DescribeMatcherTest, WorksWithMonomorphicMatcher) {
+  const Matcher<int> monomorphic = Le(0);
+  EXPECT_EQ("is <= 0", DescribeMatcher<int>(monomorphic));
+  EXPECT_EQ("isn't <= 0", DescribeMatcher<int>(monomorphic, true));
+}
+
+TEST(DescribeMatcherTest, WorksWithPolymorphicMatcher) {
+  EXPECT_EQ("is even", DescribeMatcher<int>(PolymorphicIsEven()));
+  EXPECT_EQ("is odd", DescribeMatcher<int>(PolymorphicIsEven(), true));
+}
+
+MATCHER_P(FieldIIs, inner_matcher, "") {
+  return ExplainMatchResult(inner_matcher, arg.i, result_listener);
+}
+
+#if GTEST_HAS_RTTI
+TEST(WhenDynamicCastToTest, SameType) {
+  Derived derived;
+  derived.i = 4;
+
+  // Right type. A pointer is passed down.
+  Base* as_base_ptr = &derived;
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(Not(IsNull())));
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(Pointee(FieldIIs(4))));
+  EXPECT_THAT(as_base_ptr,
+              Not(WhenDynamicCastTo<Derived*>(Pointee(FieldIIs(5)))));
+}
+
+TEST(WhenDynamicCastToTest, WrongTypes) {
+  Base base;
+  Derived derived;
+  OtherDerived other_derived;
+
+  // Wrong types. NULL is passed.
+  EXPECT_THAT(&base, Not(WhenDynamicCastTo<Derived*>(Pointee(_))));
+  EXPECT_THAT(&base, WhenDynamicCastTo<Derived*>(IsNull()));
+  Base* as_base_ptr = &derived;
+  EXPECT_THAT(as_base_ptr, Not(WhenDynamicCastTo<OtherDerived*>(Pointee(_))));
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<OtherDerived*>(IsNull()));
+  as_base_ptr = &other_derived;
+  EXPECT_THAT(as_base_ptr, Not(WhenDynamicCastTo<Derived*>(Pointee(_))));
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(IsNull()));
+}
+
+TEST(WhenDynamicCastToTest, AlreadyNull) {
+  // Already NULL.
+  Base* as_base_ptr = nullptr;
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(IsNull()));
+}
+
+struct AmbiguousCastTypes {
+  class VirtualDerived : public virtual Base {};
+  class DerivedSub1 : public VirtualDerived {};
+  class DerivedSub2 : public VirtualDerived {};
+  class ManyDerivedInHierarchy : public DerivedSub1, public DerivedSub2 {};
+};
+
+TEST(WhenDynamicCastToTest, AmbiguousCast) {
+  AmbiguousCastTypes::DerivedSub1 sub1;
+  AmbiguousCastTypes::ManyDerivedInHierarchy many_derived;
+  // Multiply derived from Base. dynamic_cast<> returns NULL.
+  Base* as_base_ptr =
+      static_cast<AmbiguousCastTypes::DerivedSub1*>(&many_derived);
+  EXPECT_THAT(as_base_ptr,
+              WhenDynamicCastTo<AmbiguousCastTypes::VirtualDerived*>(IsNull()));
+  as_base_ptr = &sub1;
+  EXPECT_THAT(
+      as_base_ptr,
+      WhenDynamicCastTo<AmbiguousCastTypes::VirtualDerived*>(Not(IsNull())));
+}
+
+TEST(WhenDynamicCastToTest, Describe) {
+  Matcher<Base*> matcher = WhenDynamicCastTo<Derived*>(Pointee(_));
+  const std::string prefix =
+      "when dynamic_cast to " + internal::GetTypeName<Derived*>() + ", ";
+  EXPECT_EQ(prefix + "points to a value that is anything", Describe(matcher));
+  EXPECT_EQ(prefix + "does not point to a value that is anything",
+            DescribeNegation(matcher));
+}
+
+TEST(WhenDynamicCastToTest, Explain) {
+  Matcher<Base*> matcher = WhenDynamicCastTo<Derived*>(Pointee(_));
+  Base* null = nullptr;
+  EXPECT_THAT(Explain(matcher, null), HasSubstr("NULL"));
+  Derived derived;
+  EXPECT_TRUE(matcher.Matches(&derived));
+  EXPECT_THAT(Explain(matcher, &derived), HasSubstr("which points to "));
+
+  // With references, the matcher itself can fail. Test for that one.
+  Matcher<const Base&> ref_matcher = WhenDynamicCastTo<const OtherDerived&>(_);
+  EXPECT_THAT(Explain(ref_matcher, derived),
+              HasSubstr("which cannot be dynamic_cast"));
+}
+
+TEST(WhenDynamicCastToTest, GoodReference) {
+  Derived derived;
+  derived.i = 4;
+  Base& as_base_ref = derived;
+  EXPECT_THAT(as_base_ref, WhenDynamicCastTo<const Derived&>(FieldIIs(4)));
+  EXPECT_THAT(as_base_ref, WhenDynamicCastTo<const Derived&>(Not(FieldIIs(5))));
+}
+
+TEST(WhenDynamicCastToTest, BadReference) {
+  Derived derived;
+  Base& as_base_ref = derived;
+  EXPECT_THAT(as_base_ref, Not(WhenDynamicCastTo<const OtherDerived&>(_)));
+}
+#endif  // GTEST_HAS_RTTI
+
+class DivisibleByImpl {
+ public:
+  explicit DivisibleByImpl(int a_divider) : divider_(a_divider) {}
+
+  // For testing using ExplainMatchResultTo() with polymorphic matchers.
+  template <typename T>
+  bool MatchAndExplain(const T& n, MatchResultListener* listener) const {
+    *listener << "which is " << (n % divider_) << " modulo " << divider_;
+    return (n % divider_) == 0;
+  }
+
+  void DescribeTo(ostream* os) const { *os << "is divisible by " << divider_; }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "is not divisible by " << divider_;
+  }
+
+  void set_divider(int a_divider) { divider_ = a_divider; }
+  int divider() const { return divider_; }
+
+ private:
+  int divider_;
+};
+
+PolymorphicMatcher<DivisibleByImpl> DivisibleBy(int n) {
+  return MakePolymorphicMatcher(DivisibleByImpl(n));
+}
+
+// Tests that when AllOf() fails, only the first failing matcher is
+// asked to explain why.
+TEST(ExplainMatchResultTest, AllOf_False_False) {
+  const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
+  EXPECT_EQ("which is 1 modulo 4", Explain(m, 5));
+}
+
+// Tests that when AllOf() fails, only the first failing matcher is
+// asked to explain why.
+TEST(ExplainMatchResultTest, AllOf_False_True) {
+  const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
+  EXPECT_EQ("which is 2 modulo 4", Explain(m, 6));
+}
+
+// Tests that when AllOf() fails, only the first failing matcher is
+// asked to explain why.
+TEST(ExplainMatchResultTest, AllOf_True_False) {
+  const Matcher<int> m = AllOf(Ge(1), DivisibleBy(3));
+  EXPECT_EQ("which is 2 modulo 3", Explain(m, 5));
+}
+
+// Tests that when AllOf() succeeds, all matchers are asked to explain
+// why.
+TEST(ExplainMatchResultTest, AllOf_True_True) {
+  const Matcher<int> m = AllOf(DivisibleBy(2), DivisibleBy(3));
+  EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
+}
+
+// Tests that when AllOf() succeeds, but matchers have no explanation,
+// the matcher description is used.
+TEST(ExplainMatchResultTest, AllOf_True_True_2) {
+  const Matcher<int> m = AllOf(Ge(2), Le(3));
+  EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
+
+TEST_P(ExplainmatcherResultTestP, MonomorphicMatcher) {
+  const Matcher<int> m = GreaterThan(5);
+  EXPECT_EQ("which is 1 more than 5", Explain(m, 6));
+}
+
+// Tests PolymorphicMatcher::mutable_impl().
+TEST(PolymorphicMatcherTest, CanAccessMutableImpl) {
+  PolymorphicMatcher<DivisibleByImpl> m(DivisibleByImpl(42));
+  DivisibleByImpl& impl = m.mutable_impl();
+  EXPECT_EQ(42, impl.divider());
+
+  impl.set_divider(0);
+  EXPECT_EQ(0, m.mutable_impl().divider());
+}
+
+// Tests PolymorphicMatcher::impl().
+TEST(PolymorphicMatcherTest, CanAccessImpl) {
+  const PolymorphicMatcher<DivisibleByImpl> m(DivisibleByImpl(42));
+  const DivisibleByImpl& impl = m.impl();
+  EXPECT_EQ(42, impl.divider());
+}
+
+}  // namespace
+}  // namespace gmock_matchers_test
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4244 4100
diff --git a/3rd-party/googletest/googlemock/test/gmock-matchers-containers_test.cc b/3rd-party/googletest/googlemock/test/gmock-matchers-containers_test.cc
new file mode 100644
index 0000000..acea4ec
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-matchers-containers_test.cc
@@ -0,0 +1,3148 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests some commonly used argument matchers.
+
+#include <algorithm>
+#include <array>
+#include <deque>
+#include <forward_list>
+#include <iterator>
+#include <list>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
+// possible loss of data and C4100, unreferenced local parameter
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
+
+#include "test/gmock-matchers_test.h"
+
+namespace testing {
+namespace gmock_matchers_test {
+namespace {
+
+std::vector<std::unique_ptr<int>> MakeUniquePtrs(const std::vector<int>& ints) {
+  std::vector<std::unique_ptr<int>> pointers;
+  for (int i : ints) pointers.emplace_back(new int(i));
+  return pointers;
+}
+
+std::string OfType(const std::string& type_name) {
+#if GTEST_HAS_RTTI
+  return IsReadableTypeName(type_name) ? " (of type " + type_name + ")" : "";
+#else
+  return "";
+#endif
+}
+
+TEST(ContainsTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(Contains(Pointee(2))));
+  helper.Call(MakeUniquePtrs({1, 2}));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(ElementsAreTest);
+
+// Tests the variadic version of the ElementsAreMatcher
+TEST(ElementsAreTest, HugeMatcher) {
+  vector<int> test_vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+
+  EXPECT_THAT(test_vector,
+              ElementsAre(Eq(1), Eq(2), Lt(13), Eq(4), Eq(5), Eq(6), Eq(7),
+                          Eq(8), Eq(9), Eq(10), Gt(1), Eq(12)));
+}
+
+// Tests the variadic version of the UnorderedElementsAreMatcher
+TEST(ElementsAreTest, HugeMatcherStr) {
+  vector<std::string> test_vector{
+      "literal_string", "", "", "", "", "", "", "", "", "", "", ""};
+
+  EXPECT_THAT(test_vector, UnorderedElementsAre("literal_string", _, _, _, _, _,
+                                                _, _, _, _, _, _));
+}
+
+// Tests the variadic version of the UnorderedElementsAreMatcher
+TEST(ElementsAreTest, HugeMatcherUnordered) {
+  vector<int> test_vector{2, 1, 8, 5, 4, 6, 7, 3, 9, 12, 11, 10};
+
+  EXPECT_THAT(test_vector, UnorderedElementsAre(
+                               Eq(2), Eq(1), Gt(7), Eq(5), Eq(4), Eq(6), Eq(7),
+                               Eq(3), Eq(9), Eq(12), Eq(11), Ne(122)));
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
+// matches the matcher.
+TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {
+  ASSERT_THAT(5, Ge(2)) << "This should succeed.";
+  ASSERT_THAT("Foo", EndsWith("oo"));
+  EXPECT_THAT(2, AllOf(Le(7), Ge(0))) << "This should succeed too.";
+  EXPECT_THAT("Hello", StartsWith("Hell"));
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
+// doesn't match the matcher.
+TEST(MatcherAssertionTest, WorksWhenMatcherIsNotSatisfied) {
+  // 'n' must be static as it is used in an EXPECT_FATAL_FAILURE(),
+  // which cannot reference auto variables.
+  static unsigned short n;  // NOLINT
+  n = 5;
+
+  EXPECT_FATAL_FAILURE(ASSERT_THAT(n, Gt(10)),
+                       "Value of: n\n"
+                       "Expected: is > 10\n"
+                       "  Actual: 5" +
+                           OfType("unsigned short"));
+  n = 0;
+  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(n, AllOf(Le(7), Ge(5))),
+                          "Value of: n\n"
+                          "Expected: (is <= 7) and (is >= 5)\n"
+                          "  Actual: 0" +
+                              OfType("unsigned short"));
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the argument
+// has a reference type.
+TEST(MatcherAssertionTest, WorksForByRefArguments) {
+  // We use a static variable here as EXPECT_FATAL_FAILURE() cannot
+  // reference auto variables.
+  static int n;
+  n = 0;
+  EXPECT_THAT(n, AllOf(Le(7), Ref(n)));
+  EXPECT_FATAL_FAILURE(ASSERT_THAT(n, Not(Ref(n))),
+                       "Value of: n\n"
+                       "Expected: does not reference the variable @");
+  // Tests the "Actual" part.
+  EXPECT_FATAL_FAILURE(ASSERT_THAT(n, Not(Ref(n))),
+                       "Actual: 0" + OfType("int") + ", which is located @");
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the matcher is
+// monomorphic.
+TEST(MatcherAssertionTest, WorksForMonomorphicMatcher) {
+  Matcher<const char*> starts_with_he = StartsWith("he");
+  ASSERT_THAT("hello", starts_with_he);
+
+  Matcher<const std::string&> ends_with_ok = EndsWith("ok");
+  ASSERT_THAT("book", ends_with_ok);
+  const std::string bad = "bad";
+  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(bad, ends_with_ok),
+                          "Value of: bad\n"
+                          "Expected: ends with \"ok\"\n"
+                          "  Actual: \"bad\"");
+  Matcher<int> is_greater_than_5 = Gt(5);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(5, is_greater_than_5),
+                          "Value of: 5\n"
+                          "Expected: is > 5\n"
+                          "  Actual: 5" +
+                              OfType("int"));
+}
+
+TEST(PointeeTest, RawPointer) {
+  const Matcher<int*> m = Pointee(Ge(0));
+
+  int n = 1;
+  EXPECT_TRUE(m.Matches(&n));
+  n = -1;
+  EXPECT_FALSE(m.Matches(&n));
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointeeTest, RawPointerToConst) {
+  const Matcher<const double*> m = Pointee(Ge(0));
+
+  double x = 1;
+  EXPECT_TRUE(m.Matches(&x));
+  x = -1;
+  EXPECT_FALSE(m.Matches(&x));
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointeeTest, ReferenceToConstRawPointer) {
+  const Matcher<int* const&> m = Pointee(Ge(0));
+
+  int n = 1;
+  EXPECT_TRUE(m.Matches(&n));
+  n = -1;
+  EXPECT_FALSE(m.Matches(&n));
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointeeTest, ReferenceToNonConstRawPointer) {
+  const Matcher<double*&> m = Pointee(Ge(0));
+
+  double x = 1.0;
+  double* p = &x;
+  EXPECT_TRUE(m.Matches(p));
+  x = -1;
+  EXPECT_FALSE(m.Matches(p));
+  p = nullptr;
+  EXPECT_FALSE(m.Matches(p));
+}
+
+TEST(PointeeTest, SmartPointer) {
+  const Matcher<std::unique_ptr<int>> m = Pointee(Ge(0));
+
+  std::unique_ptr<int> n(new int(1));
+  EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(PointeeTest, SmartPointerToConst) {
+  const Matcher<std::unique_ptr<const int>> m = Pointee(Ge(0));
+
+  // There's no implicit conversion from unique_ptr<int> to const
+  // unique_ptr<const int>, so we must pass a unique_ptr<const int> into the
+  // matcher.
+  std::unique_ptr<const int> n(new int(1));
+  EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(PointerTest, RawPointer) {
+  int n = 1;
+  const Matcher<int*> m = Pointer(Eq(&n));
+
+  EXPECT_TRUE(m.Matches(&n));
+
+  int* p = nullptr;
+  EXPECT_FALSE(m.Matches(p));
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointerTest, RawPointerToConst) {
+  int n = 1;
+  const Matcher<const int*> m = Pointer(Eq(&n));
+
+  EXPECT_TRUE(m.Matches(&n));
+
+  int* p = nullptr;
+  EXPECT_FALSE(m.Matches(p));
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointerTest, SmartPointer) {
+  std::unique_ptr<int> n(new int(10));
+  int* raw_n = n.get();
+  const Matcher<std::unique_ptr<int>> m = Pointer(Eq(raw_n));
+
+  EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(PointerTest, SmartPointerToConst) {
+  std::unique_ptr<const int> n(new int(10));
+  const int* raw_n = n.get();
+  const Matcher<std::unique_ptr<const int>> m = Pointer(Eq(raw_n));
+
+  // There's no implicit conversion from unique_ptr<int> to const
+  // unique_ptr<const int>, so we must pass a unique_ptr<const int> into the
+  // matcher.
+  std::unique_ptr<const int> p(new int(10));
+  EXPECT_FALSE(m.Matches(p));
+}
+
+// Minimal const-propagating pointer.
+template <typename T>
+class ConstPropagatingPtr {
+ public:
+  typedef T element_type;
+
+  ConstPropagatingPtr() : val_() {}
+  explicit ConstPropagatingPtr(T* t) : val_(t) {}
+  ConstPropagatingPtr(const ConstPropagatingPtr& other) : val_(other.val_) {}
+
+  T* get() { return val_; }
+  T& operator*() { return *val_; }
+  // Most smart pointers return non-const T* and T& from the next methods.
+  const T* get() const { return val_; }
+  const T& operator*() const { return *val_; }
+
+ private:
+  T* val_;
+};
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(PointeeTest);
+
+TEST(PointeeTest, WorksWithConstPropagatingPointers) {
+  const Matcher<ConstPropagatingPtr<int>> m = Pointee(Lt(5));
+  int three = 3;
+  const ConstPropagatingPtr<int> co(&three);
+  ConstPropagatingPtr<int> o(&three);
+  EXPECT_TRUE(m.Matches(o));
+  EXPECT_TRUE(m.Matches(co));
+  *o = 6;
+  EXPECT_FALSE(m.Matches(o));
+  EXPECT_FALSE(m.Matches(ConstPropagatingPtr<int>()));
+}
+
+TEST(PointeeTest, NeverMatchesNull) {
+  const Matcher<const char*> m = Pointee(_);
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+// Tests that we can write Pointee(value) instead of Pointee(Eq(value)).
+TEST(PointeeTest, MatchesAgainstAValue) {
+  const Matcher<int*> m = Pointee(5);
+
+  int n = 5;
+  EXPECT_TRUE(m.Matches(&n));
+  n = -1;
+  EXPECT_FALSE(m.Matches(&n));
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointeeTest, CanDescribeSelf) {
+  const Matcher<int*> m = Pointee(Gt(3));
+  EXPECT_EQ("points to a value that is > 3", Describe(m));
+  EXPECT_EQ("does not point to a value that is > 3", DescribeNegation(m));
+}
+
+TEST_P(PointeeTestP, CanExplainMatchResult) {
+  const Matcher<const std::string*> m = Pointee(StartsWith("Hi"));
+
+  EXPECT_EQ("", Explain(m, static_cast<const std::string*>(nullptr)));
+
+  const Matcher<long*> m2 = Pointee(GreaterThan(1));  // NOLINT
+  long n = 3;                                         // NOLINT
+  EXPECT_EQ("which points to 3" + OfType("long") + ", which is 2 more than 1",
+            Explain(m2, &n));
+}
+
+TEST(PointeeTest, AlwaysExplainsPointee) {
+  const Matcher<int*> m = Pointee(0);
+  int n = 42;
+  EXPECT_EQ("which points to 42" + OfType("int"), Explain(m, &n));
+}
+
+// An uncopyable class.
+class Uncopyable {
+ public:
+  Uncopyable() : value_(-1) {}
+  explicit Uncopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+  void set_value(int i) { value_ = i; }
+
+ private:
+  int value_;
+  Uncopyable(const Uncopyable&) = delete;
+  Uncopyable& operator=(const Uncopyable&) = delete;
+};
+
+// Returns true if and only if x.value() is positive.
+bool ValueIsPositive(const Uncopyable& x) { return x.value() > 0; }
+
+MATCHER_P(UncopyableIs, inner_matcher, "") {
+  return ExplainMatchResult(inner_matcher, arg.value(), result_listener);
+}
+
+// A user-defined struct for testing Field().
+struct AStruct {
+  AStruct() : x(0), y(1.0), z(5), p(nullptr) {}
+  AStruct(const AStruct& rhs)
+      : x(rhs.x), y(rhs.y), z(rhs.z.value()), p(rhs.p) {}
+
+  int x;           // A non-const field.
+  const double y;  // A const field.
+  Uncopyable z;    // An uncopyable field.
+  const char* p;   // A pointer field.
+};
+
+// A derived struct for testing Field().
+struct DerivedStruct : public AStruct {
+  char ch;
+};
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(FieldTest);
+
+// Tests that Field(&Foo::field, ...) works when field is non-const.
+TEST(FieldTest, WorksForNonConstField) {
+  Matcher<AStruct> m = Field(&AStruct::x, Ge(0));
+  Matcher<AStruct> m_with_name = Field("x", &AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_TRUE(m_with_name.Matches(a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_FALSE(m_with_name.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when field is const.
+TEST(FieldTest, WorksForConstField) {
+  AStruct a;
+
+  Matcher<AStruct> m = Field(&AStruct::y, Ge(0.0));
+  Matcher<AStruct> m_with_name = Field("y", &AStruct::y, Ge(0.0));
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_TRUE(m_with_name.Matches(a));
+  m = Field(&AStruct::y, Le(0.0));
+  m_with_name = Field("y", &AStruct::y, Le(0.0));
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_FALSE(m_with_name.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when field is not copyable.
+TEST(FieldTest, WorksForUncopyableField) {
+  AStruct a;
+
+  Matcher<AStruct> m = Field(&AStruct::z, Truly(ValueIsPositive));
+  EXPECT_TRUE(m.Matches(a));
+  m = Field(&AStruct::z, Not(Truly(ValueIsPositive)));
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when field is a pointer.
+TEST(FieldTest, WorksForPointerField) {
+  // Matching against NULL.
+  Matcher<AStruct> m = Field(&AStruct::p, static_cast<const char*>(nullptr));
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.p = "hi";
+  EXPECT_FALSE(m.Matches(a));
+
+  // Matching a pointer that is not NULL.
+  m = Field(&AStruct::p, StartsWith("hi"));
+  a.p = "hill";
+  EXPECT_TRUE(m.Matches(a));
+  a.p = "hole";
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field() works when the object is passed by reference.
+TEST(FieldTest, WorksForByRefArgument) {
+  Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when the argument's type
+// is a sub-type of Foo.
+TEST(FieldTest, WorksForArgumentOfSubType) {
+  // Note that the matcher expects DerivedStruct but we say AStruct
+  // inside Field().
+  Matcher<const DerivedStruct&> m = Field(&AStruct::x, Ge(0));
+
+  DerivedStruct d;
+  EXPECT_TRUE(m.Matches(d));
+  d.x = -1;
+  EXPECT_FALSE(m.Matches(d));
+}
+
+// Tests that Field(&Foo::field, m) works when field's type and m's
+// argument type are compatible but not the same.
+TEST(FieldTest, WorksForCompatibleMatcherType) {
+  // The field is an int, but the inner matcher expects a signed char.
+  Matcher<const AStruct&> m = Field(&AStruct::x, Matcher<signed char>(Ge(0)));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field() can describe itself.
+TEST(FieldTest, CanDescribeSelf) {
+  Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
+
+  EXPECT_EQ("is an object whose given field is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given field isn't >= 0", DescribeNegation(m));
+}
+
+TEST(FieldTest, CanDescribeSelfWithFieldName) {
+  Matcher<const AStruct&> m = Field("field_name", &AStruct::x, Ge(0));
+
+  EXPECT_EQ("is an object whose field `field_name` is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose field `field_name` isn't >= 0",
+            DescribeNegation(m));
+}
+
+// Tests that Field() can explain the match result.
+TEST_P(FieldTestP, CanExplainMatchResult) {
+  Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  a.x = 1;
+  EXPECT_EQ("whose given field is 1" + OfType("int"), Explain(m, a));
+
+  m = Field(&AStruct::x, GreaterThan(0));
+  EXPECT_EQ(
+      "whose given field is 1" + OfType("int") + ", which is 1 more than 0",
+      Explain(m, a));
+}
+
+TEST_P(FieldTestP, CanExplainMatchResultWithFieldName) {
+  Matcher<const AStruct&> m = Field("field_name", &AStruct::x, Ge(0));
+
+  AStruct a;
+  a.x = 1;
+  EXPECT_EQ("whose field `field_name` is 1" + OfType("int"), Explain(m, a));
+
+  m = Field("field_name", &AStruct::x, GreaterThan(0));
+  EXPECT_EQ("whose field `field_name` is 1" + OfType("int") +
+                ", which is 1 more than 0",
+            Explain(m, a));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(FieldForPointerTest);
+
+// Tests that Field() works when the argument is a pointer to const.
+TEST(FieldForPointerTest, WorksForPointerToConst) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(&a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Field() works when the argument is a pointer to non-const.
+TEST(FieldForPointerTest, WorksForPointerToNonConst) {
+  Matcher<AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(&a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Field() works when the argument is a reference to a const pointer.
+TEST(FieldForPointerTest, WorksForReferenceToConstPointer) {
+  Matcher<AStruct* const&> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(&a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Field() does not match the NULL pointer.
+TEST(FieldForPointerTest, DoesNotMatchNull) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, _);
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+// Tests that Field(&Foo::field, ...) works when the argument's type
+// is a sub-type of const Foo*.
+TEST(FieldForPointerTest, WorksForArgumentOfSubType) {
+  // Note that the matcher expects DerivedStruct but we say AStruct
+  // inside Field().
+  Matcher<DerivedStruct*> m = Field(&AStruct::x, Ge(0));
+
+  DerivedStruct d;
+  EXPECT_TRUE(m.Matches(&d));
+  d.x = -1;
+  EXPECT_FALSE(m.Matches(&d));
+}
+
+// Tests that Field() can describe itself when used to match a pointer.
+TEST(FieldForPointerTest, CanDescribeSelf) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  EXPECT_EQ("is an object whose given field is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given field isn't >= 0", DescribeNegation(m));
+}
+
+TEST(FieldForPointerTest, CanDescribeSelfWithFieldName) {
+  Matcher<const AStruct*> m = Field("field_name", &AStruct::x, Ge(0));
+
+  EXPECT_EQ("is an object whose field `field_name` is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose field `field_name` isn't >= 0",
+            DescribeNegation(m));
+}
+
+// Tests that Field() can explain the result of matching a pointer.
+TEST_P(FieldForPointerTestP, CanExplainMatchResult) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  a.x = 1;
+  EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(nullptr)));
+  EXPECT_EQ("which points to an object whose given field is 1" + OfType("int"),
+            Explain(m, &a));
+
+  m = Field(&AStruct::x, GreaterThan(0));
+  EXPECT_EQ("which points to an object whose given field is 1" + OfType("int") +
+                ", which is 1 more than 0",
+            Explain(m, &a));
+}
+
+TEST_P(FieldForPointerTestP, CanExplainMatchResultWithFieldName) {
+  Matcher<const AStruct*> m = Field("field_name", &AStruct::x, Ge(0));
+
+  AStruct a;
+  a.x = 1;
+  EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(nullptr)));
+  EXPECT_EQ(
+      "which points to an object whose field `field_name` is 1" + OfType("int"),
+      Explain(m, &a));
+
+  m = Field("field_name", &AStruct::x, GreaterThan(0));
+  EXPECT_EQ("which points to an object whose field `field_name` is 1" +
+                OfType("int") + ", which is 1 more than 0",
+            Explain(m, &a));
+}
+
+// A user-defined class for testing Property().
+class AClass {
+ public:
+  AClass() : n_(0) {}
+
+  // A getter that returns a non-reference.
+  int n() const { return n_; }
+
+  void set_n(int new_n) { n_ = new_n; }
+
+  // A getter that returns a reference to const.
+  const std::string& s() const { return s_; }
+
+  const std::string& s_ref() const& { return s_; }
+
+  void set_s(const std::string& new_s) { s_ = new_s; }
+
+  // A getter that returns a reference to non-const.
+  double& x() const { return x_; }
+
+ private:
+  int n_;
+  std::string s_;
+
+  static double x_;
+};
+
+double AClass::x_ = 0.0;
+
+// A derived class for testing Property().
+class DerivedClass : public AClass {
+ public:
+  int k() const { return k_; }
+
+ private:
+  int k_;
+};
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(PropertyTest);
+
+// Tests that Property(&Foo::property, ...) works when property()
+// returns a non-reference.
+TEST(PropertyTest, WorksForNonReferenceProperty) {
+  Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
+  Matcher<const AClass&> m_with_name = Property("n", &AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_TRUE(m_with_name.Matches(a));
+
+  a.set_n(-1);
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_FALSE(m_with_name.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when property()
+// returns a reference to const.
+TEST(PropertyTest, WorksForReferenceToConstProperty) {
+  Matcher<const AClass&> m = Property(&AClass::s, StartsWith("hi"));
+  Matcher<const AClass&> m_with_name =
+      Property("s", &AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_TRUE(m_with_name.Matches(a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_FALSE(m_with_name.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when property() is
+// ref-qualified.
+TEST(PropertyTest, WorksForRefQualifiedProperty) {
+  Matcher<const AClass&> m = Property(&AClass::s_ref, StartsWith("hi"));
+  Matcher<const AClass&> m_with_name =
+      Property("s", &AClass::s_ref, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_TRUE(m_with_name.Matches(a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_FALSE(m_with_name.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when property()
+// returns a reference to non-const.
+TEST(PropertyTest, WorksForReferenceToNonConstProperty) {
+  double x = 0.0;
+  AClass a;
+
+  Matcher<const AClass&> m = Property(&AClass::x, Ref(x));
+  EXPECT_FALSE(m.Matches(a));
+
+  m = Property(&AClass::x, Not(Ref(x)));
+  EXPECT_TRUE(m.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when the argument is
+// passed by value.
+TEST(PropertyTest, WorksForByValueArgument) {
+  Matcher<AClass> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when the argument's
+// type is a sub-type of Foo.
+TEST(PropertyTest, WorksForArgumentOfSubType) {
+  // The matcher expects a DerivedClass, but inside the Property() we
+  // say AClass.
+  Matcher<const DerivedClass&> m = Property(&AClass::n, Ge(0));
+
+  DerivedClass d;
+  d.set_n(1);
+  EXPECT_TRUE(m.Matches(d));
+
+  d.set_n(-1);
+  EXPECT_FALSE(m.Matches(d));
+}
+
+// Tests that Property(&Foo::property, m) works when property()'s type
+// and m's argument type are compatible but different.
+TEST(PropertyTest, WorksForCompatibleMatcherType) {
+  // n() returns an int but the inner matcher expects a signed char.
+  Matcher<const AClass&> m = Property(&AClass::n, Matcher<signed char>(Ge(0)));
+
+  Matcher<const AClass&> m_with_name =
+      Property("n", &AClass::n, Matcher<signed char>(Ge(0)));
+
+  AClass a;
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_TRUE(m_with_name.Matches(a));
+  a.set_n(-1);
+  EXPECT_FALSE(m.Matches(a));
+  EXPECT_FALSE(m_with_name.Matches(a));
+}
+
+// Tests that Property() can describe itself.
+TEST(PropertyTest, CanDescribeSelf) {
+  Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
+
+  EXPECT_EQ("is an object whose given property is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given property isn't >= 0",
+            DescribeNegation(m));
+}
+
+TEST(PropertyTest, CanDescribeSelfWithPropertyName) {
+  Matcher<const AClass&> m = Property("fancy_name", &AClass::n, Ge(0));
+
+  EXPECT_EQ("is an object whose property `fancy_name` is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose property `fancy_name` isn't >= 0",
+            DescribeNegation(m));
+}
+
+// Tests that Property() can explain the match result.
+TEST_P(PropertyTestP, CanExplainMatchResult) {
+  Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_EQ("whose given property is 1" + OfType("int"), Explain(m, a));
+
+  m = Property(&AClass::n, GreaterThan(0));
+  EXPECT_EQ(
+      "whose given property is 1" + OfType("int") + ", which is 1 more than 0",
+      Explain(m, a));
+}
+
+TEST_P(PropertyTestP, CanExplainMatchResultWithPropertyName) {
+  Matcher<const AClass&> m = Property("fancy_name", &AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_EQ("whose property `fancy_name` is 1" + OfType("int"), Explain(m, a));
+
+  m = Property("fancy_name", &AClass::n, GreaterThan(0));
+  EXPECT_EQ("whose property `fancy_name` is 1" + OfType("int") +
+                ", which is 1 more than 0",
+            Explain(m, a));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(PropertyForPointerTest);
+
+// Tests that Property() works when the argument is a pointer to const.
+TEST(PropertyForPointerTest, WorksForPointerToConst) {
+  Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_TRUE(m.Matches(&a));
+
+  a.set_n(-1);
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Property() works when the argument is a pointer to non-const.
+TEST(PropertyForPointerTest, WorksForPointerToNonConst) {
+  Matcher<AClass*> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(&a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Property() works when the argument is a reference to a
+// const pointer.
+TEST(PropertyForPointerTest, WorksForReferenceToConstPointer) {
+  Matcher<AClass* const&> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(&a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Property() does not match the NULL pointer.
+TEST(PropertyForPointerTest, WorksForReferenceToNonConstProperty) {
+  Matcher<const AClass*> m = Property(&AClass::x, _);
+  EXPECT_FALSE(m.Matches(nullptr));
+}
+
+// Tests that Property(&Foo::property, ...) works when the argument's
+// type is a sub-type of const Foo*.
+TEST(PropertyForPointerTest, WorksForArgumentOfSubType) {
+  // The matcher expects a DerivedClass, but inside the Property() we
+  // say AClass.
+  Matcher<const DerivedClass*> m = Property(&AClass::n, Ge(0));
+
+  DerivedClass d;
+  d.set_n(1);
+  EXPECT_TRUE(m.Matches(&d));
+
+  d.set_n(-1);
+  EXPECT_FALSE(m.Matches(&d));
+}
+
+// Tests that Property() can describe itself when used to match a pointer.
+TEST(PropertyForPointerTest, CanDescribeSelf) {
+  Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
+
+  EXPECT_EQ("is an object whose given property is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given property isn't >= 0",
+            DescribeNegation(m));
+}
+
+TEST(PropertyForPointerTest, CanDescribeSelfWithPropertyDescription) {
+  Matcher<const AClass*> m = Property("fancy_name", &AClass::n, Ge(0));
+
+  EXPECT_EQ("is an object whose property `fancy_name` is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose property `fancy_name` isn't >= 0",
+            DescribeNegation(m));
+}
+
+// Tests that Property() can explain the result of matching a pointer.
+TEST_P(PropertyForPointerTestP, CanExplainMatchResult) {
+  Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_EQ("", Explain(m, static_cast<const AClass*>(nullptr)));
+  EXPECT_EQ(
+      "which points to an object whose given property is 1" + OfType("int"),
+      Explain(m, &a));
+
+  m = Property(&AClass::n, GreaterThan(0));
+  EXPECT_EQ("which points to an object whose given property is 1" +
+                OfType("int") + ", which is 1 more than 0",
+            Explain(m, &a));
+}
+
+TEST_P(PropertyForPointerTestP, CanExplainMatchResultWithPropertyName) {
+  Matcher<const AClass*> m = Property("fancy_name", &AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_EQ("", Explain(m, static_cast<const AClass*>(nullptr)));
+  EXPECT_EQ("which points to an object whose property `fancy_name` is 1" +
+                OfType("int"),
+            Explain(m, &a));
+
+  m = Property("fancy_name", &AClass::n, GreaterThan(0));
+  EXPECT_EQ("which points to an object whose property `fancy_name` is 1" +
+                OfType("int") + ", which is 1 more than 0",
+            Explain(m, &a));
+}
+
+// Tests ResultOf.
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// function pointer.
+std::string IntToStringFunction(int input) {
+  return input == 1 ? "foo" : "bar";
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(ResultOfTest);
+
+TEST(ResultOfTest, WorksForFunctionPointers) {
+  Matcher<int> matcher = ResultOf(&IntToStringFunction, Eq(std::string("foo")));
+
+  EXPECT_TRUE(matcher.Matches(1));
+  EXPECT_FALSE(matcher.Matches(2));
+}
+
+// Tests that ResultOf() can describe itself.
+TEST(ResultOfTest, CanDescribeItself) {
+  Matcher<int> matcher = ResultOf(&IntToStringFunction, StrEq("foo"));
+
+  EXPECT_EQ(
+      "is mapped by the given callable to a value that "
+      "is equal to \"foo\"",
+      Describe(matcher));
+  EXPECT_EQ(
+      "is mapped by the given callable to a value that "
+      "isn't equal to \"foo\"",
+      DescribeNegation(matcher));
+}
+
+// Tests that ResultOf() can describe itself when provided a result description.
+TEST(ResultOfTest, CanDescribeItselfWithResultDescription) {
+  Matcher<int> matcher =
+      ResultOf("string conversion", &IntToStringFunction, StrEq("foo"));
+
+  EXPECT_EQ("whose string conversion is equal to \"foo\"", Describe(matcher));
+  EXPECT_EQ("whose string conversion isn't equal to \"foo\"",
+            DescribeNegation(matcher));
+}
+
+// Tests that ResultOf() can explain the match result.
+int IntFunction(int input) { return input == 42 ? 80 : 90; }
+
+TEST_P(ResultOfTestP, CanExplainMatchResult) {
+  Matcher<int> matcher = ResultOf(&IntFunction, Ge(85));
+  EXPECT_EQ("which is mapped by the given callable to 90" + OfType("int"),
+            Explain(matcher, 36));
+
+  matcher = ResultOf(&IntFunction, GreaterThan(85));
+  EXPECT_EQ("which is mapped by the given callable to 90" + OfType("int") +
+                ", which is 5 more than 85",
+            Explain(matcher, 36));
+}
+
+TEST_P(ResultOfTestP, CanExplainMatchResultWithResultDescription) {
+  Matcher<int> matcher = ResultOf("magic int conversion", &IntFunction, Ge(85));
+  EXPECT_EQ("whose magic int conversion is 90" + OfType("int"),
+            Explain(matcher, 36));
+
+  matcher = ResultOf("magic int conversion", &IntFunction, GreaterThan(85));
+  EXPECT_EQ("whose magic int conversion is 90" + OfType("int") +
+                ", which is 5 more than 85",
+            Explain(matcher, 36));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
+// returns a non-reference.
+TEST(ResultOfTest, WorksForNonReferenceResults) {
+  Matcher<int> matcher = ResultOf(&IntFunction, Eq(80));
+
+  EXPECT_TRUE(matcher.Matches(42));
+  EXPECT_FALSE(matcher.Matches(36));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
+// returns a reference to non-const.
+double& DoubleFunction(double& input) { return input; }  // NOLINT
+
+Uncopyable& RefUncopyableFunction(Uncopyable& obj) {  // NOLINT
+  return obj;
+}
+
+TEST(ResultOfTest, WorksForReferenceToNonConstResults) {
+  double x = 3.14;
+  double x2 = x;
+  Matcher<double&> matcher = ResultOf(&DoubleFunction, Ref(x));
+
+  EXPECT_TRUE(matcher.Matches(x));
+  EXPECT_FALSE(matcher.Matches(x2));
+
+  // Test that ResultOf works with uncopyable objects
+  Uncopyable obj(0);
+  Uncopyable obj2(0);
+  Matcher<Uncopyable&> matcher2 = ResultOf(&RefUncopyableFunction, Ref(obj));
+
+  EXPECT_TRUE(matcher2.Matches(obj));
+  EXPECT_FALSE(matcher2.Matches(obj2));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
+// returns a reference to const.
+const std::string& StringFunction(const std::string& input) { return input; }
+
+TEST(ResultOfTest, WorksForReferenceToConstResults) {
+  std::string s = "foo";
+  std::string s2 = s;
+  Matcher<const std::string&> matcher = ResultOf(&StringFunction, Ref(s));
+
+  EXPECT_TRUE(matcher.Matches(s));
+  EXPECT_FALSE(matcher.Matches(s2));
+}
+
+// Tests that ResultOf(f, m) works when f(x) and m's
+// argument types are compatible but different.
+TEST(ResultOfTest, WorksForCompatibleMatcherTypes) {
+  // IntFunction() returns int but the inner matcher expects a signed char.
+  Matcher<int> matcher = ResultOf(IntFunction, Matcher<signed char>(Ge(85)));
+
+  EXPECT_TRUE(matcher.Matches(36));
+  EXPECT_FALSE(matcher.Matches(42));
+}
+
+// Tests that the program aborts when ResultOf is passed
+// a NULL function pointer.
+TEST(ResultOfDeathTest, DiesOnNullFunctionPointers) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      ResultOf(static_cast<std::string (*)(int dummy)>(nullptr),
+               Eq(std::string("foo"))),
+      "NULL function pointer is passed into ResultOf\\(\\)\\.");
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// function reference.
+TEST(ResultOfTest, WorksForFunctionReferences) {
+  Matcher<int> matcher = ResultOf(IntToStringFunction, StrEq("foo"));
+  EXPECT_TRUE(matcher.Matches(1));
+  EXPECT_FALSE(matcher.Matches(2));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// function object.
+struct Functor {
+  std::string operator()(int input) const { return IntToStringFunction(input); }
+};
+
+TEST(ResultOfTest, WorksForFunctors) {
+  Matcher<int> matcher = ResultOf(Functor(), Eq(std::string("foo")));
+
+  EXPECT_TRUE(matcher.Matches(1));
+  EXPECT_FALSE(matcher.Matches(2));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// functor with more than one operator() defined. ResultOf() must work
+// for each defined operator().
+struct PolymorphicFunctor {
+  typedef int result_type;
+  int operator()(int n) { return n; }
+  int operator()(const char* s) { return static_cast<int>(strlen(s)); }
+  std::string operator()(int* p) { return p ? "good ptr" : "null"; }
+};
+
+TEST(ResultOfTest, WorksForPolymorphicFunctors) {
+  Matcher<int> matcher_int = ResultOf(PolymorphicFunctor(), Ge(5));
+
+  EXPECT_TRUE(matcher_int.Matches(10));
+  EXPECT_FALSE(matcher_int.Matches(2));
+
+  Matcher<const char*> matcher_string = ResultOf(PolymorphicFunctor(), Ge(5));
+
+  EXPECT_TRUE(matcher_string.Matches("long string"));
+  EXPECT_FALSE(matcher_string.Matches("shrt"));
+}
+
+TEST(ResultOfTest, WorksForPolymorphicFunctorsIgnoringResultType) {
+  Matcher<int*> matcher = ResultOf(PolymorphicFunctor(), "good ptr");
+
+  int n = 0;
+  EXPECT_TRUE(matcher.Matches(&n));
+  EXPECT_FALSE(matcher.Matches(nullptr));
+}
+
+TEST(ResultOfTest, WorksForLambdas) {
+  Matcher<int> matcher = ResultOf(
+      [](int str_len) {
+        return std::string(static_cast<size_t>(str_len), 'x');
+      },
+      "xxx");
+  EXPECT_TRUE(matcher.Matches(3));
+  EXPECT_FALSE(matcher.Matches(1));
+}
+
+TEST(ResultOfTest, WorksForNonCopyableArguments) {
+  Matcher<std::unique_ptr<int>> matcher = ResultOf(
+      [](const std::unique_ptr<int>& str_len) {
+        return std::string(static_cast<size_t>(*str_len), 'x');
+      },
+      "xxx");
+  EXPECT_TRUE(matcher.Matches(std::unique_ptr<int>(new int(3))));
+  EXPECT_FALSE(matcher.Matches(std::unique_ptr<int>(new int(1))));
+}
+
+const int* ReferencingFunction(const int& n) { return &n; }
+
+struct ReferencingFunctor {
+  typedef const int* result_type;
+  result_type operator()(const int& n) { return &n; }
+};
+
+TEST(ResultOfTest, WorksForReferencingCallables) {
+  const int n = 1;
+  const int n2 = 1;
+  Matcher<const int&> matcher2 = ResultOf(ReferencingFunction, Eq(&n));
+  EXPECT_TRUE(matcher2.Matches(n));
+  EXPECT_FALSE(matcher2.Matches(n2));
+
+  Matcher<const int&> matcher3 = ResultOf(ReferencingFunctor(), Eq(&n));
+  EXPECT_TRUE(matcher3.Matches(n));
+  EXPECT_FALSE(matcher3.Matches(n2));
+}
+
+TEST(SizeIsTest, ImplementsSizeIs) {
+  vector<int> container;
+  EXPECT_THAT(container, SizeIs(0));
+  EXPECT_THAT(container, Not(SizeIs(1)));
+  container.push_back(0);
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(1));
+  container.push_back(0);
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(2));
+}
+
+TEST(SizeIsTest, WorksWithMap) {
+  map<std::string, int> container;
+  EXPECT_THAT(container, SizeIs(0));
+  EXPECT_THAT(container, Not(SizeIs(1)));
+  container.insert(make_pair("foo", 1));
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(1));
+  container.insert(make_pair("bar", 2));
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(2));
+}
+
+TEST(SizeIsTest, WorksWithReferences) {
+  vector<int> container;
+  Matcher<const vector<int>&> m = SizeIs(1);
+  EXPECT_THAT(container, Not(m));
+  container.push_back(0);
+  EXPECT_THAT(container, m);
+}
+
+TEST(SizeIsTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(SizeIs(3)));
+  helper.Call(MakeUniquePtrs({1, 2, 3}));
+}
+
+// SizeIs should work for any type that provides a size() member function.
+// For example, a size_type member type should not need to be provided.
+struct MinimalistCustomType {
+  int size() const { return 1; }
+};
+TEST(SizeIsTest, WorksWithMinimalistCustomType) {
+  MinimalistCustomType container;
+  EXPECT_THAT(container, SizeIs(1));
+  EXPECT_THAT(container, Not(SizeIs(0)));
+}
+
+TEST(SizeIsTest, CanDescribeSelf) {
+  Matcher<vector<int>> m = SizeIs(2);
+  EXPECT_EQ("has a size that is equal to 2", Describe(m));
+  EXPECT_EQ("has a size that isn't equal to 2", DescribeNegation(m));
+}
+
+TEST(SizeIsTest, ExplainsResult) {
+  Matcher<vector<int>> m1 = SizeIs(2);
+  Matcher<vector<int>> m2 = SizeIs(Lt(2u));
+  Matcher<vector<int>> m3 = SizeIs(AnyOf(0, 3));
+  Matcher<vector<int>> m4 = SizeIs(Gt(1u));
+  vector<int> container;
+  EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
+  EXPECT_EQ("whose size 0 matches", Explain(m2, container));
+  EXPECT_EQ("whose size 0 matches", Explain(m3, container));
+  EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container));
+  container.push_back(0);
+  container.push_back(0);
+  EXPECT_EQ("whose size 2 matches", Explain(m1, container));
+  EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
+  EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container));
+  EXPECT_EQ("whose size 2 matches", Explain(m4, container));
+}
+
+TEST(WhenSortedByTest, WorksForEmptyContainer) {
+  const vector<int> numbers;
+  EXPECT_THAT(numbers, WhenSortedBy(less<int>(), ElementsAre()));
+  EXPECT_THAT(numbers, Not(WhenSortedBy(less<int>(), ElementsAre(1))));
+}
+
+TEST(WhenSortedByTest, WorksForNonEmptyContainer) {
+  vector<unsigned> numbers;
+  numbers.push_back(3);
+  numbers.push_back(1);
+  numbers.push_back(2);
+  numbers.push_back(2);
+  EXPECT_THAT(numbers,
+              WhenSortedBy(greater<unsigned>(), ElementsAre(3, 2, 2, 1)));
+  EXPECT_THAT(numbers,
+              Not(WhenSortedBy(greater<unsigned>(), ElementsAre(1, 2, 2, 3))));
+}
+
+TEST(WhenSortedByTest, WorksForNonVectorContainer) {
+  list<std::string> words;
+  words.push_back("say");
+  words.push_back("hello");
+  words.push_back("world");
+  EXPECT_THAT(words, WhenSortedBy(less<std::string>(),
+                                  ElementsAre("hello", "say", "world")));
+  EXPECT_THAT(words, Not(WhenSortedBy(less<std::string>(),
+                                      ElementsAre("say", "hello", "world"))));
+}
+
+TEST(WhenSortedByTest, WorksForNativeArray) {
+  const int numbers[] = {1, 3, 2, 4};
+  const int sorted_numbers[] = {1, 2, 3, 4};
+  EXPECT_THAT(numbers, WhenSortedBy(less<int>(), ElementsAre(1, 2, 3, 4)));
+  EXPECT_THAT(numbers,
+              WhenSortedBy(less<int>(), ElementsAreArray(sorted_numbers)));
+  EXPECT_THAT(numbers, Not(WhenSortedBy(less<int>(), ElementsAre(1, 3, 2, 4))));
+}
+
+TEST(WhenSortedByTest, CanDescribeSelf) {
+  const Matcher<vector<int>> m = WhenSortedBy(less<int>(), ElementsAre(1, 2));
+  EXPECT_EQ(
+      "(when sorted) has 2 elements where\n"
+      "element #0 is equal to 1,\n"
+      "element #1 is equal to 2",
+      Describe(m));
+  EXPECT_EQ(
+      "(when sorted) doesn't have 2 elements, or\n"
+      "element #0 isn't equal to 1, or\n"
+      "element #1 isn't equal to 2",
+      DescribeNegation(m));
+}
+
+TEST(WhenSortedByTest, ExplainsMatchResult) {
+  const int a[] = {2, 1};
+  EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
+            Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
+  EXPECT_EQ("which is { 1, 2 } when sorted",
+            Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
+}
+
+// WhenSorted() is a simple wrapper on WhenSortedBy().  Hence we don't
+// need to test it as exhaustively as we test the latter.
+
+TEST(WhenSortedTest, WorksForEmptyContainer) {
+  const vector<int> numbers;
+  EXPECT_THAT(numbers, WhenSorted(ElementsAre()));
+  EXPECT_THAT(numbers, Not(WhenSorted(ElementsAre(1))));
+}
+
+TEST(WhenSortedTest, WorksForNonEmptyContainer) {
+  list<std::string> words;
+  words.push_back("3");
+  words.push_back("1");
+  words.push_back("2");
+  words.push_back("2");
+  EXPECT_THAT(words, WhenSorted(ElementsAre("1", "2", "2", "3")));
+  EXPECT_THAT(words, Not(WhenSorted(ElementsAre("3", "1", "2", "2"))));
+}
+
+TEST(WhenSortedTest, WorksForMapTypes) {
+  map<std::string, int> word_counts;
+  word_counts["and"] = 1;
+  word_counts["the"] = 1;
+  word_counts["buffalo"] = 2;
+  EXPECT_THAT(word_counts,
+              WhenSorted(ElementsAre(Pair("and", 1), Pair("buffalo", 2),
+                                     Pair("the", 1))));
+  EXPECT_THAT(word_counts,
+              Not(WhenSorted(ElementsAre(Pair("and", 1), Pair("the", 1),
+                                         Pair("buffalo", 2)))));
+}
+
+TEST(WhenSortedTest, WorksForMultiMapTypes) {
+  multimap<int, int> ifib;
+  ifib.insert(make_pair(8, 6));
+  ifib.insert(make_pair(2, 3));
+  ifib.insert(make_pair(1, 1));
+  ifib.insert(make_pair(3, 4));
+  ifib.insert(make_pair(1, 2));
+  ifib.insert(make_pair(5, 5));
+  EXPECT_THAT(ifib,
+              WhenSorted(ElementsAre(Pair(1, 1), Pair(1, 2), Pair(2, 3),
+                                     Pair(3, 4), Pair(5, 5), Pair(8, 6))));
+  EXPECT_THAT(ifib,
+              Not(WhenSorted(ElementsAre(Pair(8, 6), Pair(2, 3), Pair(1, 1),
+                                         Pair(3, 4), Pair(1, 2), Pair(5, 5)))));
+}
+
+TEST(WhenSortedTest, WorksForPolymorphicMatcher) {
+  std::deque<int> d;
+  d.push_back(2);
+  d.push_back(1);
+  EXPECT_THAT(d, WhenSorted(ElementsAre(1, 2)));
+  EXPECT_THAT(d, Not(WhenSorted(ElementsAre(2, 1))));
+}
+
+TEST(WhenSortedTest, WorksForVectorConstRefMatcher) {
+  std::deque<int> d;
+  d.push_back(2);
+  d.push_back(1);
+  Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2);
+  EXPECT_THAT(d, WhenSorted(vector_match));
+  Matcher<const std::vector<int>&> not_vector_match = ElementsAre(2, 1);
+  EXPECT_THAT(d, Not(WhenSorted(not_vector_match)));
+}
+
+// Deliberately bare pseudo-container.
+// Offers only begin() and end() accessors, yielding InputIterator.
+template <typename T>
+class Streamlike {
+ private:
+  class ConstIter;
+
+ public:
+  typedef ConstIter const_iterator;
+  typedef T value_type;
+
+  template <typename InIter>
+  Streamlike(InIter first, InIter last) : remainder_(first, last) {}
+
+  const_iterator begin() const {
+    return const_iterator(this, remainder_.begin());
+  }
+  const_iterator end() const { return const_iterator(this, remainder_.end()); }
+
+ private:
+  class ConstIter {
+   public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type = T;
+    using difference_type = ptrdiff_t;
+    using pointer = const value_type*;
+    using reference = const value_type&;
+
+    ConstIter(const Streamlike* s, typename std::list<value_type>::iterator pos)
+        : s_(s), pos_(pos) {}
+
+    const value_type& operator*() const { return *pos_; }
+    const value_type* operator->() const { return &*pos_; }
+    ConstIter& operator++() {
+      s_->remainder_.erase(pos_++);
+      return *this;
+    }
+
+    // *iter++ is required to work (see std::istreambuf_iterator).
+    // (void)iter++ is also required to work.
+    class PostIncrProxy {
+     public:
+      explicit PostIncrProxy(const value_type& value) : value_(value) {}
+      value_type operator*() const { return value_; }
+
+     private:
+      value_type value_;
+    };
+    PostIncrProxy operator++(int) {
+      PostIncrProxy proxy(**this);
+      ++(*this);
+      return proxy;
+    }
+
+    friend bool operator==(const ConstIter& a, const ConstIter& b) {
+      return a.s_ == b.s_ && a.pos_ == b.pos_;
+    }
+    friend bool operator!=(const ConstIter& a, const ConstIter& b) {
+      return !(a == b);
+    }
+
+   private:
+    const Streamlike* s_;
+    typename std::list<value_type>::iterator pos_;
+  };
+
+  friend std::ostream& operator<<(std::ostream& os, const Streamlike& s) {
+    os << "[";
+    typedef typename std::list<value_type>::const_iterator Iter;
+    const char* sep = "";
+    for (Iter it = s.remainder_.begin(); it != s.remainder_.end(); ++it) {
+      os << sep << *it;
+      sep = ",";
+    }
+    os << "]";
+    return os;
+  }
+
+  mutable std::list<value_type> remainder_;  // modified by iteration
+};
+
+TEST(StreamlikeTest, Iteration) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(a, a + 5);
+  Streamlike<int>::const_iterator it = s.begin();
+  const int* ip = a;
+  while (it != s.end()) {
+    SCOPED_TRACE(ip - a);
+    EXPECT_EQ(*ip++, *it++);
+  }
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(BeginEndDistanceIsTest);
+
+TEST(BeginEndDistanceIsTest, WorksWithForwardList) {
+  std::forward_list<int> container;
+  EXPECT_THAT(container, BeginEndDistanceIs(0));
+  EXPECT_THAT(container, Not(BeginEndDistanceIs(1)));
+  container.push_front(0);
+  EXPECT_THAT(container, Not(BeginEndDistanceIs(0)));
+  EXPECT_THAT(container, BeginEndDistanceIs(1));
+  container.push_front(0);
+  EXPECT_THAT(container, Not(BeginEndDistanceIs(0)));
+  EXPECT_THAT(container, BeginEndDistanceIs(2));
+}
+
+TEST(BeginEndDistanceIsTest, WorksWithNonStdList) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(a, a + 5);
+  EXPECT_THAT(s, BeginEndDistanceIs(5));
+}
+
+TEST(BeginEndDistanceIsTest, CanDescribeSelf) {
+  Matcher<vector<int>> m = BeginEndDistanceIs(2);
+  EXPECT_EQ("distance between begin() and end() is equal to 2", Describe(m));
+  EXPECT_EQ("distance between begin() and end() isn't equal to 2",
+            DescribeNegation(m));
+}
+
+TEST(BeginEndDistanceIsTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(BeginEndDistanceIs(2)));
+  helper.Call(MakeUniquePtrs({1, 2}));
+}
+
+TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
+  Matcher<vector<int>> m1 = BeginEndDistanceIs(2);
+  Matcher<vector<int>> m2 = BeginEndDistanceIs(Lt(2));
+  Matcher<vector<int>> m3 = BeginEndDistanceIs(AnyOf(0, 3));
+  Matcher<vector<int>> m4 = BeginEndDistanceIs(GreaterThan(1));
+  vector<int> container;
+  EXPECT_EQ("whose distance between begin() and end() 0 doesn't match",
+            Explain(m1, container));
+  EXPECT_EQ("whose distance between begin() and end() 0 matches",
+            Explain(m2, container));
+  EXPECT_EQ("whose distance between begin() and end() 0 matches",
+            Explain(m3, container));
+  EXPECT_EQ(
+      "whose distance between begin() and end() 0 doesn't match, which is 1 "
+      "less than 1",
+      Explain(m4, container));
+  container.push_back(0);
+  container.push_back(0);
+  EXPECT_EQ("whose distance between begin() and end() 2 matches",
+            Explain(m1, container));
+  EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
+            Explain(m2, container));
+  EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
+            Explain(m3, container));
+  EXPECT_EQ(
+      "whose distance between begin() and end() 2 matches, which is 1 more "
+      "than 1",
+      Explain(m4, container));
+}
+
+TEST(WhenSortedTest, WorksForStreamlike) {
+  // Streamlike 'container' provides only minimal iterator support.
+  // Its iterators are tagged with input_iterator_tag.
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(std::begin(a), std::end(a));
+  EXPECT_THAT(s, WhenSorted(ElementsAre(1, 2, 3, 4, 5)));
+  EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
+}
+
+TEST(WhenSortedTest, WorksForVectorConstRefMatcherOnStreamlike) {
+  const int a[] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(std::begin(a), std::end(a));
+  Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2, 3, 4, 5);
+  EXPECT_THAT(s, WhenSorted(vector_match));
+  EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
+}
+
+TEST(IsSupersetOfTest, WorksForNativeArray) {
+  const int subset[] = {1, 4};
+  const int superset[] = {1, 2, 4};
+  const int disjoint[] = {1, 0, 3};
+  EXPECT_THAT(subset, IsSupersetOf(subset));
+  EXPECT_THAT(subset, Not(IsSupersetOf(superset)));
+  EXPECT_THAT(superset, IsSupersetOf(subset));
+  EXPECT_THAT(subset, Not(IsSupersetOf(disjoint)));
+  EXPECT_THAT(disjoint, Not(IsSupersetOf(subset)));
+}
+
+TEST(IsSupersetOfTest, WorksWithDuplicates) {
+  const int not_enough[] = {1, 2};
+  const int enough[] = {1, 1, 2};
+  const int expected[] = {1, 1};
+  EXPECT_THAT(not_enough, Not(IsSupersetOf(expected)));
+  EXPECT_THAT(enough, IsSupersetOf(expected));
+}
+
+TEST(IsSupersetOfTest, WorksForEmpty) {
+  vector<int> numbers;
+  vector<int> expected;
+  EXPECT_THAT(numbers, IsSupersetOf(expected));
+  expected.push_back(1);
+  EXPECT_THAT(numbers, Not(IsSupersetOf(expected)));
+  expected.clear();
+  numbers.push_back(1);
+  numbers.push_back(2);
+  EXPECT_THAT(numbers, IsSupersetOf(expected));
+  expected.push_back(1);
+  EXPECT_THAT(numbers, IsSupersetOf(expected));
+  expected.push_back(2);
+  EXPECT_THAT(numbers, IsSupersetOf(expected));
+  expected.push_back(3);
+  EXPECT_THAT(numbers, Not(IsSupersetOf(expected)));
+}
+
+TEST(IsSupersetOfTest, WorksForStreamlike) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(std::begin(a), std::end(a));
+
+  vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(5);
+  EXPECT_THAT(s, IsSupersetOf(expected));
+
+  expected.push_back(0);
+  EXPECT_THAT(s, Not(IsSupersetOf(expected)));
+}
+
+TEST(IsSupersetOfTest, TakesStlContainer) {
+  const int actual[] = {3, 1, 2};
+
+  ::std::list<int> expected;
+  expected.push_back(1);
+  expected.push_back(3);
+  EXPECT_THAT(actual, IsSupersetOf(expected));
+
+  expected.push_back(4);
+  EXPECT_THAT(actual, Not(IsSupersetOf(expected)));
+}
+
+TEST(IsSupersetOfTest, Describe) {
+  typedef std::vector<int> IntVec;
+  IntVec expected;
+  expected.push_back(111);
+  expected.push_back(222);
+  expected.push_back(333);
+  EXPECT_THAT(
+      Describe<IntVec>(IsSupersetOf(expected)),
+      Eq("a surjection from elements to requirements exists such that:\n"
+         " - an element is equal to 111\n"
+         " - an element is equal to 222\n"
+         " - an element is equal to 333"));
+}
+
+TEST(IsSupersetOfTest, DescribeNegation) {
+  typedef std::vector<int> IntVec;
+  IntVec expected;
+  expected.push_back(111);
+  expected.push_back(222);
+  expected.push_back(333);
+  EXPECT_THAT(
+      DescribeNegation<IntVec>(IsSupersetOf(expected)),
+      Eq("no surjection from elements to requirements exists such that:\n"
+         " - an element is equal to 111\n"
+         " - an element is equal to 222\n"
+         " - an element is equal to 333"));
+}
+
+TEST(IsSupersetOfTest, MatchAndExplain) {
+  std::vector<int> v;
+  v.push_back(2);
+  v.push_back(3);
+  std::vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  StringMatchResultListener listener;
+  ASSERT_FALSE(ExplainMatchResult(IsSupersetOf(expected), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("where the following matchers don't match any elements:\n"
+                 "matcher #0: is equal to 1"));
+
+  v.push_back(1);
+  listener.Clear();
+  ASSERT_TRUE(ExplainMatchResult(IsSupersetOf(expected), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(), Eq("where:\n"
+                                 " - element #0 is matched by matcher #1,\n"
+                                 " - element #2 is matched by matcher #0"));
+}
+
+TEST(IsSupersetOfTest, WorksForRhsInitializerList) {
+  const int numbers[] = {1, 3, 6, 2, 4, 5};
+  EXPECT_THAT(numbers, IsSupersetOf({1, 2}));
+  EXPECT_THAT(numbers, Not(IsSupersetOf({3, 0})));
+}
+
+TEST(IsSupersetOfTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(IsSupersetOf({Pointee(1)})));
+  helper.Call(MakeUniquePtrs({1, 2}));
+  EXPECT_CALL(helper, Call(Not(IsSupersetOf({Pointee(1), Pointee(2)}))));
+  helper.Call(MakeUniquePtrs({2}));
+}
+
+TEST(IsSubsetOfTest, WorksForNativeArray) {
+  const int subset[] = {1, 4};
+  const int superset[] = {1, 2, 4};
+  const int disjoint[] = {1, 0, 3};
+  EXPECT_THAT(subset, IsSubsetOf(subset));
+  EXPECT_THAT(subset, IsSubsetOf(superset));
+  EXPECT_THAT(superset, Not(IsSubsetOf(subset)));
+  EXPECT_THAT(subset, Not(IsSubsetOf(disjoint)));
+  EXPECT_THAT(disjoint, Not(IsSubsetOf(subset)));
+}
+
+TEST(IsSubsetOfTest, WorksWithDuplicates) {
+  const int not_enough[] = {1, 2};
+  const int enough[] = {1, 1, 2};
+  const int actual[] = {1, 1};
+  EXPECT_THAT(actual, Not(IsSubsetOf(not_enough)));
+  EXPECT_THAT(actual, IsSubsetOf(enough));
+}
+
+TEST(IsSubsetOfTest, WorksForEmpty) {
+  vector<int> numbers;
+  vector<int> expected;
+  EXPECT_THAT(numbers, IsSubsetOf(expected));
+  expected.push_back(1);
+  EXPECT_THAT(numbers, IsSubsetOf(expected));
+  expected.clear();
+  numbers.push_back(1);
+  numbers.push_back(2);
+  EXPECT_THAT(numbers, Not(IsSubsetOf(expected)));
+  expected.push_back(1);
+  EXPECT_THAT(numbers, Not(IsSubsetOf(expected)));
+  expected.push_back(2);
+  EXPECT_THAT(numbers, IsSubsetOf(expected));
+  expected.push_back(3);
+  EXPECT_THAT(numbers, IsSubsetOf(expected));
+}
+
+TEST(IsSubsetOfTest, WorksForStreamlike) {
+  const int a[5] = {1, 2};
+  Streamlike<int> s(std::begin(a), std::end(a));
+
+  vector<int> expected;
+  expected.push_back(1);
+  EXPECT_THAT(s, Not(IsSubsetOf(expected)));
+  expected.push_back(2);
+  expected.push_back(5);
+  EXPECT_THAT(s, IsSubsetOf(expected));
+}
+
+TEST(IsSubsetOfTest, TakesStlContainer) {
+  const int actual[] = {3, 1, 2};
+
+  ::std::list<int> expected;
+  expected.push_back(1);
+  expected.push_back(3);
+  EXPECT_THAT(actual, Not(IsSubsetOf(expected)));
+
+  expected.push_back(2);
+  expected.push_back(4);
+  EXPECT_THAT(actual, IsSubsetOf(expected));
+}
+
+TEST(IsSubsetOfTest, Describe) {
+  typedef std::vector<int> IntVec;
+  IntVec expected;
+  expected.push_back(111);
+  expected.push_back(222);
+  expected.push_back(333);
+
+  EXPECT_THAT(
+      Describe<IntVec>(IsSubsetOf(expected)),
+      Eq("an injection from elements to requirements exists such that:\n"
+         " - an element is equal to 111\n"
+         " - an element is equal to 222\n"
+         " - an element is equal to 333"));
+}
+
+TEST(IsSubsetOfTest, DescribeNegation) {
+  typedef std::vector<int> IntVec;
+  IntVec expected;
+  expected.push_back(111);
+  expected.push_back(222);
+  expected.push_back(333);
+  EXPECT_THAT(
+      DescribeNegation<IntVec>(IsSubsetOf(expected)),
+      Eq("no injection from elements to requirements exists such that:\n"
+         " - an element is equal to 111\n"
+         " - an element is equal to 222\n"
+         " - an element is equal to 333"));
+}
+
+TEST(IsSubsetOfTest, MatchAndExplain) {
+  std::vector<int> v;
+  v.push_back(2);
+  v.push_back(3);
+  std::vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  StringMatchResultListener listener;
+  ASSERT_FALSE(ExplainMatchResult(IsSubsetOf(expected), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("where the following elements don't match any matchers:\n"
+                 "element #1: 3"));
+
+  expected.push_back(3);
+  listener.Clear();
+  ASSERT_TRUE(ExplainMatchResult(IsSubsetOf(expected), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(), Eq("where:\n"
+                                 " - element #0 is matched by matcher #1,\n"
+                                 " - element #1 is matched by matcher #2"));
+}
+
+TEST(IsSubsetOfTest, WorksForRhsInitializerList) {
+  const int numbers[] = {1, 2, 3};
+  EXPECT_THAT(numbers, IsSubsetOf({1, 2, 3, 4}));
+  EXPECT_THAT(numbers, Not(IsSubsetOf({1, 2})));
+}
+
+TEST(IsSubsetOfTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(IsSubsetOf({Pointee(1), Pointee(2)})));
+  helper.Call(MakeUniquePtrs({1}));
+  EXPECT_CALL(helper, Call(Not(IsSubsetOf({Pointee(1)}))));
+  helper.Call(MakeUniquePtrs({2}));
+}
+
+// Tests using ElementsAre() and ElementsAreArray() with stream-like
+// "containers".
+
+TEST(ElemensAreStreamTest, WorksForStreamlike) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(std::begin(a), std::end(a));
+  EXPECT_THAT(s, ElementsAre(1, 2, 3, 4, 5));
+  EXPECT_THAT(s, Not(ElementsAre(2, 1, 4, 5, 3)));
+}
+
+TEST(ElemensAreArrayStreamTest, WorksForStreamlike) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(std::begin(a), std::end(a));
+
+  vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(3);
+  expected.push_back(4);
+  expected.push_back(5);
+  EXPECT_THAT(s, ElementsAreArray(expected));
+
+  expected[3] = 0;
+  EXPECT_THAT(s, Not(ElementsAreArray(expected)));
+}
+
+TEST(ElementsAreTest, WorksWithUncopyable) {
+  Uncopyable objs[2];
+  objs[0].set_value(-3);
+  objs[1].set_value(1);
+  EXPECT_THAT(objs, ElementsAre(UncopyableIs(-3), Truly(ValueIsPositive)));
+}
+
+TEST(ElementsAreTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(ElementsAre(Pointee(1), Pointee(2))));
+  helper.Call(MakeUniquePtrs({1, 2}));
+
+  EXPECT_CALL(helper, Call(ElementsAreArray({Pointee(3), Pointee(4)})));
+  helper.Call(MakeUniquePtrs({3, 4}));
+}
+
+TEST(ElementsAreTest, TakesStlContainer) {
+  const int actual[] = {3, 1, 2};
+
+  ::std::list<int> expected;
+  expected.push_back(3);
+  expected.push_back(1);
+  expected.push_back(2);
+  EXPECT_THAT(actual, ElementsAreArray(expected));
+
+  expected.push_back(4);
+  EXPECT_THAT(actual, Not(ElementsAreArray(expected)));
+}
+
+// Tests for UnorderedElementsAreArray()
+
+TEST(UnorderedElementsAreArrayTest, SucceedsWhenExpected) {
+  const int a[] = {0, 1, 2, 3, 4};
+  std::vector<int> s(std::begin(a), std::end(a));
+  do {
+    StringMatchResultListener listener;
+    EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(a), s, &listener))
+        << listener.str();
+  } while (std::next_permutation(s.begin(), s.end()));
+}
+
+TEST(UnorderedElementsAreArrayTest, VectorBool) {
+  const bool a[] = {false, true, false, true, true};
+  const bool b[] = {true, false, true, true, false};
+  std::vector<bool> expected(std::begin(a), std::end(a));
+  std::vector<bool> actual(std::begin(b), std::end(b));
+  StringMatchResultListener listener;
+  EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(expected), actual,
+                                 &listener))
+      << listener.str();
+}
+
+TEST(UnorderedElementsAreArrayTest, WorksForStreamlike) {
+  // Streamlike 'container' provides only minimal iterator support.
+  // Its iterators are tagged with input_iterator_tag, and it has no
+  // size() or empty() methods.
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(std::begin(a), std::end(a));
+
+  ::std::vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(3);
+  expected.push_back(4);
+  expected.push_back(5);
+  EXPECT_THAT(s, UnorderedElementsAreArray(expected));
+
+  expected.push_back(6);
+  EXPECT_THAT(s, Not(UnorderedElementsAreArray(expected)));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesStlContainer) {
+  const int actual[] = {3, 1, 2};
+
+  ::std::list<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(3);
+  EXPECT_THAT(actual, UnorderedElementsAreArray(expected));
+
+  expected.push_back(4);
+  EXPECT_THAT(actual, Not(UnorderedElementsAreArray(expected)));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesInitializerList) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  EXPECT_THAT(a, UnorderedElementsAreArray({1, 2, 3, 4, 5}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray({1, 2, 3, 4, 6})));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesInitializerListOfCStrings) {
+  const std::string a[5] = {"a", "b", "c", "d", "e"};
+  EXPECT_THAT(a, UnorderedElementsAreArray({"a", "b", "c", "d", "e"}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray({"a", "b", "c", "d", "ef"})));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesInitializerListOfSameTypedMatchers) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  EXPECT_THAT(a,
+              UnorderedElementsAreArray({Eq(1), Eq(2), Eq(3), Eq(4), Eq(5)}));
+  EXPECT_THAT(
+      a, Not(UnorderedElementsAreArray({Eq(1), Eq(2), Eq(3), Eq(4), Eq(6)})));
+}
+
+TEST(UnorderedElementsAreArrayTest,
+     TakesInitializerListOfDifferentTypedMatchers) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  // The compiler cannot infer the type of the initializer list if its
+  // elements have different types.  We must explicitly specify the
+  // unified element type in this case.
+  EXPECT_THAT(a, UnorderedElementsAreArray<Matcher<int>>(
+                     {Eq(1), Ne(-2), Ge(3), Le(4), Eq(5)}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray<Matcher<int>>(
+                     {Eq(1), Ne(-2), Ge(3), Le(4), Eq(6)})));
+}
+
+TEST(UnorderedElementsAreArrayTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper,
+              Call(UnorderedElementsAreArray({Pointee(1), Pointee(2)})));
+  helper.Call(MakeUniquePtrs({2, 1}));
+}
+
+class UnorderedElementsAreTest : public testing::Test {
+ protected:
+  typedef std::vector<int> IntVec;
+};
+
+TEST_F(UnorderedElementsAreTest, WorksWithUncopyable) {
+  Uncopyable objs[2];
+  objs[0].set_value(-3);
+  objs[1].set_value(1);
+  EXPECT_THAT(objs,
+              UnorderedElementsAre(Truly(ValueIsPositive), UncopyableIs(-3)));
+}
+
+TEST_F(UnorderedElementsAreTest, SucceedsWhenExpected) {
+  const int a[] = {1, 2, 3};
+  std::vector<int> s(std::begin(a), std::end(a));
+  do {
+    StringMatchResultListener listener;
+    EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3), s, &listener))
+        << listener.str();
+  } while (std::next_permutation(s.begin(), s.end()));
+}
+
+TEST_F(UnorderedElementsAreTest, FailsWhenAnElementMatchesNoMatcher) {
+  const int a[] = {1, 2, 3};
+  std::vector<int> s(std::begin(a), std::end(a));
+  std::vector<Matcher<int>> mv;
+  mv.push_back(1);
+  mv.push_back(2);
+  mv.push_back(2);
+  // The element with value '3' matches nothing: fail fast.
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAreArray(mv), s, &listener))
+      << listener.str();
+}
+
+TEST_F(UnorderedElementsAreTest, WorksForStreamlike) {
+  // Streamlike 'container' provides only minimal iterator support.
+  // Its iterators are tagged with input_iterator_tag, and it has no
+  // size() or empty() methods.
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(std::begin(a), std::end(a));
+
+  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+  EXPECT_THAT(s, Not(UnorderedElementsAre(2, 2, 3, 4, 5)));
+}
+
+TEST_F(UnorderedElementsAreTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(UnorderedElementsAre(Pointee(1), Pointee(2))));
+  helper.Call(MakeUniquePtrs({2, 1}));
+}
+
+// One naive implementation of the matcher runs in O(N!) time, which is too
+// slow for many real-world inputs. This test shows that our matcher can match
+// 100 inputs very quickly (a few milliseconds).  An O(100!) is 10^158
+// iterations and obviously effectively incomputable.
+// [ RUN      ] UnorderedElementsAreTest.Performance
+// [       OK ] UnorderedElementsAreTest.Performance (4 ms)
+TEST_F(UnorderedElementsAreTest, Performance) {
+  std::vector<int> s;
+  std::vector<Matcher<int>> mv;
+  for (int i = 0; i < 100; ++i) {
+    s.push_back(i);
+    mv.push_back(_);
+  }
+  mv[50] = Eq(0);
+  StringMatchResultListener listener;
+  EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(mv), s, &listener))
+      << listener.str();
+}
+
+// Another variant of 'Performance' with similar expectations.
+// [ RUN      ] UnorderedElementsAreTest.PerformanceHalfStrict
+// [       OK ] UnorderedElementsAreTest.PerformanceHalfStrict (4 ms)
+TEST_F(UnorderedElementsAreTest, PerformanceHalfStrict) {
+  std::vector<int> s;
+  std::vector<Matcher<int>> mv;
+  for (int i = 0; i < 100; ++i) {
+    s.push_back(i);
+    if (i & 1) {
+      mv.push_back(_);
+    } else {
+      mv.push_back(i);
+    }
+  }
+  StringMatchResultListener listener;
+  EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(mv), s, &listener))
+      << listener.str();
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageCountWrong) {
+  std::vector<int> v;
+  v.push_back(4);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("which has 1 element\n"
+                 "where the following matchers don't match any elements:\n"
+                 "matcher #0: is equal to 1,\n"
+                 "matcher #1: is equal to 2,\n"
+                 "matcher #2: is equal to 3\n"
+                 "and where the following elements don't match any matchers:\n"
+                 "element #0: 4"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageCountWrongZero) {
+  std::vector<int> v;
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("where the following matchers don't match any elements:\n"
+                 "matcher #0: is equal to 1,\n"
+                 "matcher #1: is equal to 2,\n"
+                 "matcher #2: is equal to 3"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedMatchers) {
+  std::vector<int> v;
+  v.push_back(1);
+  v.push_back(1);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("where the following matchers don't match any elements:\n"
+                 "matcher #1: is equal to 2"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedElements) {
+  std::vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 1), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("where the following elements don't match any matchers:\n"
+                 "element #1: 2"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedMatcherAndElement) {
+  std::vector<int> v;
+  v.push_back(2);
+  v.push_back(3);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2), v, &listener))
+      << listener.str();
+  EXPECT_THAT(listener.str(),
+              Eq("where"
+                 " the following matchers don't match any elements:\n"
+                 "matcher #0: is equal to 1\n"
+                 "and"
+                 " where"
+                 " the following elements don't match any matchers:\n"
+                 "element #1: 3"));
+}
+
+// Test helper for formatting element, matcher index pairs in expectations.
+static std::string EMString(int element, int matcher) {
+  stringstream ss;
+  ss << "(element #" << element << ", matcher #" << matcher << ")";
+  return ss.str();
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageImperfectMatchOnly) {
+  // A situation where all elements and matchers have a match
+  // associated with them, but the max matching is not perfect.
+  std::vector<std::string> v;
+  v.push_back("a");
+  v.push_back("b");
+  v.push_back("c");
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(
+      UnorderedElementsAre("a", "a", AnyOf("b", "c")), v, &listener))
+      << listener.str();
+
+  std::string prefix =
+      "where no permutation of the elements can satisfy all matchers, "
+      "and the closest match is 2 of 3 matchers with the "
+      "pairings:\n";
+
+  // We have to be a bit loose here, because there are 4 valid max matches.
+  EXPECT_THAT(
+      listener.str(),
+      AnyOf(
+          prefix + "{\n  " + EMString(0, 0) + ",\n  " + EMString(1, 2) + "\n}",
+          prefix + "{\n  " + EMString(0, 1) + ",\n  " + EMString(1, 2) + "\n}",
+          prefix + "{\n  " + EMString(0, 0) + ",\n  " + EMString(2, 2) + "\n}",
+          prefix + "{\n  " + EMString(0, 1) + ",\n  " + EMString(2, 2) +
+              "\n}"));
+}
+
+TEST_F(UnorderedElementsAreTest, Describe) {
+  EXPECT_THAT(Describe<IntVec>(UnorderedElementsAre()), Eq("is empty"));
+  EXPECT_THAT(Describe<IntVec>(UnorderedElementsAre(345)),
+              Eq("has 1 element and that element is equal to 345"));
+  EXPECT_THAT(Describe<IntVec>(UnorderedElementsAre(111, 222, 333)),
+              Eq("has 3 elements and there exists some permutation "
+                 "of elements such that:\n"
+                 " - element #0 is equal to 111, and\n"
+                 " - element #1 is equal to 222, and\n"
+                 " - element #2 is equal to 333"));
+}
+
+TEST_F(UnorderedElementsAreTest, DescribeNegation) {
+  EXPECT_THAT(DescribeNegation<IntVec>(UnorderedElementsAre()),
+              Eq("isn't empty"));
+  EXPECT_THAT(
+      DescribeNegation<IntVec>(UnorderedElementsAre(345)),
+      Eq("doesn't have 1 element, or has 1 element that isn't equal to 345"));
+  EXPECT_THAT(DescribeNegation<IntVec>(UnorderedElementsAre(123, 234, 345)),
+              Eq("doesn't have 3 elements, or there exists no permutation "
+                 "of elements such that:\n"
+                 " - element #0 is equal to 123, and\n"
+                 " - element #1 is equal to 234, and\n"
+                 " - element #2 is equal to 345"));
+}
+
+// Tests Each().
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(EachTest);
+
+TEST_P(EachTestP, ExplainsMatchResultCorrectly) {
+  set<int> a;  // empty
+
+  Matcher<set<int>> m = Each(2);
+  EXPECT_EQ("", Explain(m, a));
+
+  Matcher<const int(&)[1]> n = Each(1);  // NOLINT
+
+  const int b[1] = {1};
+  EXPECT_EQ("", Explain(n, b));
+
+  n = Each(3);
+  EXPECT_EQ("whose element #0 doesn't match", Explain(n, b));
+
+  a.insert(1);
+  a.insert(2);
+  a.insert(3);
+  m = Each(GreaterThan(0));
+  EXPECT_EQ("", Explain(m, a));
+
+  m = Each(GreaterThan(10));
+  EXPECT_EQ("whose element #0 doesn't match, which is 9 less than 10",
+            Explain(m, a));
+}
+
+TEST(EachTest, DescribesItselfCorrectly) {
+  Matcher<vector<int>> m = Each(1);
+  EXPECT_EQ("only contains elements that is equal to 1", Describe(m));
+
+  Matcher<vector<int>> m2 = Not(m);
+  EXPECT_EQ("contains some element that isn't equal to 1", Describe(m2));
+}
+
+TEST(EachTest, MatchesVectorWhenAllElementsMatch) {
+  vector<int> some_vector;
+  EXPECT_THAT(some_vector, Each(1));
+  some_vector.push_back(3);
+  EXPECT_THAT(some_vector, Not(Each(1)));
+  EXPECT_THAT(some_vector, Each(3));
+  some_vector.push_back(1);
+  some_vector.push_back(2);
+  EXPECT_THAT(some_vector, Not(Each(3)));
+  EXPECT_THAT(some_vector, Each(Lt(3.5)));
+
+  vector<std::string> another_vector;
+  another_vector.push_back("fee");
+  EXPECT_THAT(another_vector, Each(std::string("fee")));
+  another_vector.push_back("fie");
+  another_vector.push_back("foe");
+  another_vector.push_back("fum");
+  EXPECT_THAT(another_vector, Not(Each(std::string("fee"))));
+}
+
+TEST(EachTest, MatchesMapWhenAllElementsMatch) {
+  map<const char*, int> my_map;
+  const char* bar = "a string";
+  my_map[bar] = 2;
+  EXPECT_THAT(my_map, Each(make_pair(bar, 2)));
+
+  map<std::string, int> another_map;
+  EXPECT_THAT(another_map, Each(make_pair(std::string("fee"), 1)));
+  another_map["fee"] = 1;
+  EXPECT_THAT(another_map, Each(make_pair(std::string("fee"), 1)));
+  another_map["fie"] = 2;
+  another_map["foe"] = 3;
+  another_map["fum"] = 4;
+  EXPECT_THAT(another_map, Not(Each(make_pair(std::string("fee"), 1))));
+  EXPECT_THAT(another_map, Not(Each(make_pair(std::string("fum"), 1))));
+  EXPECT_THAT(another_map, Each(Pair(_, Gt(0))));
+}
+
+TEST(EachTest, AcceptsMatcher) {
+  const int a[] = {1, 2, 3};
+  EXPECT_THAT(a, Each(Gt(0)));
+  EXPECT_THAT(a, Not(Each(Gt(1))));
+}
+
+TEST(EachTest, WorksForNativeArrayAsTuple) {
+  const int a[] = {1, 2};
+  const int* const pointer = a;
+  EXPECT_THAT(std::make_tuple(pointer, 2), Each(Gt(0)));
+  EXPECT_THAT(std::make_tuple(pointer, 2), Not(Each(Gt(1))));
+}
+
+TEST(EachTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(Each(Pointee(Gt(0)))));
+  helper.Call(MakeUniquePtrs({1, 2}));
+}
+
+// For testing Pointwise().
+class IsHalfOfMatcher {
+ public:
+  template <typename T1, typename T2>
+  bool MatchAndExplain(const std::tuple<T1, T2>& a_pair,
+                       MatchResultListener* listener) const {
+    if (std::get<0>(a_pair) == std::get<1>(a_pair) / 2) {
+      *listener << "where the second is " << std::get<1>(a_pair);
+      return true;
+    } else {
+      *listener << "where the second/2 is " << std::get<1>(a_pair) / 2;
+      return false;
+    }
+  }
+
+  void DescribeTo(ostream* os) const {
+    *os << "are a pair where the first is half of the second";
+  }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "are a pair where the first isn't half of the second";
+  }
+};
+
+PolymorphicMatcher<IsHalfOfMatcher> IsHalfOf() {
+  return MakePolymorphicMatcher(IsHalfOfMatcher());
+}
+
+TEST(PointwiseTest, DescribesSelf) {
+  vector<int> rhs;
+  rhs.push_back(1);
+  rhs.push_back(2);
+  rhs.push_back(3);
+  const Matcher<const vector<int>&> m = Pointwise(IsHalfOf(), rhs);
+  EXPECT_EQ(
+      "contains 3 values, where each value and its corresponding value "
+      "in { 1, 2, 3 } are a pair where the first is half of the second",
+      Describe(m));
+  EXPECT_EQ(
+      "doesn't contain exactly 3 values, or contains a value x at some "
+      "index i where x and the i-th value of { 1, 2, 3 } are a pair "
+      "where the first isn't half of the second",
+      DescribeNegation(m));
+}
+
+TEST(PointwiseTest, MakesCopyOfRhs) {
+  list<signed char> rhs;
+  rhs.push_back(2);
+  rhs.push_back(4);
+
+  int lhs[] = {1, 2};
+  const Matcher<const int(&)[2]> m = Pointwise(IsHalfOf(), rhs);
+  EXPECT_THAT(lhs, m);
+
+  // Changing rhs now shouldn't affect m, which made a copy of rhs.
+  rhs.push_back(6);
+  EXPECT_THAT(lhs, m);
+}
+
+TEST(PointwiseTest, WorksForLhsNativeArray) {
+  const int lhs[] = {1, 2, 3};
+  vector<int> rhs;
+  rhs.push_back(2);
+  rhs.push_back(4);
+  rhs.push_back(6);
+  EXPECT_THAT(lhs, Pointwise(Lt(), rhs));
+  EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs)));
+}
+
+TEST(PointwiseTest, WorksForRhsNativeArray) {
+  const int rhs[] = {1, 2, 3};
+  vector<int> lhs;
+  lhs.push_back(2);
+  lhs.push_back(4);
+  lhs.push_back(6);
+  EXPECT_THAT(lhs, Pointwise(Gt(), rhs));
+  EXPECT_THAT(lhs, Not(Pointwise(Lt(), rhs)));
+}
+
+// Test is effective only with sanitizers.
+TEST(PointwiseTest, WorksForVectorOfBool) {
+  vector<bool> rhs(3, false);
+  rhs[1] = true;
+  vector<bool> lhs = rhs;
+  EXPECT_THAT(lhs, Pointwise(Eq(), rhs));
+  rhs[0] = true;
+  EXPECT_THAT(lhs, Not(Pointwise(Eq(), rhs)));
+}
+
+TEST(PointwiseTest, WorksForRhsInitializerList) {
+  const vector<int> lhs{2, 4, 6};
+  EXPECT_THAT(lhs, Pointwise(Gt(), {1, 2, 3}));
+  EXPECT_THAT(lhs, Not(Pointwise(Lt(), {3, 3, 7})));
+}
+
+TEST(PointwiseTest, RejectsWrongSize) {
+  const double lhs[2] = {1, 2};
+  const int rhs[1] = {0};
+  EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs)));
+  EXPECT_EQ("which contains 2 values", Explain(Pointwise(Gt(), rhs), lhs));
+
+  const int rhs2[3] = {0, 1, 2};
+  EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs2)));
+}
+
+TEST(PointwiseTest, RejectsWrongContent) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 6, 4};
+  EXPECT_THAT(lhs, Not(Pointwise(IsHalfOf(), rhs)));
+  EXPECT_EQ(
+      "where the value pair (2, 6) at index #1 don't match, "
+      "where the second/2 is 3",
+      Explain(Pointwise(IsHalfOf(), rhs), lhs));
+}
+
+TEST(PointwiseTest, AcceptsCorrectContent) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 4, 6};
+  EXPECT_THAT(lhs, Pointwise(IsHalfOf(), rhs));
+  EXPECT_EQ("", Explain(Pointwise(IsHalfOf(), rhs), lhs));
+}
+
+TEST(PointwiseTest, AllowsMonomorphicInnerMatcher) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 4, 6};
+  const Matcher<std::tuple<const double&, const int&>> m1 = IsHalfOf();
+  EXPECT_THAT(lhs, Pointwise(m1, rhs));
+  EXPECT_EQ("", Explain(Pointwise(m1, rhs), lhs));
+
+  // This type works as a std::tuple<const double&, const int&> can be
+  // implicitly cast to std::tuple<double, int>.
+  const Matcher<std::tuple<double, int>> m2 = IsHalfOf();
+  EXPECT_THAT(lhs, Pointwise(m2, rhs));
+  EXPECT_EQ("", Explain(Pointwise(m2, rhs), lhs));
+}
+
+MATCHER(PointeeEquals, "Points to an equal value") {
+  return ExplainMatchResult(::testing::Pointee(::testing::get<1>(arg)),
+                            ::testing::get<0>(arg), result_listener);
+}
+
+TEST(PointwiseTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(Pointwise(PointeeEquals(), std::vector<int>{1, 2})));
+  helper.Call(MakeUniquePtrs({1, 2}));
+}
+
+TEST(UnorderedPointwiseTest, DescribesSelf) {
+  vector<int> rhs;
+  rhs.push_back(1);
+  rhs.push_back(2);
+  rhs.push_back(3);
+  const Matcher<const vector<int>&> m = UnorderedPointwise(IsHalfOf(), rhs);
+  EXPECT_EQ(
+      "has 3 elements and there exists some permutation of elements such "
+      "that:\n"
+      " - element #0 and 1 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #1 and 2 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #2 and 3 are a pair where the first is half of the second",
+      Describe(m));
+  EXPECT_EQ(
+      "doesn't have 3 elements, or there exists no permutation of elements "
+      "such that:\n"
+      " - element #0 and 1 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #1 and 2 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #2 and 3 are a pair where the first is half of the second",
+      DescribeNegation(m));
+}
+
+TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
+  list<signed char> rhs;
+  rhs.push_back(2);
+  rhs.push_back(4);
+
+  int lhs[] = {2, 1};
+  const Matcher<const int(&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
+  EXPECT_THAT(lhs, m);
+
+  // Changing rhs now shouldn't affect m, which made a copy of rhs.
+  rhs.push_back(6);
+  EXPECT_THAT(lhs, m);
+}
+
+TEST(UnorderedPointwiseTest, WorksForLhsNativeArray) {
+  const int lhs[] = {1, 2, 3};
+  vector<int> rhs;
+  rhs.push_back(4);
+  rhs.push_back(6);
+  rhs.push_back(2);
+  EXPECT_THAT(lhs, UnorderedPointwise(Lt(), rhs));
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
+}
+
+TEST(UnorderedPointwiseTest, WorksForRhsNativeArray) {
+  const int rhs[] = {1, 2, 3};
+  vector<int> lhs;
+  lhs.push_back(4);
+  lhs.push_back(2);
+  lhs.push_back(6);
+  EXPECT_THAT(lhs, UnorderedPointwise(Gt(), rhs));
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Lt(), rhs)));
+}
+
+TEST(UnorderedPointwiseTest, WorksForRhsInitializerList) {
+  const vector<int> lhs{2, 4, 6};
+  EXPECT_THAT(lhs, UnorderedPointwise(Gt(), {5, 1, 3}));
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Lt(), {1, 1, 7})));
+}
+
+TEST(UnorderedPointwiseTest, RejectsWrongSize) {
+  const double lhs[2] = {1, 2};
+  const int rhs[1] = {0};
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
+  EXPECT_EQ("which has 2 elements\n",
+            Explain(UnorderedPointwise(Gt(), rhs), lhs));
+
+  const int rhs2[3] = {0, 1, 2};
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs2)));
+}
+
+TEST(UnorderedPointwiseTest, RejectsWrongContent) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 6, 6};
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(IsHalfOf(), rhs)));
+  EXPECT_EQ(
+      "where the following elements don't match any matchers:\n"
+      "element #1: 2",
+      Explain(UnorderedPointwise(IsHalfOf(), rhs), lhs));
+}
+
+TEST(UnorderedPointwiseTest, AcceptsCorrectContentInSameOrder) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 4, 6};
+  EXPECT_THAT(lhs, UnorderedPointwise(IsHalfOf(), rhs));
+}
+
+TEST(UnorderedPointwiseTest, AcceptsCorrectContentInDifferentOrder) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {6, 4, 2};
+  EXPECT_THAT(lhs, UnorderedPointwise(IsHalfOf(), rhs));
+}
+
+TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {4, 6, 2};
+  const Matcher<std::tuple<const double&, const int&>> m1 = IsHalfOf();
+  EXPECT_THAT(lhs, UnorderedPointwise(m1, rhs));
+
+  // This type works as a std::tuple<const double&, const int&> can be
+  // implicitly cast to std::tuple<double, int>.
+  const Matcher<std::tuple<double, int>> m2 = IsHalfOf();
+  EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));
+}
+
+TEST(UnorderedPointwiseTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(UnorderedPointwise(PointeeEquals(),
+                                              std::vector<int>{1, 2})));
+  helper.Call(MakeUniquePtrs({2, 1}));
+}
+
+TEST(PointeeTest, WorksOnMoveOnlyType) {
+  std::unique_ptr<int> p(new int(3));
+  EXPECT_THAT(p, Pointee(Eq(3)));
+  EXPECT_THAT(p, Not(Pointee(Eq(2))));
+}
+
+class PredicateFormatterFromMatcherTest : public ::testing::Test {
+ protected:
+  enum Behavior { kInitialSuccess, kAlwaysFail, kFlaky };
+
+  // A matcher that can return different results when used multiple times on the
+  // same input. No real matcher should do this; but this lets us test that we
+  // detect such behavior and fail appropriately.
+  class MockMatcher : public MatcherInterface<Behavior> {
+   public:
+    bool MatchAndExplain(Behavior behavior,
+                         MatchResultListener* listener) const override {
+      *listener << "[MatchAndExplain]";
+      switch (behavior) {
+        case kInitialSuccess:
+          // The first call to MatchAndExplain should use a "not interested"
+          // listener; so this is expected to return |true|. There should be no
+          // subsequent calls.
+          return !listener->IsInterested();
+
+        case kAlwaysFail:
+          return false;
+
+        case kFlaky:
+          // The first call to MatchAndExplain should use a "not interested"
+          // listener; so this will return |false|. Subsequent calls should have
+          // an "interested" listener; so this will return |true|, thus
+          // simulating a flaky matcher.
+          return listener->IsInterested();
+      }
+
+      GTEST_LOG_(FATAL) << "This should never be reached";
+      return false;
+    }
+
+    void DescribeTo(ostream* os) const override { *os << "[DescribeTo]"; }
+
+    void DescribeNegationTo(ostream* os) const override {
+      *os << "[DescribeNegationTo]";
+    }
+  };
+
+  AssertionResult RunPredicateFormatter(Behavior behavior) {
+    auto matcher = MakeMatcher(new MockMatcher);
+    PredicateFormatterFromMatcher<Matcher<Behavior>> predicate_formatter(
+        matcher);
+    return predicate_formatter("dummy-name", behavior);
+  }
+};
+
+TEST_F(PredicateFormatterFromMatcherTest, ShortCircuitOnSuccess) {
+  AssertionResult result = RunPredicateFormatter(kInitialSuccess);
+  EXPECT_TRUE(result);  // Implicit cast to bool.
+  std::string expect;
+  EXPECT_EQ(expect, result.message());
+}
+
+TEST_F(PredicateFormatterFromMatcherTest, NoShortCircuitOnFailure) {
+  AssertionResult result = RunPredicateFormatter(kAlwaysFail);
+  EXPECT_FALSE(result);  // Implicit cast to bool.
+  std::string expect =
+      "Value of: dummy-name\nExpected: [DescribeTo]\n"
+      "  Actual: 1" +
+      OfType(internal::GetTypeName<Behavior>()) + ", [MatchAndExplain]";
+  EXPECT_EQ(expect, result.message());
+}
+
+TEST_F(PredicateFormatterFromMatcherTest, DetectsFlakyShortCircuit) {
+  AssertionResult result = RunPredicateFormatter(kFlaky);
+  EXPECT_FALSE(result);  // Implicit cast to bool.
+  std::string expect =
+      "Value of: dummy-name\nExpected: [DescribeTo]\n"
+      "  The matcher failed on the initial attempt; but passed when rerun to "
+      "generate the explanation.\n"
+      "  Actual: 2" +
+      OfType(internal::GetTypeName<Behavior>()) + ", [MatchAndExplain]";
+  EXPECT_EQ(expect, result.message());
+}
+
+// Tests for ElementsAre().
+
+TEST(ElementsAreTest, CanDescribeExpectingNoElement) {
+  Matcher<const vector<int>&> m = ElementsAre();
+  EXPECT_EQ("is empty", Describe(m));
+}
+
+TEST(ElementsAreTest, CanDescribeExpectingOneElement) {
+  Matcher<vector<int>> m = ElementsAre(Gt(5));
+  EXPECT_EQ("has 1 element that is > 5", Describe(m));
+}
+
+TEST(ElementsAreTest, CanDescribeExpectingManyElements) {
+  Matcher<list<std::string>> m = ElementsAre(StrEq("one"), "two");
+  EXPECT_EQ(
+      "has 2 elements where\n"
+      "element #0 is equal to \"one\",\n"
+      "element #1 is equal to \"two\"",
+      Describe(m));
+}
+
+TEST(ElementsAreTest, CanDescribeNegationOfExpectingNoElement) {
+  Matcher<vector<int>> m = ElementsAre();
+  EXPECT_EQ("isn't empty", DescribeNegation(m));
+}
+
+TEST(ElementsAreTest, CanDescribeNegationOfExpectingOneElement) {
+  Matcher<const list<int>&> m = ElementsAre(Gt(5));
+  EXPECT_EQ(
+      "doesn't have 1 element, or\n"
+      "element #0 isn't > 5",
+      DescribeNegation(m));
+}
+
+TEST(ElementsAreTest, CanDescribeNegationOfExpectingManyElements) {
+  Matcher<const list<std::string>&> m = ElementsAre("one", "two");
+  EXPECT_EQ(
+      "doesn't have 2 elements, or\n"
+      "element #0 isn't equal to \"one\", or\n"
+      "element #1 isn't equal to \"two\"",
+      DescribeNegation(m));
+}
+
+TEST(ElementsAreTest, DoesNotExplainTrivialMatch) {
+  Matcher<const list<int>&> m = ElementsAre(1, Ne(2));
+
+  list<int> test_list;
+  test_list.push_back(1);
+  test_list.push_back(3);
+  EXPECT_EQ("", Explain(m, test_list));  // No need to explain anything.
+}
+
+TEST_P(ElementsAreTestP, ExplainsNonTrivialMatch) {
+  Matcher<const vector<int>&> m =
+      ElementsAre(GreaterThan(1), 0, GreaterThan(2));
+
+  const int a[] = {10, 0, 100};
+  vector<int> test_vector(std::begin(a), std::end(a));
+  EXPECT_EQ(
+      "whose element #0 matches, which is 9 more than 1,\n"
+      "and whose element #2 matches, which is 98 more than 2",
+      Explain(m, test_vector));
+}
+
+TEST(ElementsAreTest, CanExplainMismatchWrongSize) {
+  Matcher<const list<int>&> m = ElementsAre(1, 3);
+
+  list<int> test_list;
+  // No need to explain when the container is empty.
+  EXPECT_EQ("", Explain(m, test_list));
+
+  test_list.push_back(1);
+  EXPECT_EQ("which has 1 element", Explain(m, test_list));
+}
+
+TEST_P(ElementsAreTestP, CanExplainMismatchRightSize) {
+  Matcher<const vector<int>&> m = ElementsAre(1, GreaterThan(5));
+
+  vector<int> v;
+  v.push_back(2);
+  v.push_back(1);
+  EXPECT_EQ("whose element #0 doesn't match", Explain(m, v));
+
+  v[0] = 1;
+  EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5",
+            Explain(m, v));
+}
+
+TEST(ElementsAreTest, MatchesOneElementVector) {
+  vector<std::string> test_vector;
+  test_vector.push_back("test string");
+
+  EXPECT_THAT(test_vector, ElementsAre(StrEq("test string")));
+}
+
+TEST(ElementsAreTest, MatchesOneElementList) {
+  list<std::string> test_list;
+  test_list.push_back("test string");
+
+  EXPECT_THAT(test_list, ElementsAre("test string"));
+}
+
+TEST(ElementsAreTest, MatchesThreeElementVector) {
+  vector<std::string> test_vector;
+  test_vector.push_back("one");
+  test_vector.push_back("two");
+  test_vector.push_back("three");
+
+  EXPECT_THAT(test_vector, ElementsAre("one", StrEq("two"), _));
+}
+
+TEST(ElementsAreTest, MatchesOneElementEqMatcher) {
+  vector<int> test_vector;
+  test_vector.push_back(4);
+
+  EXPECT_THAT(test_vector, ElementsAre(Eq(4)));
+}
+
+TEST(ElementsAreTest, MatchesOneElementAnyMatcher) {
+  vector<int> test_vector;
+  test_vector.push_back(4);
+
+  EXPECT_THAT(test_vector, ElementsAre(_));
+}
+
+TEST(ElementsAreTest, MatchesOneElementValue) {
+  vector<int> test_vector;
+  test_vector.push_back(4);
+
+  EXPECT_THAT(test_vector, ElementsAre(4));
+}
+
+TEST(ElementsAreTest, MatchesThreeElementsMixedMatchers) {
+  vector<int> test_vector;
+  test_vector.push_back(1);
+  test_vector.push_back(2);
+  test_vector.push_back(3);
+
+  EXPECT_THAT(test_vector, ElementsAre(1, Eq(2), _));
+}
+
+TEST(ElementsAreTest, MatchesTenElementVector) {
+  const int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+  vector<int> test_vector(std::begin(a), std::end(a));
+
+  EXPECT_THAT(test_vector,
+              // The element list can contain values and/or matchers
+              // of different types.
+              ElementsAre(0, Ge(0), _, 3, 4, Ne(2), Eq(6), 7, 8, _));
+}
+
+TEST(ElementsAreTest, DoesNotMatchWrongSize) {
+  vector<std::string> test_vector;
+  test_vector.push_back("test string");
+  test_vector.push_back("test string");
+
+  Matcher<vector<std::string>> m = ElementsAre(StrEq("test string"));
+  EXPECT_FALSE(m.Matches(test_vector));
+}
+
+TEST(ElementsAreTest, DoesNotMatchWrongValue) {
+  vector<std::string> test_vector;
+  test_vector.push_back("other string");
+
+  Matcher<vector<std::string>> m = ElementsAre(StrEq("test string"));
+  EXPECT_FALSE(m.Matches(test_vector));
+}
+
+TEST(ElementsAreTest, DoesNotMatchWrongOrder) {
+  vector<std::string> test_vector;
+  test_vector.push_back("one");
+  test_vector.push_back("three");
+  test_vector.push_back("two");
+
+  Matcher<vector<std::string>> m =
+      ElementsAre(StrEq("one"), StrEq("two"), StrEq("three"));
+  EXPECT_FALSE(m.Matches(test_vector));
+}
+
+TEST(ElementsAreTest, WorksForNestedContainer) {
+  constexpr std::array<const char*, 2> strings = {{"Hi", "world"}};
+
+  vector<list<char>> nested;
+  for (const auto& s : strings) {
+    nested.emplace_back(s, s + strlen(s));
+  }
+
+  EXPECT_THAT(nested, ElementsAre(ElementsAre('H', Ne('e')),
+                                  ElementsAre('w', 'o', _, _, 'd')));
+  EXPECT_THAT(nested, Not(ElementsAre(ElementsAre('H', 'e'),
+                                      ElementsAre('w', 'o', _, _, 'd'))));
+}
+
+TEST(ElementsAreTest, WorksWithByRefElementMatchers) {
+  int a[] = {0, 1, 2};
+  vector<int> v(std::begin(a), std::end(a));
+
+  EXPECT_THAT(v, ElementsAre(Ref(v[0]), Ref(v[1]), Ref(v[2])));
+  EXPECT_THAT(v, Not(ElementsAre(Ref(v[0]), Ref(v[1]), Ref(a[2]))));
+}
+
+TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) {
+  int a[] = {0, 1, 2};
+  vector<int> v(std::begin(a), std::end(a));
+
+  EXPECT_THAT(&v, Pointee(ElementsAre(0, 1, _)));
+  EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3))));
+}
+
+TEST(ElementsAreTest, WorksWithNativeArrayPassedByReference) {
+  int array[] = {0, 1, 2};
+  EXPECT_THAT(array, ElementsAre(0, 1, _));
+  EXPECT_THAT(array, Not(ElementsAre(1, _, _)));
+  EXPECT_THAT(array, Not(ElementsAre(0, _)));
+}
+
+class NativeArrayPassedAsPointerAndSize {
+ public:
+  NativeArrayPassedAsPointerAndSize() = default;
+
+  MOCK_METHOD(void, Helper, (int* array, int size));
+
+ private:
+  NativeArrayPassedAsPointerAndSize(const NativeArrayPassedAsPointerAndSize&) =
+      delete;
+  NativeArrayPassedAsPointerAndSize& operator=(
+      const NativeArrayPassedAsPointerAndSize&) = delete;
+};
+
+TEST(ElementsAreTest, WorksWithNativeArrayPassedAsPointerAndSize) {
+  int array[] = {0, 1};
+  ::std::tuple<int*, size_t> array_as_tuple(array, 2);
+  EXPECT_THAT(array_as_tuple, ElementsAre(0, 1));
+  EXPECT_THAT(array_as_tuple, Not(ElementsAre(0)));
+
+  NativeArrayPassedAsPointerAndSize helper;
+  EXPECT_CALL(helper, Helper(_, _)).With(ElementsAre(0, 1));
+  helper.Helper(array, 2);
+}
+
+TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) {
+  const char a2[][3] = {"hi", "lo"};
+  EXPECT_THAT(a2, ElementsAre(ElementsAre('h', 'i', '\0'),
+                              ElementsAre('l', 'o', '\0')));
+  EXPECT_THAT(a2, ElementsAre(StrEq("hi"), StrEq("lo")));
+  EXPECT_THAT(a2, ElementsAre(Not(ElementsAre('h', 'o', '\0')),
+                              ElementsAre('l', 'o', '\0')));
+}
+
+TEST(ElementsAreTest, AcceptsStringLiteral) {
+  std::string array[] = {"hi", "one", "two"};
+  EXPECT_THAT(array, ElementsAre("hi", "one", "two"));
+  EXPECT_THAT(array, Not(ElementsAre("hi", "one", "too")));
+}
+
+// Declared here with the size unknown.  Defined AFTER the following test.
+extern const char kHi[];
+
+TEST(ElementsAreTest, AcceptsArrayWithUnknownSize) {
+  // The size of kHi is not known in this test, but ElementsAre() should
+  // still accept it.
+
+  std::string array1[] = {"hi"};
+  EXPECT_THAT(array1, ElementsAre(kHi));
+
+  std::string array2[] = {"ho"};
+  EXPECT_THAT(array2, Not(ElementsAre(kHi)));
+}
+
+const char kHi[] = "hi";
+
+TEST(ElementsAreTest, MakesCopyOfArguments) {
+  int x = 1;
+  int y = 2;
+  // This should make a copy of x and y.
+  ::testing::internal::ElementsAreMatcher<std::tuple<int, int>>
+      polymorphic_matcher = ElementsAre(x, y);
+  // Changing x and y now shouldn't affect the meaning of the above matcher.
+  x = y = 0;
+  const int array1[] = {1, 2};
+  EXPECT_THAT(array1, polymorphic_matcher);
+  const int array2[] = {0, 0};
+  EXPECT_THAT(array2, Not(polymorphic_matcher));
+}
+
+// Tests for ElementsAreArray().  Since ElementsAreArray() shares most
+// of the implementation with ElementsAre(), we don't test it as
+// thoroughly here.
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithValueArray) {
+  const int a[] = {1, 2, 3};
+
+  vector<int> test_vector(std::begin(a), std::end(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(a));
+
+  test_vector[2] = 0;
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(a)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithArraySize) {
+  std::array<const char*, 3> a = {{"one", "two", "three"}};
+
+  vector<std::string> test_vector(std::begin(a), std::end(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(a.data(), a.size()));
+
+  const char** p = a.data();
+  test_vector[0] = "1";
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(p, a.size())));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithoutArraySize) {
+  const char* a[] = {"one", "two", "three"};
+
+  vector<std::string> test_vector(std::begin(a), std::end(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(a));
+
+  test_vector[0] = "1";
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(a)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) {
+  const Matcher<std::string> kMatcherArray[] = {StrEq("one"), StrEq("two"),
+                                                StrEq("three")};
+
+  vector<std::string> test_vector;
+  test_vector.push_back("one");
+  test_vector.push_back("two");
+  test_vector.push_back("three");
+  EXPECT_THAT(test_vector, ElementsAreArray(kMatcherArray));
+
+  test_vector.push_back("three");
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithVector) {
+  const int a[] = {1, 2, 3};
+  vector<int> test_vector(std::begin(a), std::end(a));
+  const vector<int> expected(std::begin(a), std::end(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(expected));
+  test_vector.push_back(4);
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(expected)));
+}
+
+TEST(ElementsAreArrayTest, TakesInitializerList) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  EXPECT_THAT(a, ElementsAreArray({1, 2, 3, 4, 5}));
+  EXPECT_THAT(a, Not(ElementsAreArray({1, 2, 3, 5, 4})));
+  EXPECT_THAT(a, Not(ElementsAreArray({1, 2, 3, 4, 6})));
+}
+
+TEST(ElementsAreArrayTest, TakesInitializerListOfCStrings) {
+  const std::string a[5] = {"a", "b", "c", "d", "e"};
+  EXPECT_THAT(a, ElementsAreArray({"a", "b", "c", "d", "e"}));
+  EXPECT_THAT(a, Not(ElementsAreArray({"a", "b", "c", "e", "d"})));
+  EXPECT_THAT(a, Not(ElementsAreArray({"a", "b", "c", "d", "ef"})));
+}
+
+TEST(ElementsAreArrayTest, TakesInitializerListOfSameTypedMatchers) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  EXPECT_THAT(a, ElementsAreArray({Eq(1), Eq(2), Eq(3), Eq(4), Eq(5)}));
+  EXPECT_THAT(a, Not(ElementsAreArray({Eq(1), Eq(2), Eq(3), Eq(4), Eq(6)})));
+}
+
+TEST(ElementsAreArrayTest, TakesInitializerListOfDifferentTypedMatchers) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  // The compiler cannot infer the type of the initializer list if its
+  // elements have different types.  We must explicitly specify the
+  // unified element type in this case.
+  EXPECT_THAT(
+      a, ElementsAreArray<Matcher<int>>({Eq(1), Ne(-2), Ge(3), Le(4), Eq(5)}));
+  EXPECT_THAT(a, Not(ElementsAreArray<Matcher<int>>(
+                     {Eq(1), Ne(-2), Ge(3), Le(4), Eq(6)})));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherVector) {
+  const int a[] = {1, 2, 3};
+  const Matcher<int> kMatchers[] = {Eq(1), Eq(2), Eq(3)};
+  vector<int> test_vector(std::begin(a), std::end(a));
+  const vector<Matcher<int>> expected(std::begin(kMatchers),
+                                      std::end(kMatchers));
+  EXPECT_THAT(test_vector, ElementsAreArray(expected));
+  test_vector.push_back(4);
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(expected)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithIteratorRange) {
+  const int a[] = {1, 2, 3};
+  const vector<int> test_vector(std::begin(a), std::end(a));
+  const vector<int> expected(std::begin(a), std::end(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(expected.begin(), expected.end()));
+  // Pointers are iterators, too.
+  EXPECT_THAT(test_vector, ElementsAreArray(std::begin(a), std::end(a)));
+  // The empty range of NULL pointers should also be okay.
+  int* const null_int = nullptr;
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(null_int, null_int)));
+  EXPECT_THAT((vector<int>()), ElementsAreArray(null_int, null_int));
+}
+
+// Since ElementsAre() and ElementsAreArray() share much of the
+// implementation, we only do a test for native arrays here.
+TEST(ElementsAreArrayTest, WorksWithNativeArray) {
+  ::std::string a[] = {"hi", "ho"};
+  ::std::string b[] = {"hi", "ho"};
+
+  EXPECT_THAT(a, ElementsAreArray(b));
+  EXPECT_THAT(a, ElementsAreArray(b, 2));
+  EXPECT_THAT(a, Not(ElementsAreArray(b, 1)));
+}
+
+TEST(ElementsAreArrayTest, SourceLifeSpan) {
+  const int a[] = {1, 2, 3};
+  vector<int> test_vector(std::begin(a), std::end(a));
+  vector<int> expect(std::begin(a), std::end(a));
+  ElementsAreArrayMatcher<int> matcher_maker =
+      ElementsAreArray(expect.begin(), expect.end());
+  EXPECT_THAT(test_vector, matcher_maker);
+  // Changing in place the values that initialized matcher_maker should not
+  // affect matcher_maker anymore. It should have made its own copy of them.
+  for (int& i : expect) {
+    i += 10;
+  }
+  EXPECT_THAT(test_vector, matcher_maker);
+  test_vector.push_back(3);
+  EXPECT_THAT(test_vector, Not(matcher_maker));
+}
+
+// Tests Contains().
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(ContainsTest);
+
+TEST(ContainsTest, ListMatchesWhenElementIsInContainer) {
+  list<int> some_list;
+  some_list.push_back(3);
+  some_list.push_back(1);
+  some_list.push_back(2);
+  some_list.push_back(3);
+  EXPECT_THAT(some_list, Contains(1));
+  EXPECT_THAT(some_list, Contains(Gt(2.5)));
+  EXPECT_THAT(some_list, Contains(Eq(2.0f)));
+
+  list<std::string> another_list;
+  another_list.push_back("fee");
+  another_list.push_back("fie");
+  another_list.push_back("foe");
+  another_list.push_back("fum");
+  EXPECT_THAT(another_list, Contains(std::string("fee")));
+}
+
+TEST(ContainsTest, ListDoesNotMatchWhenElementIsNotInContainer) {
+  list<int> some_list;
+  some_list.push_back(3);
+  some_list.push_back(1);
+  EXPECT_THAT(some_list, Not(Contains(4)));
+}
+
+TEST(ContainsTest, SetMatchesWhenElementIsInContainer) {
+  set<int> some_set;
+  some_set.insert(3);
+  some_set.insert(1);
+  some_set.insert(2);
+  EXPECT_THAT(some_set, Contains(Eq(1.0)));
+  EXPECT_THAT(some_set, Contains(Eq(3.0f)));
+  EXPECT_THAT(some_set, Contains(2));
+
+  set<std::string> another_set;
+  another_set.insert("fee");
+  another_set.insert("fie");
+  another_set.insert("foe");
+  another_set.insert("fum");
+  EXPECT_THAT(another_set, Contains(Eq(std::string("fum"))));
+}
+
+TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
+  set<int> some_set;
+  some_set.insert(3);
+  some_set.insert(1);
+  EXPECT_THAT(some_set, Not(Contains(4)));
+
+  set<std::string> c_string_set;
+  c_string_set.insert("hello");
+  EXPECT_THAT(c_string_set, Not(Contains(std::string("goodbye"))));
+}
+
+TEST_P(ContainsTestP, ExplainsMatchResultCorrectly) {
+  const int a[2] = {1, 2};
+  Matcher<const int(&)[2]> m = Contains(2);
+  EXPECT_EQ("whose element #1 matches", Explain(m, a));
+
+  m = Contains(3);
+  EXPECT_EQ("", Explain(m, a));
+
+  m = Contains(GreaterThan(0));
+  EXPECT_EQ("whose element #0 matches, which is 1 more than 0", Explain(m, a));
+
+  m = Contains(GreaterThan(10));
+  EXPECT_EQ("", Explain(m, a));
+}
+
+TEST(ContainsTest, DescribesItselfCorrectly) {
+  Matcher<vector<int>> m = Contains(1);
+  EXPECT_EQ("contains at least one element that is equal to 1", Describe(m));
+
+  Matcher<vector<int>> m2 = Not(m);
+  EXPECT_EQ("doesn't contain any element that is equal to 1", Describe(m2));
+}
+
+TEST(ContainsTest, MapMatchesWhenElementIsInContainer) {
+  map<std::string, int> my_map;
+  const char* bar = "a string";
+  my_map[bar] = 2;
+  EXPECT_THAT(my_map, Contains(pair<const char* const, int>(bar, 2)));
+
+  map<std::string, int> another_map;
+  another_map["fee"] = 1;
+  another_map["fie"] = 2;
+  another_map["foe"] = 3;
+  another_map["fum"] = 4;
+  EXPECT_THAT(another_map,
+              Contains(pair<const std::string, int>(std::string("fee"), 1)));
+  EXPECT_THAT(another_map, Contains(pair<const std::string, int>("fie", 2)));
+}
+
+TEST(ContainsTest, MapDoesNotMatchWhenElementIsNotInContainer) {
+  map<int, int> some_map;
+  some_map[1] = 11;
+  some_map[2] = 22;
+  EXPECT_THAT(some_map, Not(Contains(pair<const int, int>(2, 23))));
+}
+
+TEST(ContainsTest, ArrayMatchesWhenElementIsInContainer) {
+  const char* string_array[] = {"fee", "fie", "foe", "fum"};
+  EXPECT_THAT(string_array, Contains(Eq(std::string("fum"))));
+}
+
+TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) {
+  int int_array[] = {1, 2, 3, 4};
+  EXPECT_THAT(int_array, Not(Contains(5)));
+}
+
+TEST(ContainsTest, AcceptsMatcher) {
+  const int a[] = {1, 2, 3};
+  EXPECT_THAT(a, Contains(Gt(2)));
+  EXPECT_THAT(a, Not(Contains(Gt(4))));
+}
+
+TEST(ContainsTest, WorksForNativeArrayAsTuple) {
+  const int a[] = {1, 2};
+  const int* const pointer = a;
+  EXPECT_THAT(std::make_tuple(pointer, 2), Contains(1));
+  EXPECT_THAT(std::make_tuple(pointer, 2), Not(Contains(Gt(3))));
+}
+
+TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
+  int a[][3] = {{1, 2, 3}, {4, 5, 6}};
+  EXPECT_THAT(a, Contains(ElementsAre(4, 5, 6)));
+  EXPECT_THAT(a, Contains(Contains(5)));
+  EXPECT_THAT(a, Not(Contains(ElementsAre(3, 4, 5))));
+  EXPECT_THAT(a, Contains(Not(Contains(5))));
+}
+
+}  // namespace
+}  // namespace gmock_matchers_test
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4244 4100
diff --git a/3rd-party/googletest/googlemock/test/gmock-matchers-misc_test.cc b/3rd-party/googletest/googlemock/test/gmock-matchers-misc_test.cc
new file mode 100644
index 0000000..b8f6458
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-matchers-misc_test.cc
@@ -0,0 +1,1823 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests some commonly used argument matchers.
+
+#include <array>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
+// possible loss of data and C4100, unreferenced local parameter
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
+
+#include "test/gmock-matchers_test.h"
+
+namespace testing {
+namespace gmock_matchers_test {
+namespace {
+
+TEST(AddressTest, NonConst) {
+  int n = 1;
+  const Matcher<int> m = Address(Eq(&n));
+
+  EXPECT_TRUE(m.Matches(n));
+
+  int other = 5;
+
+  EXPECT_FALSE(m.Matches(other));
+
+  int& n_ref = n;
+
+  EXPECT_TRUE(m.Matches(n_ref));
+}
+
+TEST(AddressTest, Const) {
+  const int n = 1;
+  const Matcher<int> m = Address(Eq(&n));
+
+  EXPECT_TRUE(m.Matches(n));
+
+  int other = 5;
+
+  EXPECT_FALSE(m.Matches(other));
+}
+
+TEST(AddressTest, MatcherDoesntCopy) {
+  std::unique_ptr<int> n(new int(1));
+  const Matcher<std::unique_ptr<int>> m = Address(Eq(&n));
+
+  EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(AddressTest, Describe) {
+  Matcher<int> matcher = Address(_);
+  EXPECT_EQ("has address that is anything", Describe(matcher));
+  EXPECT_EQ("does not have address that is anything",
+            DescribeNegation(matcher));
+}
+
+// The following two tests verify that values without a public copy
+// ctor can be used as arguments to matchers like Eq(), Ge(), and etc
+// with the help of ByRef().
+
+class NotCopyable {
+ public:
+  explicit NotCopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+
+  bool operator==(const NotCopyable& rhs) const {
+    return value() == rhs.value();
+  }
+
+  bool operator>=(const NotCopyable& rhs) const {
+    return value() >= rhs.value();
+  }
+
+ private:
+  int value_;
+
+  NotCopyable(const NotCopyable&) = delete;
+  NotCopyable& operator=(const NotCopyable&) = delete;
+};
+
+TEST(ByRefTest, AllowsNotCopyableConstValueInMatchers) {
+  const NotCopyable const_value1(1);
+  const Matcher<const NotCopyable&> m = Eq(ByRef(const_value1));
+
+  const NotCopyable n1(1), n2(2);
+  EXPECT_TRUE(m.Matches(n1));
+  EXPECT_FALSE(m.Matches(n2));
+}
+
+TEST(ByRefTest, AllowsNotCopyableValueInMatchers) {
+  NotCopyable value2(2);
+  const Matcher<NotCopyable&> m = Ge(ByRef(value2));
+
+  NotCopyable n1(1), n2(2);
+  EXPECT_FALSE(m.Matches(n1));
+  EXPECT_TRUE(m.Matches(n2));
+}
+
+TEST(IsEmptyTest, ImplementsIsEmpty) {
+  vector<int> container;
+  EXPECT_THAT(container, IsEmpty());
+  container.push_back(0);
+  EXPECT_THAT(container, Not(IsEmpty()));
+  container.push_back(1);
+  EXPECT_THAT(container, Not(IsEmpty()));
+}
+
+TEST(IsEmptyTest, WorksWithString) {
+  std::string text;
+  EXPECT_THAT(text, IsEmpty());
+  text = "foo";
+  EXPECT_THAT(text, Not(IsEmpty()));
+  text = std::string("\0", 1);
+  EXPECT_THAT(text, Not(IsEmpty()));
+}
+
+TEST(IsEmptyTest, CanDescribeSelf) {
+  Matcher<vector<int>> m = IsEmpty();
+  EXPECT_EQ("is empty", Describe(m));
+  EXPECT_EQ("isn't empty", DescribeNegation(m));
+}
+
+TEST(IsEmptyTest, ExplainsResult) {
+  Matcher<vector<int>> m = IsEmpty();
+  vector<int> container;
+  EXPECT_EQ("", Explain(m, container));
+  container.push_back(0);
+  EXPECT_EQ("whose size is 1", Explain(m, container));
+}
+
+TEST(IsEmptyTest, WorksWithMoveOnly) {
+  ContainerHelper helper;
+  EXPECT_CALL(helper, Call(IsEmpty()));
+  helper.Call({});
+}
+
+TEST(IsTrueTest, IsTrueIsFalse) {
+  EXPECT_THAT(true, IsTrue());
+  EXPECT_THAT(false, IsFalse());
+  EXPECT_THAT(true, Not(IsFalse()));
+  EXPECT_THAT(false, Not(IsTrue()));
+  EXPECT_THAT(0, Not(IsTrue()));
+  EXPECT_THAT(0, IsFalse());
+  EXPECT_THAT(nullptr, Not(IsTrue()));
+  EXPECT_THAT(nullptr, IsFalse());
+  EXPECT_THAT(-1, IsTrue());
+  EXPECT_THAT(-1, Not(IsFalse()));
+  EXPECT_THAT(1, IsTrue());
+  EXPECT_THAT(1, Not(IsFalse()));
+  EXPECT_THAT(2, IsTrue());
+  EXPECT_THAT(2, Not(IsFalse()));
+  int a = 42;
+  EXPECT_THAT(a, IsTrue());
+  EXPECT_THAT(a, Not(IsFalse()));
+  EXPECT_THAT(&a, IsTrue());
+  EXPECT_THAT(&a, Not(IsFalse()));
+  EXPECT_THAT(false, Not(IsTrue()));
+  EXPECT_THAT(true, Not(IsFalse()));
+  EXPECT_THAT(std::true_type(), IsTrue());
+  EXPECT_THAT(std::true_type(), Not(IsFalse()));
+  EXPECT_THAT(std::false_type(), IsFalse());
+  EXPECT_THAT(std::false_type(), Not(IsTrue()));
+  EXPECT_THAT(nullptr, Not(IsTrue()));
+  EXPECT_THAT(nullptr, IsFalse());
+  std::unique_ptr<int> null_unique;
+  std::unique_ptr<int> nonnull_unique(new int(0));
+  EXPECT_THAT(null_unique, Not(IsTrue()));
+  EXPECT_THAT(null_unique, IsFalse());
+  EXPECT_THAT(nonnull_unique, IsTrue());
+  EXPECT_THAT(nonnull_unique, Not(IsFalse()));
+}
+
+#ifdef GTEST_HAS_TYPED_TEST
+// Tests ContainerEq with different container types, and
+// different element types.
+
+template <typename T>
+class ContainerEqTest : public testing::Test {};
+
+typedef testing::Types<set<int>, vector<size_t>, multiset<size_t>, list<int>>
+    ContainerEqTestTypes;
+
+TYPED_TEST_SUITE(ContainerEqTest, ContainerEqTestTypes);
+
+// Tests that the filled container is equal to itself.
+TYPED_TEST(ContainerEqTest, EqualsSelf) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  TypeParam my_set(vals, vals + 6);
+  const Matcher<TypeParam> m = ContainerEq(my_set);
+  EXPECT_TRUE(m.Matches(my_set));
+  EXPECT_EQ("", Explain(m, my_set));
+}
+
+// Tests that missing values are reported.
+TYPED_TEST(ContainerEqTest, ValueMissing) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {2, 1, 8, 5};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 4);
+  const Matcher<TypeParam> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which doesn't have these expected elements: 3",
+            Explain(m, test_set));
+}
+
+// Tests that added values are reported.
+TYPED_TEST(ContainerEqTest, ValueAdded) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 5, 8, 46};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 6);
+  const Matcher<const TypeParam&> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which has these unexpected elements: 46", Explain(m, test_set));
+}
+
+// Tests that added and missing values are reported together.
+TYPED_TEST(ContainerEqTest, ValueAddedAndRemoved) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 8, 46};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 5);
+  const Matcher<TypeParam> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ(
+      "which has these unexpected elements: 46,\n"
+      "and doesn't have these expected elements: 5",
+      Explain(m, test_set));
+}
+
+// Tests duplicated value -- expect no explanation.
+TYPED_TEST(ContainerEqTest, DuplicateDifference) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 5, 8};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 5);
+  const Matcher<const TypeParam&> m = ContainerEq(my_set);
+  // Depending on the container, match may be true or false
+  // But in any case there should be no explanation.
+  EXPECT_EQ("", Explain(m, test_set));
+}
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Tests that multiple missing values are reported.
+// Using just vector here, so order is predictable.
+TEST(ContainerEqExtraTest, MultipleValuesMissing) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {2, 1, 5};
+  vector<int> my_set(vals, vals + 6);
+  vector<int> test_set(test_vals, test_vals + 3);
+  const Matcher<vector<int>> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which doesn't have these expected elements: 3, 8",
+            Explain(m, test_set));
+}
+
+// Tests that added values are reported.
+// Using just vector here, so order is predictable.
+TEST(ContainerEqExtraTest, MultipleValuesAdded) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 92, 3, 5, 8, 46};
+  list<size_t> my_set(vals, vals + 6);
+  list<size_t> test_set(test_vals, test_vals + 7);
+  const Matcher<const list<size_t>&> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which has these unexpected elements: 92, 46",
+            Explain(m, test_set));
+}
+
+// Tests that added and missing values are reported together.
+TEST(ContainerEqExtraTest, MultipleValuesAddedAndRemoved) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 92, 46};
+  list<size_t> my_set(vals, vals + 6);
+  list<size_t> test_set(test_vals, test_vals + 5);
+  const Matcher<const list<size_t>> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ(
+      "which has these unexpected elements: 92, 46,\n"
+      "and doesn't have these expected elements: 5, 8",
+      Explain(m, test_set));
+}
+
+// Tests to see that duplicate elements are detected,
+// but (as above) not reported in the explanation.
+TEST(ContainerEqExtraTest, MultiSetOfIntDuplicateDifference) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 5, 8};
+  vector<int> my_set(vals, vals + 6);
+  vector<int> test_set(test_vals, test_vals + 5);
+  const Matcher<vector<int>> m = ContainerEq(my_set);
+  EXPECT_TRUE(m.Matches(my_set));
+  EXPECT_FALSE(m.Matches(test_set));
+  // There is nothing to report when both sets contain all the same values.
+  EXPECT_EQ("", Explain(m, test_set));
+}
+
+// Tests that ContainerEq works for non-trivial associative containers,
+// like maps.
+TEST(ContainerEqExtraTest, WorksForMaps) {
+  map<int, std::string> my_map;
+  my_map[0] = "a";
+  my_map[1] = "b";
+
+  map<int, std::string> test_map;
+  test_map[0] = "aa";
+  test_map[1] = "b";
+
+  const Matcher<const map<int, std::string>&> m = ContainerEq(my_map);
+  EXPECT_TRUE(m.Matches(my_map));
+  EXPECT_FALSE(m.Matches(test_map));
+
+  EXPECT_EQ(
+      "which has these unexpected elements: (0, \"aa\"),\n"
+      "and doesn't have these expected elements: (0, \"a\")",
+      Explain(m, test_map));
+}
+
+TEST(ContainerEqExtraTest, WorksForNativeArray) {
+  int a1[] = {1, 2, 3};
+  int a2[] = {1, 2, 3};
+  int b[] = {1, 2, 4};
+
+  EXPECT_THAT(a1, ContainerEq(a2));
+  EXPECT_THAT(a1, Not(ContainerEq(b)));
+}
+
+TEST(ContainerEqExtraTest, WorksForTwoDimensionalNativeArray) {
+  const char a1[][3] = {"hi", "lo"};
+  const char a2[][3] = {"hi", "lo"};
+  const char b[][3] = {"lo", "hi"};
+
+  // Tests using ContainerEq() in the first dimension.
+  EXPECT_THAT(a1, ContainerEq(a2));
+  EXPECT_THAT(a1, Not(ContainerEq(b)));
+
+  // Tests using ContainerEq() in the second dimension.
+  EXPECT_THAT(a1, ElementsAre(ContainerEq(a2[0]), ContainerEq(a2[1])));
+  EXPECT_THAT(a1, ElementsAre(Not(ContainerEq(b[0])), ContainerEq(a2[1])));
+}
+
+TEST(ContainerEqExtraTest, WorksForNativeArrayAsTuple) {
+  const int a1[] = {1, 2, 3};
+  const int a2[] = {1, 2, 3};
+  const int b[] = {1, 2, 3, 4};
+
+  const int* const p1 = a1;
+  EXPECT_THAT(std::make_tuple(p1, 3), ContainerEq(a2));
+  EXPECT_THAT(std::make_tuple(p1, 3), Not(ContainerEq(b)));
+
+  const int c[] = {1, 3, 2};
+  EXPECT_THAT(std::make_tuple(p1, 3), Not(ContainerEq(c)));
+}
+
+TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
+  std::string a1[][3] = {{"hi", "hello", "ciao"}, {"bye", "see you", "ciao"}};
+
+  std::string a2[][3] = {{"hi", "hello", "ciao"}, {"bye", "see you", "ciao"}};
+
+  const Matcher<const std::string(&)[2][3]> m = ContainerEq(a2);
+  EXPECT_THAT(a1, m);
+
+  a2[0][0] = "ha";
+  EXPECT_THAT(a1, m);
+}
+
+namespace {
+
+// Used as a check on the more complex max flow method used in the
+// real testing::internal::FindMaxBipartiteMatching. This method is
+// compatible but runs in worst-case factorial time, so we only
+// use it in testing for small problem sizes.
+template <typename Graph>
+class BacktrackingMaxBPMState {
+ public:
+  // Does not take ownership of 'g'.
+  explicit BacktrackingMaxBPMState(const Graph* g) : graph_(g) {}
+
+  ElementMatcherPairs Compute() {
+    if (graph_->LhsSize() == 0 || graph_->RhsSize() == 0) {
+      return best_so_far_;
+    }
+    lhs_used_.assign(graph_->LhsSize(), kUnused);
+    rhs_used_.assign(graph_->RhsSize(), kUnused);
+    for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
+      matches_.clear();
+      RecurseInto(irhs);
+      if (best_so_far_.size() == graph_->RhsSize()) break;
+    }
+    return best_so_far_;
+  }
+
+ private:
+  static const size_t kUnused = static_cast<size_t>(-1);
+
+  void PushMatch(size_t lhs, size_t rhs) {
+    matches_.push_back(ElementMatcherPair(lhs, rhs));
+    lhs_used_[lhs] = rhs;
+    rhs_used_[rhs] = lhs;
+    if (matches_.size() > best_so_far_.size()) {
+      best_so_far_ = matches_;
+    }
+  }
+
+  void PopMatch() {
+    const ElementMatcherPair& back = matches_.back();
+    lhs_used_[back.first] = kUnused;
+    rhs_used_[back.second] = kUnused;
+    matches_.pop_back();
+  }
+
+  bool RecurseInto(size_t irhs) {
+    if (rhs_used_[irhs] != kUnused) {
+      return true;
+    }
+    for (size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) {
+      if (lhs_used_[ilhs] != kUnused) {
+        continue;
+      }
+      if (!graph_->HasEdge(ilhs, irhs)) {
+        continue;
+      }
+      PushMatch(ilhs, irhs);
+      if (best_so_far_.size() == graph_->RhsSize()) {
+        return false;
+      }
+      for (size_t mi = irhs + 1; mi < graph_->RhsSize(); ++mi) {
+        if (!RecurseInto(mi)) return false;
+      }
+      PopMatch();
+    }
+    return true;
+  }
+
+  const Graph* graph_;  // not owned
+  std::vector<size_t> lhs_used_;
+  std::vector<size_t> rhs_used_;
+  ElementMatcherPairs matches_;
+  ElementMatcherPairs best_so_far_;
+};
+
+template <typename Graph>
+const size_t BacktrackingMaxBPMState<Graph>::kUnused;
+
+}  // namespace
+
+// Implement a simple backtracking algorithm to determine if it is possible
+// to find one element per matcher, without reusing elements.
+template <typename Graph>
+ElementMatcherPairs FindBacktrackingMaxBPM(const Graph& g) {
+  return BacktrackingMaxBPMState<Graph>(&g).Compute();
+}
+
+class BacktrackingBPMTest : public ::testing::Test {};
+
+// Tests the MaxBipartiteMatching algorithm with square matrices.
+// The single int param is the # of nodes on each of the left and right sides.
+class BipartiteTest : public ::testing::TestWithParam<size_t> {};
+
+// Verify all match graphs up to some moderate number of edges.
+TEST_P(BipartiteTest, Exhaustive) {
+  size_t nodes = GetParam();
+  MatchMatrix graph(nodes, nodes);
+  do {
+    ElementMatcherPairs matches = internal::FindMaxBipartiteMatching(graph);
+    EXPECT_EQ(FindBacktrackingMaxBPM(graph).size(), matches.size())
+        << "graph: " << graph.DebugString();
+    // Check that all elements of matches are in the graph.
+    // Check that elements of first and second are unique.
+    std::vector<bool> seen_element(graph.LhsSize());
+    std::vector<bool> seen_matcher(graph.RhsSize());
+    SCOPED_TRACE(PrintToString(matches));
+    for (size_t i = 0; i < matches.size(); ++i) {
+      size_t ilhs = matches[i].first;
+      size_t irhs = matches[i].second;
+      EXPECT_TRUE(graph.HasEdge(ilhs, irhs));
+      EXPECT_FALSE(seen_element[ilhs]);
+      EXPECT_FALSE(seen_matcher[irhs]);
+      seen_element[ilhs] = true;
+      seen_matcher[irhs] = true;
+    }
+  } while (graph.NextGraph());
+}
+
+INSTANTIATE_TEST_SUITE_P(AllGraphs, BipartiteTest,
+                         ::testing::Range(size_t{0}, size_t{5}));
+
+// Parameterized by a pair interpreted as (LhsSize, RhsSize).
+class BipartiteNonSquareTest
+    : public ::testing::TestWithParam<std::pair<size_t, size_t>> {};
+
+TEST_F(BipartiteNonSquareTest, SimpleBacktracking) {
+  //   .......
+  // 0:-----\ :
+  // 1:---\ | :
+  // 2:---\ | :
+  // 3:-\ | | :
+  //  :.......:
+  //    0 1 2
+  MatchMatrix g(4, 3);
+  constexpr std::array<std::array<size_t, 2>, 4> kEdges = {
+      {{{0, 2}}, {{1, 1}}, {{2, 1}}, {{3, 0}}}};
+  for (size_t i = 0; i < kEdges.size(); ++i) {
+    g.SetEdge(kEdges[i][0], kEdges[i][1], true);
+  }
+  EXPECT_THAT(FindBacktrackingMaxBPM(g),
+              ElementsAre(Pair(3, 0), Pair(AnyOf(1, 2), 1), Pair(0, 2)))
+      << g.DebugString();
+}
+
+// Verify a few nonsquare matrices.
+TEST_P(BipartiteNonSquareTest, Exhaustive) {
+  size_t nlhs = GetParam().first;
+  size_t nrhs = GetParam().second;
+  MatchMatrix graph(nlhs, nrhs);
+  do {
+    EXPECT_EQ(FindBacktrackingMaxBPM(graph).size(),
+              internal::FindMaxBipartiteMatching(graph).size())
+        << "graph: " << graph.DebugString()
+        << "\nbacktracking: " << PrintToString(FindBacktrackingMaxBPM(graph))
+        << "\nmax flow: "
+        << PrintToString(internal::FindMaxBipartiteMatching(graph));
+  } while (graph.NextGraph());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    AllGraphs, BipartiteNonSquareTest,
+    testing::Values(std::make_pair(1, 2), std::make_pair(2, 1),
+                    std::make_pair(3, 2), std::make_pair(2, 3),
+                    std::make_pair(4, 1), std::make_pair(1, 4),
+                    std::make_pair(4, 3), std::make_pair(3, 4)));
+
+class BipartiteRandomTest
+    : public ::testing::TestWithParam<std::pair<int, int>> {};
+
+// Verifies a large sample of larger graphs.
+TEST_P(BipartiteRandomTest, LargerNets) {
+  int nodes = GetParam().first;
+  int iters = GetParam().second;
+  MatchMatrix graph(static_cast<size_t>(nodes), static_cast<size_t>(nodes));
+
+  auto seed = static_cast<uint32_t>(GTEST_FLAG_GET(random_seed));
+  if (seed == 0) {
+    seed = static_cast<uint32_t>(time(nullptr));
+  }
+
+  for (; iters > 0; --iters, ++seed) {
+    srand(static_cast<unsigned int>(seed));
+    graph.Randomize();
+    EXPECT_EQ(FindBacktrackingMaxBPM(graph).size(),
+              internal::FindMaxBipartiteMatching(graph).size())
+        << " graph: " << graph.DebugString()
+        << "\nTo reproduce the failure, rerun the test with the flag"
+           " --"
+        << GTEST_FLAG_PREFIX_ << "random_seed=" << seed;
+  }
+}
+
+// Test argument is a std::pair<int, int> representing (nodes, iters).
+INSTANTIATE_TEST_SUITE_P(Samples, BipartiteRandomTest,
+                         testing::Values(std::make_pair(5, 10000),
+                                         std::make_pair(6, 5000),
+                                         std::make_pair(7, 2000),
+                                         std::make_pair(8, 500),
+                                         std::make_pair(9, 100)));
+
+// Tests IsReadableTypeName().
+
+TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
+  EXPECT_TRUE(IsReadableTypeName("int"));
+  EXPECT_TRUE(IsReadableTypeName("const unsigned char*"));
+  EXPECT_TRUE(IsReadableTypeName("MyMap<int, void*>"));
+  EXPECT_TRUE(IsReadableTypeName("void (*)(int, bool)"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsTrueForLongNonTemplateNonFunctionNames) {
+  EXPECT_TRUE(IsReadableTypeName("my_long_namespace::MyClassName"));
+  EXPECT_TRUE(IsReadableTypeName("int [5][6][7][8][9][10][11]"));
+  EXPECT_TRUE(IsReadableTypeName("my_namespace::MyOuterClass::MyInnerClass"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsFalseForLongTemplateNames) {
+  EXPECT_FALSE(
+      IsReadableTypeName("basic_string<char, std::char_traits<char> >"));
+  EXPECT_FALSE(IsReadableTypeName("std::vector<int, std::alloc_traits<int> >"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsFalseForLongFunctionTypeNames) {
+  EXPECT_FALSE(IsReadableTypeName("void (&)(int, bool, char, float)"));
+}
+
+// Tests FormatMatcherDescription().
+
+TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) {
+  EXPECT_EQ("is even",
+            FormatMatcherDescription(false, "IsEven", {}, Strings()));
+  EXPECT_EQ("not (is even)",
+            FormatMatcherDescription(true, "IsEven", {}, Strings()));
+
+  EXPECT_EQ("equals (a: 5)",
+            FormatMatcherDescription(false, "Equals", {"a"}, {"5"}));
+
+  EXPECT_EQ(
+      "is in range (a: 5, b: 8)",
+      FormatMatcherDescription(false, "IsInRange", {"a", "b"}, {"5", "8"}));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(MatcherTupleTest);
+
+TEST_P(MatcherTupleTestP, ExplainsMatchFailure) {
+  stringstream ss1;
+  ExplainMatchFailureTupleTo(
+      std::make_tuple(Matcher<char>(Eq('a')), GreaterThan(5)),
+      std::make_tuple('a', 10), &ss1);
+  EXPECT_EQ("", ss1.str());  // Successful match.
+
+  stringstream ss2;
+  ExplainMatchFailureTupleTo(
+      std::make_tuple(GreaterThan(5), Matcher<char>(Eq('a'))),
+      std::make_tuple(2, 'b'), &ss2);
+  EXPECT_EQ(
+      "  Expected arg #0: is > 5\n"
+      "           Actual: 2, which is 3 less than 5\n"
+      "  Expected arg #1: is equal to 'a' (97, 0x61)\n"
+      "           Actual: 'b' (98, 0x62)\n",
+      ss2.str());  // Failed match where both arguments need explanation.
+
+  stringstream ss3;
+  ExplainMatchFailureTupleTo(
+      std::make_tuple(GreaterThan(5), Matcher<char>(Eq('a'))),
+      std::make_tuple(2, 'a'), &ss3);
+  EXPECT_EQ(
+      "  Expected arg #0: is > 5\n"
+      "           Actual: 2, which is 3 less than 5\n",
+      ss3.str());  // Failed match where only one argument needs
+                   // explanation.
+}
+
+// Sample optional type implementation with minimal requirements for use with
+// Optional matcher.
+template <typename T>
+class SampleOptional {
+ public:
+  using value_type = T;
+  explicit SampleOptional(T value)
+      : value_(std::move(value)), has_value_(true) {}
+  SampleOptional() : value_(), has_value_(false) {}
+  operator bool() const { return has_value_; }
+  const T& operator*() const { return value_; }
+
+ private:
+  T value_;
+  bool has_value_;
+};
+
+TEST(OptionalTest, DescribesSelf) {
+  const Matcher<SampleOptional<int>> m = Optional(Eq(1));
+  EXPECT_EQ("value is equal to 1", Describe(m));
+}
+
+TEST(OptionalTest, ExplainsSelf) {
+  const Matcher<SampleOptional<int>> m = Optional(Eq(1));
+  EXPECT_EQ("whose value 1 matches", Explain(m, SampleOptional<int>(1)));
+  EXPECT_EQ("whose value 2 doesn't match", Explain(m, SampleOptional<int>(2)));
+}
+
+TEST(OptionalTest, MatchesNonEmptyOptional) {
+  const Matcher<SampleOptional<int>> m1 = Optional(1);
+  const Matcher<SampleOptional<int>> m2 = Optional(Eq(2));
+  const Matcher<SampleOptional<int>> m3 = Optional(Lt(3));
+  SampleOptional<int> opt(1);
+  EXPECT_TRUE(m1.Matches(opt));
+  EXPECT_FALSE(m2.Matches(opt));
+  EXPECT_TRUE(m3.Matches(opt));
+}
+
+TEST(OptionalTest, DoesNotMatchNullopt) {
+  const Matcher<SampleOptional<int>> m = Optional(1);
+  SampleOptional<int> empty;
+  EXPECT_FALSE(m.Matches(empty));
+}
+
+TEST(OptionalTest, WorksWithMoveOnly) {
+  Matcher<SampleOptional<std::unique_ptr<int>>> m = Optional(Eq(nullptr));
+  EXPECT_TRUE(m.Matches(SampleOptional<std::unique_ptr<int>>(nullptr)));
+}
+
+class SampleVariantIntString {
+ public:
+  SampleVariantIntString(int i) : i_(i), has_int_(true) {}
+  SampleVariantIntString(const std::string& s) : s_(s), has_int_(false) {}
+
+  template <typename T>
+  friend bool holds_alternative(const SampleVariantIntString& value) {
+    return value.has_int_ == std::is_same<T, int>::value;
+  }
+
+  template <typename T>
+  friend const T& get(const SampleVariantIntString& value) {
+    return value.get_impl(static_cast<T*>(nullptr));
+  }
+
+ private:
+  const int& get_impl(int*) const { return i_; }
+  const std::string& get_impl(std::string*) const { return s_; }
+
+  int i_;
+  std::string s_;
+  bool has_int_;
+};
+
+TEST(VariantTest, DescribesSelf) {
+  const Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
+  EXPECT_THAT(Describe(m), ContainsRegex("is a variant<> with value of type "
+                                         "'.*' and the value is equal to 1"));
+}
+
+TEST(VariantTest, ExplainsSelf) {
+  const Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
+  EXPECT_THAT(Explain(m, SampleVariantIntString(1)),
+              ContainsRegex("whose value 1"));
+  EXPECT_THAT(Explain(m, SampleVariantIntString("A")),
+              HasSubstr("whose value is not of type '"));
+  EXPECT_THAT(Explain(m, SampleVariantIntString(2)),
+              "whose value 2 doesn't match");
+}
+
+TEST(VariantTest, FullMatch) {
+  Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
+  EXPECT_TRUE(m.Matches(SampleVariantIntString(1)));
+
+  m = VariantWith<std::string>(Eq("1"));
+  EXPECT_TRUE(m.Matches(SampleVariantIntString("1")));
+}
+
+TEST(VariantTest, TypeDoesNotMatch) {
+  Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
+  EXPECT_FALSE(m.Matches(SampleVariantIntString("1")));
+
+  m = VariantWith<std::string>(Eq("1"));
+  EXPECT_FALSE(m.Matches(SampleVariantIntString(1)));
+}
+
+TEST(VariantTest, InnerDoesNotMatch) {
+  Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
+  EXPECT_FALSE(m.Matches(SampleVariantIntString(2)));
+
+  m = VariantWith<std::string>(Eq("1"));
+  EXPECT_FALSE(m.Matches(SampleVariantIntString("2")));
+}
+
+class SampleAnyType {
+ public:
+  explicit SampleAnyType(int i) : index_(0), i_(i) {}
+  explicit SampleAnyType(const std::string& s) : index_(1), s_(s) {}
+
+  template <typename T>
+  friend const T* any_cast(const SampleAnyType* any) {
+    return any->get_impl(static_cast<T*>(nullptr));
+  }
+
+ private:
+  int index_;
+  int i_;
+  std::string s_;
+
+  const int* get_impl(int*) const { return index_ == 0 ? &i_ : nullptr; }
+  const std::string* get_impl(std::string*) const {
+    return index_ == 1 ? &s_ : nullptr;
+  }
+};
+
+TEST(AnyWithTest, FullMatch) {
+  Matcher<SampleAnyType> m = AnyWith<int>(Eq(1));
+  EXPECT_TRUE(m.Matches(SampleAnyType(1)));
+}
+
+TEST(AnyWithTest, TestBadCastType) {
+  Matcher<SampleAnyType> m = AnyWith<std::string>(Eq("fail"));
+  EXPECT_FALSE(m.Matches(SampleAnyType(1)));
+}
+
+TEST(AnyWithTest, TestUseInContainers) {
+  std::vector<SampleAnyType> a;
+  a.emplace_back(1);
+  a.emplace_back(2);
+  a.emplace_back(3);
+  EXPECT_THAT(
+      a, ElementsAreArray({AnyWith<int>(1), AnyWith<int>(2), AnyWith<int>(3)}));
+
+  std::vector<SampleAnyType> b;
+  b.emplace_back("hello");
+  b.emplace_back("merhaba");
+  b.emplace_back("salut");
+  EXPECT_THAT(b, ElementsAreArray({AnyWith<std::string>("hello"),
+                                   AnyWith<std::string>("merhaba"),
+                                   AnyWith<std::string>("salut")}));
+}
+TEST(AnyWithTest, TestCompare) {
+  EXPECT_THAT(SampleAnyType(1), AnyWith<int>(Gt(0)));
+}
+
+TEST(AnyWithTest, DescribesSelf) {
+  const Matcher<const SampleAnyType&> m = AnyWith<int>(Eq(1));
+  EXPECT_THAT(Describe(m), ContainsRegex("is an 'any' type with value of type "
+                                         "'.*' and the value is equal to 1"));
+}
+
+TEST(AnyWithTest, ExplainsSelf) {
+  const Matcher<const SampleAnyType&> m = AnyWith<int>(Eq(1));
+
+  EXPECT_THAT(Explain(m, SampleAnyType(1)), ContainsRegex("whose value 1"));
+  EXPECT_THAT(Explain(m, SampleAnyType("A")),
+              HasSubstr("whose value is not of type '"));
+  EXPECT_THAT(Explain(m, SampleAnyType(2)), "whose value 2 doesn't match");
+}
+
+// Tests Args<k0, ..., kn>(m).
+
+TEST(ArgsTest, AcceptsZeroTemplateArg) {
+  const std::tuple<int, bool> t(5, true);
+  EXPECT_THAT(t, Args<>(Eq(std::tuple<>())));
+  EXPECT_THAT(t, Not(Args<>(Ne(std::tuple<>()))));
+}
+
+TEST(ArgsTest, AcceptsOneTemplateArg) {
+  const std::tuple<int, bool> t(5, true);
+  EXPECT_THAT(t, Args<0>(Eq(std::make_tuple(5))));
+  EXPECT_THAT(t, Args<1>(Eq(std::make_tuple(true))));
+  EXPECT_THAT(t, Not(Args<1>(Eq(std::make_tuple(false)))));
+}
+
+TEST(ArgsTest, AcceptsTwoTemplateArgs) {
+  const std::tuple<short, int, long> t(short{4}, 5, 6L);  // NOLINT
+
+  EXPECT_THAT(t, (Args<0, 1>(Lt())));
+  EXPECT_THAT(t, (Args<1, 2>(Lt())));
+  EXPECT_THAT(t, Not(Args<0, 2>(Gt())));
+}
+
+TEST(ArgsTest, AcceptsRepeatedTemplateArgs) {
+  const std::tuple<short, int, long> t(short{4}, 5, 6L);  // NOLINT
+  EXPECT_THAT(t, (Args<0, 0>(Eq())));
+  EXPECT_THAT(t, Not(Args<1, 1>(Ne())));
+}
+
+TEST(ArgsTest, AcceptsDecreasingTemplateArgs) {
+  const std::tuple<short, int, long> t(short{4}, 5, 6L);  // NOLINT
+  EXPECT_THAT(t, (Args<2, 0>(Gt())));
+  EXPECT_THAT(t, Not(Args<2, 1>(Lt())));
+}
+
+MATCHER(SumIsZero, "") {
+  return std::get<0>(arg) + std::get<1>(arg) + std::get<2>(arg) == 0;
+}
+
+TEST(ArgsTest, AcceptsMoreTemplateArgsThanArityOfOriginalTuple) {
+  EXPECT_THAT(std::make_tuple(-1, 2), (Args<0, 0, 1>(SumIsZero())));
+  EXPECT_THAT(std::make_tuple(1, 2), Not(Args<0, 0, 1>(SumIsZero())));
+}
+
+TEST(ArgsTest, CanBeNested) {
+  const std::tuple<short, int, long, int> t(short{4}, 5, 6L, 6);  // NOLINT
+  EXPECT_THAT(t, (Args<1, 2, 3>(Args<1, 2>(Eq()))));
+  EXPECT_THAT(t, (Args<0, 1, 3>(Args<0, 2>(Lt()))));
+}
+
+TEST(ArgsTest, CanMatchTupleByValue) {
+  typedef std::tuple<char, int, int> Tuple3;
+  const Matcher<Tuple3> m = Args<1, 2>(Lt());
+  EXPECT_TRUE(m.Matches(Tuple3('a', 1, 2)));
+  EXPECT_FALSE(m.Matches(Tuple3('b', 2, 2)));
+}
+
+TEST(ArgsTest, CanMatchTupleByReference) {
+  typedef std::tuple<char, char, int> Tuple3;
+  const Matcher<const Tuple3&> m = Args<0, 1>(Lt());
+  EXPECT_TRUE(m.Matches(Tuple3('a', 'b', 2)));
+  EXPECT_FALSE(m.Matches(Tuple3('b', 'b', 2)));
+}
+
+// Validates that arg is printed as str.
+MATCHER_P(PrintsAs, str, "") { return testing::PrintToString(arg) == str; }
+
+TEST(ArgsTest, AcceptsTenTemplateArgs) {
+  EXPECT_THAT(std::make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9),
+              (Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>(
+                  PrintsAs("(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)"))));
+  EXPECT_THAT(std::make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9),
+              Not(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>(
+                  PrintsAs("(0, 8, 7, 6, 5, 4, 3, 2, 1, 0)"))));
+}
+
+TEST(ArgsTest, DescirbesSelfCorrectly) {
+  const Matcher<std::tuple<int, bool, char>> m = Args<2, 0>(Lt());
+  EXPECT_EQ(
+      "are a tuple whose fields (#2, #0) are a pair where "
+      "the first < the second",
+      Describe(m));
+}
+
+TEST(ArgsTest, DescirbesNestedArgsCorrectly) {
+  const Matcher<const std::tuple<int, bool, char, int>&> m =
+      Args<0, 2, 3>(Args<2, 0>(Lt()));
+  EXPECT_EQ(
+      "are a tuple whose fields (#0, #2, #3) are a tuple "
+      "whose fields (#2, #0) are a pair where the first < the second",
+      Describe(m));
+}
+
+TEST(ArgsTest, DescribesNegationCorrectly) {
+  const Matcher<std::tuple<int, char>> m = Args<1, 0>(Gt());
+  EXPECT_EQ(
+      "are a tuple whose fields (#1, #0) aren't a pair "
+      "where the first > the second",
+      DescribeNegation(m));
+}
+
+TEST(ArgsTest, ExplainsMatchResultWithoutInnerExplanation) {
+  const Matcher<std::tuple<bool, int, int>> m = Args<1, 2>(Eq());
+  EXPECT_EQ("whose fields (#1, #2) are (42, 42)",
+            Explain(m, std::make_tuple(false, 42, 42)));
+  EXPECT_EQ("whose fields (#1, #2) are (42, 43)",
+            Explain(m, std::make_tuple(false, 42, 43)));
+}
+
+// For testing Args<>'s explanation.
+class LessThanMatcher : public MatcherInterface<std::tuple<char, int>> {
+ public:
+  void DescribeTo(::std::ostream* /*os*/) const override {}
+
+  bool MatchAndExplain(std::tuple<char, int> value,
+                       MatchResultListener* listener) const override {
+    const int diff = std::get<0>(value) - std::get<1>(value);
+    if (diff > 0) {
+      *listener << "where the first value is " << diff
+                << " more than the second";
+    }
+    return diff < 0;
+  }
+};
+
+Matcher<std::tuple<char, int>> LessThan() {
+  return MakeMatcher(new LessThanMatcher);
+}
+
+TEST(ArgsTest, ExplainsMatchResultWithInnerExplanation) {
+  const Matcher<std::tuple<char, int, int>> m = Args<0, 2>(LessThan());
+  EXPECT_EQ(
+      "whose fields (#0, #2) are ('a' (97, 0x61), 42), "
+      "where the first value is 55 more than the second",
+      Explain(m, std::make_tuple('a', 42, 42)));
+  EXPECT_EQ("whose fields (#0, #2) are ('\\0', 43)",
+            Explain(m, std::make_tuple('\0', 42, 43)));
+}
+
+// Tests for the MATCHER*() macro family.
+
+// Tests that a simple MATCHER() definition works.
+
+MATCHER(IsEven, "") { return (arg % 2) == 0; }
+
+TEST(MatcherMacroTest, Works) {
+  const Matcher<int> m = IsEven();
+  EXPECT_TRUE(m.Matches(6));
+  EXPECT_FALSE(m.Matches(7));
+
+  EXPECT_EQ("is even", Describe(m));
+  EXPECT_EQ("not (is even)", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 6));
+  EXPECT_EQ("", Explain(m, 7));
+}
+
+// This also tests that the description string can reference 'negation'.
+MATCHER(IsEven2, negation ? "is odd" : "is even") {
+  if ((arg % 2) == 0) {
+    // Verifies that we can stream to result_listener, a listener
+    // supplied by the MATCHER macro implicitly.
+    *result_listener << "OK";
+    return true;
+  } else {
+    *result_listener << "% 2 == " << (arg % 2);
+    return false;
+  }
+}
+
+// This also tests that the description string can reference matcher
+// parameters.
+MATCHER_P2(EqSumOf, x, y,
+           std::string(negation ? "doesn't equal" : "equals") + " the sum of " +
+               PrintToString(x) + " and " + PrintToString(y)) {
+  if (arg == (x + y)) {
+    *result_listener << "OK";
+    return true;
+  } else {
+    // Verifies that we can stream to the underlying stream of
+    // result_listener.
+    if (result_listener->stream() != nullptr) {
+      *result_listener->stream() << "diff == " << (x + y - arg);
+    }
+    return false;
+  }
+}
+
+// Tests that the matcher description can reference 'negation' and the
+// matcher parameters.
+TEST(MatcherMacroTest, DescriptionCanReferenceNegationAndParameters) {
+  const Matcher<int> m1 = IsEven2();
+  EXPECT_EQ("is even", Describe(m1));
+  EXPECT_EQ("is odd", DescribeNegation(m1));
+
+  const Matcher<int> m2 = EqSumOf(5, 9);
+  EXPECT_EQ("equals the sum of 5 and 9", Describe(m2));
+  EXPECT_EQ("doesn't equal the sum of 5 and 9", DescribeNegation(m2));
+}
+
+// Tests explaining match result in a MATCHER* macro.
+TEST(MatcherMacroTest, CanExplainMatchResult) {
+  const Matcher<int> m1 = IsEven2();
+  EXPECT_EQ("OK", Explain(m1, 4));
+  EXPECT_EQ("% 2 == 1", Explain(m1, 5));
+
+  const Matcher<int> m2 = EqSumOf(1, 2);
+  EXPECT_EQ("OK", Explain(m2, 3));
+  EXPECT_EQ("diff == -1", Explain(m2, 4));
+}
+
+// Tests that the body of MATCHER() can reference the type of the
+// value being matched.
+
+MATCHER(IsEmptyString, "") {
+  StaticAssertTypeEq<::std::string, arg_type>();
+  return arg.empty();
+}
+
+MATCHER(IsEmptyStringByRef, "") {
+  StaticAssertTypeEq<const ::std::string&, arg_type>();
+  return arg.empty();
+}
+
+TEST(MatcherMacroTest, CanReferenceArgType) {
+  const Matcher<::std::string> m1 = IsEmptyString();
+  EXPECT_TRUE(m1.Matches(""));
+
+  const Matcher<const ::std::string&> m2 = IsEmptyStringByRef();
+  EXPECT_TRUE(m2.Matches(""));
+}
+
+// Tests that MATCHER() can be used in a namespace.
+
+namespace matcher_test {
+MATCHER(IsOdd, "") { return (arg % 2) != 0; }
+}  // namespace matcher_test
+
+TEST(MatcherMacroTest, WorksInNamespace) {
+  Matcher<int> m = matcher_test::IsOdd();
+  EXPECT_FALSE(m.Matches(4));
+  EXPECT_TRUE(m.Matches(5));
+}
+
+// Tests that Value() can be used to compose matchers.
+MATCHER(IsPositiveOdd, "") {
+  return Value(arg, matcher_test::IsOdd()) && arg > 0;
+}
+
+TEST(MatcherMacroTest, CanBeComposedUsingValue) {
+  EXPECT_THAT(3, IsPositiveOdd());
+  EXPECT_THAT(4, Not(IsPositiveOdd()));
+  EXPECT_THAT(-1, Not(IsPositiveOdd()));
+}
+
+// Tests that a simple MATCHER_P() definition works.
+
+MATCHER_P(IsGreaterThan32And, n, "") { return arg > 32 && arg > n; }
+
+TEST(MatcherPMacroTest, Works) {
+  const Matcher<int> m = IsGreaterThan32And(5);
+  EXPECT_TRUE(m.Matches(36));
+  EXPECT_FALSE(m.Matches(5));
+
+  EXPECT_EQ("is greater than 32 and (n: 5)", Describe(m));
+  EXPECT_EQ("not (is greater than 32 and (n: 5))", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 36));
+  EXPECT_EQ("", Explain(m, 5));
+}
+
+// Tests that the description is calculated correctly from the matcher name.
+MATCHER_P(_is_Greater_Than32and_, n, "") { return arg > 32 && arg > n; }
+
+TEST(MatcherPMacroTest, GeneratesCorrectDescription) {
+  const Matcher<int> m = _is_Greater_Than32and_(5);
+
+  EXPECT_EQ("is greater than 32 and (n: 5)", Describe(m));
+  EXPECT_EQ("not (is greater than 32 and (n: 5))", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 36));
+  EXPECT_EQ("", Explain(m, 5));
+}
+
+// Tests that a MATCHER_P matcher can be explicitly instantiated with
+// a reference parameter type.
+
+class UncopyableFoo {
+ public:
+  explicit UncopyableFoo(char value) : value_(value) { (void)value_; }
+
+  UncopyableFoo(const UncopyableFoo&) = delete;
+  void operator=(const UncopyableFoo&) = delete;
+
+ private:
+  char value_;
+};
+
+MATCHER_P(ReferencesUncopyable, variable, "") { return &arg == &variable; }
+
+TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) {
+  UncopyableFoo foo1('1'), foo2('2');
+  const Matcher<const UncopyableFoo&> m =
+      ReferencesUncopyable<const UncopyableFoo&>(foo1);
+
+  EXPECT_TRUE(m.Matches(foo1));
+  EXPECT_FALSE(m.Matches(foo2));
+
+  // We don't want the address of the parameter printed, as most
+  // likely it will just annoy the user.  If the address is
+  // interesting, the user should consider passing the parameter by
+  // pointer instead.
+  EXPECT_EQ("references uncopyable (variable: 1-byte object <31>)",
+            Describe(m));
+}
+
+// Tests that the body of MATCHER_Pn() can reference the parameter
+// types.
+
+MATCHER_P3(ParamTypesAreIntLongAndChar, foo, bar, baz, "") {
+  StaticAssertTypeEq<int, foo_type>();
+  StaticAssertTypeEq<long, bar_type>();  // NOLINT
+  StaticAssertTypeEq<char, baz_type>();
+  return arg == 0;
+}
+
+TEST(MatcherPnMacroTest, CanReferenceParamTypes) {
+  EXPECT_THAT(0, ParamTypesAreIntLongAndChar(10, 20L, 'a'));
+}
+
+// Tests that a MATCHER_Pn matcher can be explicitly instantiated with
+// reference parameter types.
+
+MATCHER_P2(ReferencesAnyOf, variable1, variable2, "") {
+  return &arg == &variable1 || &arg == &variable2;
+}
+
+TEST(MatcherPnMacroTest, WorksWhenExplicitlyInstantiatedWithReferences) {
+  UncopyableFoo foo1('1'), foo2('2'), foo3('3');
+  const Matcher<const UncopyableFoo&> const_m =
+      ReferencesAnyOf<const UncopyableFoo&, const UncopyableFoo&>(foo1, foo2);
+
+  EXPECT_TRUE(const_m.Matches(foo1));
+  EXPECT_TRUE(const_m.Matches(foo2));
+  EXPECT_FALSE(const_m.Matches(foo3));
+
+  const Matcher<UncopyableFoo&> m =
+      ReferencesAnyOf<UncopyableFoo&, UncopyableFoo&>(foo1, foo2);
+
+  EXPECT_TRUE(m.Matches(foo1));
+  EXPECT_TRUE(m.Matches(foo2));
+  EXPECT_FALSE(m.Matches(foo3));
+}
+
+TEST(MatcherPnMacroTest,
+     GeneratesCorretDescriptionWhenExplicitlyInstantiatedWithReferences) {
+  UncopyableFoo foo1('1'), foo2('2');
+  const Matcher<const UncopyableFoo&> m =
+      ReferencesAnyOf<const UncopyableFoo&, const UncopyableFoo&>(foo1, foo2);
+
+  // We don't want the addresses of the parameters printed, as most
+  // likely they will just annoy the user.  If the addresses are
+  // interesting, the user should consider passing the parameters by
+  // pointers instead.
+  EXPECT_EQ(
+      "references any of (variable1: 1-byte object <31>, variable2: 1-byte "
+      "object <32>)",
+      Describe(m));
+}
+
+// Tests that a simple MATCHER_P2() definition works.
+
+MATCHER_P2(IsNotInClosedRange, low, hi, "") { return arg < low || arg > hi; }
+
+TEST(MatcherPnMacroTest, Works) {
+  const Matcher<const long&> m = IsNotInClosedRange(10, 20);  // NOLINT
+  EXPECT_TRUE(m.Matches(36L));
+  EXPECT_FALSE(m.Matches(15L));
+
+  EXPECT_EQ("is not in closed range (low: 10, hi: 20)", Describe(m));
+  EXPECT_EQ("not (is not in closed range (low: 10, hi: 20))",
+            DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 36L));
+  EXPECT_EQ("", Explain(m, 15L));
+}
+
+// Tests that MATCHER*() definitions can be overloaded on the number
+// of parameters; also tests MATCHER_Pn() where n >= 3.
+
+MATCHER(EqualsSumOf, "") { return arg == 0; }
+MATCHER_P(EqualsSumOf, a, "") { return arg == a; }
+MATCHER_P2(EqualsSumOf, a, b, "") { return arg == a + b; }
+MATCHER_P3(EqualsSumOf, a, b, c, "") { return arg == a + b + c; }
+MATCHER_P4(EqualsSumOf, a, b, c, d, "") { return arg == a + b + c + d; }
+MATCHER_P5(EqualsSumOf, a, b, c, d, e, "") { return arg == a + b + c + d + e; }
+MATCHER_P6(EqualsSumOf, a, b, c, d, e, f, "") {
+  return arg == a + b + c + d + e + f;
+}
+MATCHER_P7(EqualsSumOf, a, b, c, d, e, f, g, "") {
+  return arg == a + b + c + d + e + f + g;
+}
+MATCHER_P8(EqualsSumOf, a, b, c, d, e, f, g, h, "") {
+  return arg == a + b + c + d + e + f + g + h;
+}
+MATCHER_P9(EqualsSumOf, a, b, c, d, e, f, g, h, i, "") {
+  return arg == a + b + c + d + e + f + g + h + i;
+}
+MATCHER_P10(EqualsSumOf, a, b, c, d, e, f, g, h, i, j, "") {
+  return arg == a + b + c + d + e + f + g + h + i + j;
+}
+
+TEST(MatcherPnMacroTest, CanBeOverloadedOnNumberOfParameters) {
+  EXPECT_THAT(0, EqualsSumOf());
+  EXPECT_THAT(1, EqualsSumOf(1));
+  EXPECT_THAT(12, EqualsSumOf(10, 2));
+  EXPECT_THAT(123, EqualsSumOf(100, 20, 3));
+  EXPECT_THAT(1234, EqualsSumOf(1000, 200, 30, 4));
+  EXPECT_THAT(12345, EqualsSumOf(10000, 2000, 300, 40, 5));
+  EXPECT_THAT("abcdef",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f'));
+  EXPECT_THAT("abcdefg",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g'));
+  EXPECT_THAT("abcdefgh", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e",
+                                      'f', 'g', "h"));
+  EXPECT_THAT("abcdefghi", EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e",
+                                       'f', 'g', "h", 'i'));
+  EXPECT_THAT("abcdefghij",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g', "h",
+                          'i', ::std::string("j")));
+
+  EXPECT_THAT(1, Not(EqualsSumOf()));
+  EXPECT_THAT(-1, Not(EqualsSumOf(1)));
+  EXPECT_THAT(-12, Not(EqualsSumOf(10, 2)));
+  EXPECT_THAT(-123, Not(EqualsSumOf(100, 20, 3)));
+  EXPECT_THAT(-1234, Not(EqualsSumOf(1000, 200, 30, 4)));
+  EXPECT_THAT(-12345, Not(EqualsSumOf(10000, 2000, 300, 40, 5)));
+  EXPECT_THAT("abcdef ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f')));
+  EXPECT_THAT("abcdefg ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d",
+                                          "e", 'f', 'g')));
+  EXPECT_THAT("abcdefgh ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d",
+                                           "e", 'f', 'g', "h")));
+  EXPECT_THAT("abcdefghi ", Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d",
+                                            "e", 'f', 'g', "h", 'i')));
+  EXPECT_THAT("abcdefghij ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                              "h", 'i', ::std::string("j"))));
+}
+
+// Tests that a MATCHER_Pn() definition can be instantiated with any
+// compatible parameter types.
+TEST(MatcherPnMacroTest, WorksForDifferentParameterTypes) {
+  EXPECT_THAT(123, EqualsSumOf(100L, 20, static_cast<char>(3)));
+  EXPECT_THAT("abcd", EqualsSumOf(::std::string("a"), "b", 'c', "d"));
+
+  EXPECT_THAT(124, Not(EqualsSumOf(100L, 20, static_cast<char>(3))));
+  EXPECT_THAT("abcde", Not(EqualsSumOf(::std::string("a"), "b", 'c', "d")));
+}
+
+// Tests that the matcher body can promote the parameter types.
+
+MATCHER_P2(EqConcat, prefix, suffix, "") {
+  // The following lines promote the two parameters to desired types.
+  std::string prefix_str(prefix);
+  char suffix_char = static_cast<char>(suffix);
+  return arg == prefix_str + suffix_char;
+}
+
+TEST(MatcherPnMacroTest, SimpleTypePromotion) {
+  Matcher<std::string> no_promo = EqConcat(std::string("foo"), 't');
+  Matcher<const std::string&> promo = EqConcat("foo", static_cast<int>('t'));
+  EXPECT_FALSE(no_promo.Matches("fool"));
+  EXPECT_FALSE(promo.Matches("fool"));
+  EXPECT_TRUE(no_promo.Matches("foot"));
+  EXPECT_TRUE(promo.Matches("foot"));
+}
+
+// Verifies the type of a MATCHER*.
+
+TEST(MatcherPnMacroTest, TypesAreCorrect) {
+  // EqualsSumOf() must be assignable to a EqualsSumOfMatcher variable.
+  EqualsSumOfMatcher a0 = EqualsSumOf();
+
+  // EqualsSumOf(1) must be assignable to a EqualsSumOfMatcherP variable.
+  EqualsSumOfMatcherP<int> a1 = EqualsSumOf(1);
+
+  // EqualsSumOf(p1, ..., pk) must be assignable to a EqualsSumOfMatcherPk
+  // variable, and so on.
+  EqualsSumOfMatcherP2<int, char> a2 = EqualsSumOf(1, '2');
+  EqualsSumOfMatcherP3<int, int, char> a3 = EqualsSumOf(1, 2, '3');
+  EqualsSumOfMatcherP4<int, int, int, char> a4 = EqualsSumOf(1, 2, 3, '4');
+  EqualsSumOfMatcherP5<int, int, int, int, char> a5 =
+      EqualsSumOf(1, 2, 3, 4, '5');
+  EqualsSumOfMatcherP6<int, int, int, int, int, char> a6 =
+      EqualsSumOf(1, 2, 3, 4, 5, '6');
+  EqualsSumOfMatcherP7<int, int, int, int, int, int, char> a7 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, '7');
+  EqualsSumOfMatcherP8<int, int, int, int, int, int, int, char> a8 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, 7, '8');
+  EqualsSumOfMatcherP9<int, int, int, int, int, int, int, int, char> a9 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, '9');
+  EqualsSumOfMatcherP10<int, int, int, int, int, int, int, int, int, char> a10 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, 9, '0');
+
+  // Avoid "unused variable" warnings.
+  (void)a0;
+  (void)a1;
+  (void)a2;
+  (void)a3;
+  (void)a4;
+  (void)a5;
+  (void)a6;
+  (void)a7;
+  (void)a8;
+  (void)a9;
+  (void)a10;
+}
+
+// Tests that matcher-typed parameters can be used in Value() inside a
+// MATCHER_Pn definition.
+
+// Succeeds if arg matches exactly 2 of the 3 matchers.
+MATCHER_P3(TwoOf, m1, m2, m3, "") {
+  const int count = static_cast<int>(Value(arg, m1)) +
+                    static_cast<int>(Value(arg, m2)) +
+                    static_cast<int>(Value(arg, m3));
+  return count == 2;
+}
+
+TEST(MatcherPnMacroTest, CanUseMatcherTypedParameterInValue) {
+  EXPECT_THAT(42, TwoOf(Gt(0), Lt(50), Eq(10)));
+  EXPECT_THAT(0, Not(TwoOf(Gt(-1), Lt(1), Eq(0))));
+}
+
+// Tests Contains().Times().
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(ContainsTimes);
+
+TEST(ContainsTimes, ListMatchesWhenElementQuantityMatches) {
+  list<int> some_list;
+  some_list.push_back(3);
+  some_list.push_back(1);
+  some_list.push_back(2);
+  some_list.push_back(3);
+  EXPECT_THAT(some_list, Contains(3).Times(2));
+  EXPECT_THAT(some_list, Contains(2).Times(1));
+  EXPECT_THAT(some_list, Contains(Ge(2)).Times(3));
+  EXPECT_THAT(some_list, Contains(Ge(2)).Times(Gt(2)));
+  EXPECT_THAT(some_list, Contains(4).Times(0));
+  EXPECT_THAT(some_list, Contains(_).Times(4));
+  EXPECT_THAT(some_list, Not(Contains(5).Times(1)));
+  EXPECT_THAT(some_list, Contains(5).Times(_));  // Times(_) always matches
+  EXPECT_THAT(some_list, Not(Contains(3).Times(1)));
+  EXPECT_THAT(some_list, Contains(3).Times(Not(1)));
+  EXPECT_THAT(list<int>{}, Not(Contains(_)));
+}
+
+TEST_P(ContainsTimesP, ExplainsMatchResultCorrectly) {
+  const int a[2] = {1, 2};
+  Matcher<const int(&)[2]> m = Contains(2).Times(3);
+  EXPECT_EQ(
+      "whose element #1 matches but whose match quantity of 1 does not match",
+      Explain(m, a));
+
+  m = Contains(3).Times(0);
+  EXPECT_EQ("has no element that matches and whose match quantity of 0 matches",
+            Explain(m, a));
+
+  m = Contains(3).Times(4);
+  EXPECT_EQ(
+      "has no element that matches and whose match quantity of 0 does not "
+      "match",
+      Explain(m, a));
+
+  m = Contains(2).Times(4);
+  EXPECT_EQ(
+      "whose element #1 matches but whose match quantity of 1 does not "
+      "match",
+      Explain(m, a));
+
+  m = Contains(GreaterThan(0)).Times(2);
+  EXPECT_EQ("whose elements (0, 1) match and whose match quantity of 2 matches",
+            Explain(m, a));
+
+  m = Contains(GreaterThan(10)).Times(Gt(1));
+  EXPECT_EQ(
+      "has no element that matches and whose match quantity of 0 does not "
+      "match",
+      Explain(m, a));
+
+  m = Contains(GreaterThan(0)).Times(GreaterThan<size_t>(5));
+  EXPECT_EQ(
+      "whose elements (0, 1) match but whose match quantity of 2 does not "
+      "match, which is 3 less than 5",
+      Explain(m, a));
+}
+
+TEST(ContainsTimes, DescribesItselfCorrectly) {
+  Matcher<vector<int>> m = Contains(1).Times(2);
+  EXPECT_EQ("quantity of elements that match is equal to 1 is equal to 2",
+            Describe(m));
+
+  Matcher<vector<int>> m2 = Not(m);
+  EXPECT_EQ("quantity of elements that match is equal to 1 isn't equal to 2",
+            Describe(m2));
+}
+
+// Tests AllOfArray()
+
+TEST(AllOfArrayTest, BasicForms) {
+  // Iterator
+  std::vector<int> v0{};
+  std::vector<int> v1{1};
+  std::vector<int> v2{2, 3};
+  std::vector<int> v3{4, 4, 4};
+  EXPECT_THAT(0, AllOfArray(v0.begin(), v0.end()));
+  EXPECT_THAT(1, AllOfArray(v1.begin(), v1.end()));
+  EXPECT_THAT(2, Not(AllOfArray(v1.begin(), v1.end())));
+  EXPECT_THAT(3, Not(AllOfArray(v2.begin(), v2.end())));
+  EXPECT_THAT(4, AllOfArray(v3.begin(), v3.end()));
+  // Pointer +  size
+  int ar[6] = {1, 2, 3, 4, 4, 4};
+  EXPECT_THAT(0, AllOfArray(ar, 0));
+  EXPECT_THAT(1, AllOfArray(ar, 1));
+  EXPECT_THAT(2, Not(AllOfArray(ar, 1)));
+  EXPECT_THAT(3, Not(AllOfArray(ar + 1, 3)));
+  EXPECT_THAT(4, AllOfArray(ar + 3, 3));
+  // Array
+  // int ar0[0];  Not usable
+  int ar1[1] = {1};
+  int ar2[2] = {2, 3};
+  int ar3[3] = {4, 4, 4};
+  // EXPECT_THAT(0, Not(AllOfArray(ar0)));  // Cannot work
+  EXPECT_THAT(1, AllOfArray(ar1));
+  EXPECT_THAT(2, Not(AllOfArray(ar1)));
+  EXPECT_THAT(3, Not(AllOfArray(ar2)));
+  EXPECT_THAT(4, AllOfArray(ar3));
+  // Container
+  EXPECT_THAT(0, AllOfArray(v0));
+  EXPECT_THAT(1, AllOfArray(v1));
+  EXPECT_THAT(2, Not(AllOfArray(v1)));
+  EXPECT_THAT(3, Not(AllOfArray(v2)));
+  EXPECT_THAT(4, AllOfArray(v3));
+  // Initializer
+  EXPECT_THAT(0, AllOfArray<int>({}));  // Requires template arg.
+  EXPECT_THAT(1, AllOfArray({1}));
+  EXPECT_THAT(2, Not(AllOfArray({1})));
+  EXPECT_THAT(3, Not(AllOfArray({2, 3})));
+  EXPECT_THAT(4, AllOfArray({4, 4, 4}));
+}
+
+TEST(AllOfArrayTest, Matchers) {
+  // vector
+  std::vector<Matcher<int>> matchers{Ge(1), Lt(2)};
+  EXPECT_THAT(0, Not(AllOfArray(matchers)));
+  EXPECT_THAT(1, AllOfArray(matchers));
+  EXPECT_THAT(2, Not(AllOfArray(matchers)));
+  // initializer_list
+  EXPECT_THAT(0, Not(AllOfArray({Ge(0), Ge(1)})));
+  EXPECT_THAT(1, AllOfArray({Ge(0), Ge(1)}));
+}
+
+INSTANTIATE_GTEST_MATCHER_TEST_P(AnyOfArrayTest);
+
+TEST(AnyOfArrayTest, BasicForms) {
+  // Iterator
+  std::vector<int> v0{};
+  std::vector<int> v1{1};
+  std::vector<int> v2{2, 3};
+  EXPECT_THAT(0, Not(AnyOfArray(v0.begin(), v0.end())));
+  EXPECT_THAT(1, AnyOfArray(v1.begin(), v1.end()));
+  EXPECT_THAT(2, Not(AnyOfArray(v1.begin(), v1.end())));
+  EXPECT_THAT(3, AnyOfArray(v2.begin(), v2.end()));
+  EXPECT_THAT(4, Not(AnyOfArray(v2.begin(), v2.end())));
+  // Pointer +  size
+  int ar[3] = {1, 2, 3};
+  EXPECT_THAT(0, Not(AnyOfArray(ar, 0)));
+  EXPECT_THAT(1, AnyOfArray(ar, 1));
+  EXPECT_THAT(2, Not(AnyOfArray(ar, 1)));
+  EXPECT_THAT(3, AnyOfArray(ar + 1, 2));
+  EXPECT_THAT(4, Not(AnyOfArray(ar + 1, 2)));
+  // Array
+  // int ar0[0];  Not usable
+  int ar1[1] = {1};
+  int ar2[2] = {2, 3};
+  // EXPECT_THAT(0, Not(AnyOfArray(ar0)));  // Cannot work
+  EXPECT_THAT(1, AnyOfArray(ar1));
+  EXPECT_THAT(2, Not(AnyOfArray(ar1)));
+  EXPECT_THAT(3, AnyOfArray(ar2));
+  EXPECT_THAT(4, Not(AnyOfArray(ar2)));
+  // Container
+  EXPECT_THAT(0, Not(AnyOfArray(v0)));
+  EXPECT_THAT(1, AnyOfArray(v1));
+  EXPECT_THAT(2, Not(AnyOfArray(v1)));
+  EXPECT_THAT(3, AnyOfArray(v2));
+  EXPECT_THAT(4, Not(AnyOfArray(v2)));
+  // Initializer
+  EXPECT_THAT(0, Not(AnyOfArray<int>({})));  // Requires template arg.
+  EXPECT_THAT(1, AnyOfArray({1}));
+  EXPECT_THAT(2, Not(AnyOfArray({1})));
+  EXPECT_THAT(3, AnyOfArray({2, 3}));
+  EXPECT_THAT(4, Not(AnyOfArray({2, 3})));
+}
+
+TEST(AnyOfArrayTest, Matchers) {
+  // We negate test AllOfArrayTest.Matchers.
+  // vector
+  std::vector<Matcher<int>> matchers{Lt(1), Ge(2)};
+  EXPECT_THAT(0, AnyOfArray(matchers));
+  EXPECT_THAT(1, Not(AnyOfArray(matchers)));
+  EXPECT_THAT(2, AnyOfArray(matchers));
+  // initializer_list
+  EXPECT_THAT(0, AnyOfArray({Lt(0), Lt(1)}));
+  EXPECT_THAT(1, Not(AllOfArray({Lt(0), Lt(1)})));
+}
+
+TEST_P(AnyOfArrayTestP, ExplainsMatchResultCorrectly) {
+  // AnyOfArray and AllOfArray use the same underlying template-template,
+  // thus it is sufficient to test one here.
+  const std::vector<int> v0{};
+  const std::vector<int> v1{1};
+  const std::vector<int> v2{2, 3};
+  const Matcher<int> m0 = AnyOfArray(v0);
+  const Matcher<int> m1 = AnyOfArray(v1);
+  const Matcher<int> m2 = AnyOfArray(v2);
+  EXPECT_EQ("", Explain(m0, 0));
+  EXPECT_EQ("", Explain(m1, 1));
+  EXPECT_EQ("", Explain(m1, 2));
+  EXPECT_EQ("", Explain(m2, 3));
+  EXPECT_EQ("", Explain(m2, 4));
+  EXPECT_EQ("()", Describe(m0));
+  EXPECT_EQ("(is equal to 1)", Describe(m1));
+  EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2));
+  EXPECT_EQ("()", DescribeNegation(m0));
+  EXPECT_EQ("(isn't equal to 1)", DescribeNegation(m1));
+  EXPECT_EQ("(isn't equal to 2) and (isn't equal to 3)", DescribeNegation(m2));
+  // Explain with matchers
+  const Matcher<int> g1 = AnyOfArray({GreaterThan(1)});
+  const Matcher<int> g2 = AnyOfArray({GreaterThan(1), GreaterThan(2)});
+  // Explains the first positive match and all prior negative matches...
+  EXPECT_EQ("which is 1 less than 1", Explain(g1, 0));
+  EXPECT_EQ("which is the same as 1", Explain(g1, 1));
+  EXPECT_EQ("which is 1 more than 1", Explain(g1, 2));
+  EXPECT_EQ("which is 1 less than 1, and which is 2 less than 2",
+            Explain(g2, 0));
+  EXPECT_EQ("which is the same as 1, and which is 1 less than 2",
+            Explain(g2, 1));
+  EXPECT_EQ("which is 1 more than 1",  // Only the first
+            Explain(g2, 2));
+}
+
+MATCHER(IsNotNull, "") { return arg != nullptr; }
+
+// Verifies that a matcher defined using MATCHER() can work on
+// move-only types.
+TEST(MatcherMacroTest, WorksOnMoveOnlyType) {
+  std::unique_ptr<int> p(new int(3));
+  EXPECT_THAT(p, IsNotNull());
+  EXPECT_THAT(std::unique_ptr<int>(), Not(IsNotNull()));
+}
+
+MATCHER_P(UniquePointee, pointee, "") { return *arg == pointee; }
+
+// Verifies that a matcher defined using MATCHER_P*() can work on
+// move-only types.
+TEST(MatcherPMacroTest, WorksOnMoveOnlyType) {
+  std::unique_ptr<int> p(new int(3));
+  EXPECT_THAT(p, UniquePointee(3));
+  EXPECT_THAT(p, Not(UniquePointee(2)));
+}
+
+MATCHER(EnsureNoUnusedButMarkedUnusedWarning, "") { return (arg % 2) == 0; }
+
+TEST(MockMethodMockFunctionTest, EnsureNoUnusedButMarkedUnusedWarning) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wused-but-marked-unused"
+#endif
+  // https://github.com/google/googletest/issues/4055
+  EXPECT_THAT(0, EnsureNoUnusedButMarkedUnusedWarning());
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// std::function<void()> is used below for compatibility with older copies of
+// GCC. Normally, a raw lambda is all that is needed.
+
+// Test that examples from documentation compile
+TEST(ThrowsTest, Examples) {
+  EXPECT_THAT(
+      std::function<void()>([]() { throw std::runtime_error("message"); }),
+      Throws<std::runtime_error>());
+
+  EXPECT_THAT(
+      std::function<void()>([]() { throw std::runtime_error("message"); }),
+      ThrowsMessage<std::runtime_error>(HasSubstr("message")));
+}
+
+TEST(ThrowsTest, PrintsExceptionWhat) {
+  EXPECT_THAT(
+      std::function<void()>([]() { throw std::runtime_error("ABC123XYZ"); }),
+      ThrowsMessage<std::runtime_error>(HasSubstr("ABC123XYZ")));
+}
+
+TEST(ThrowsTest, DoesNotGenerateDuplicateCatchClauseWarning) {
+  EXPECT_THAT(std::function<void()>([]() { throw std::exception(); }),
+              Throws<std::exception>());
+}
+
+TEST(ThrowsTest, CallableExecutedExactlyOnce) {
+  size_t a = 0;
+
+  EXPECT_THAT(std::function<void()>([&a]() {
+                a++;
+                throw 10;
+              }),
+              Throws<int>());
+  EXPECT_EQ(a, 1u);
+
+  EXPECT_THAT(std::function<void()>([&a]() {
+                a++;
+                throw std::runtime_error("message");
+              }),
+              Throws<std::runtime_error>());
+  EXPECT_EQ(a, 2u);
+
+  EXPECT_THAT(std::function<void()>([&a]() {
+                a++;
+                throw std::runtime_error("message");
+              }),
+              ThrowsMessage<std::runtime_error>(HasSubstr("message")));
+  EXPECT_EQ(a, 3u);
+
+  EXPECT_THAT(std::function<void()>([&a]() {
+                a++;
+                throw std::runtime_error("message");
+              }),
+              Throws<std::runtime_error>(
+                  Property(&std::runtime_error::what, HasSubstr("message"))));
+  EXPECT_EQ(a, 4u);
+}
+
+TEST(ThrowsTest, Describe) {
+  Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
+  std::stringstream ss;
+  matcher.DescribeTo(&ss);
+  auto explanation = ss.str();
+  EXPECT_THAT(explanation, HasSubstr("std::runtime_error"));
+}
+
+TEST(ThrowsTest, Success) {
+  Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
+  StringMatchResultListener listener;
+  EXPECT_TRUE(matcher.MatchAndExplain(
+      []() { throw std::runtime_error("error message"); }, &listener));
+  EXPECT_THAT(listener.str(), HasSubstr("std::runtime_error"));
+}
+
+TEST(ThrowsTest, FailWrongType) {
+  Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
+  StringMatchResultListener listener;
+  EXPECT_FALSE(matcher.MatchAndExplain(
+      []() { throw std::logic_error("error message"); }, &listener));
+  EXPECT_THAT(listener.str(), HasSubstr("std::logic_error"));
+  EXPECT_THAT(listener.str(), HasSubstr("\"error message\""));
+}
+
+TEST(ThrowsTest, FailWrongTypeNonStd) {
+  Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
+  StringMatchResultListener listener;
+  EXPECT_FALSE(matcher.MatchAndExplain([]() { throw 10; }, &listener));
+  EXPECT_THAT(listener.str(),
+              HasSubstr("throws an exception of an unknown type"));
+}
+
+TEST(ThrowsTest, FailNoThrow) {
+  Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
+  StringMatchResultListener listener;
+  EXPECT_FALSE(matcher.MatchAndExplain([]() { (void)0; }, &listener));
+  EXPECT_THAT(listener.str(), HasSubstr("does not throw any exception"));
+}
+
+class ThrowsPredicateTest
+    : public TestWithParam<Matcher<std::function<void()>>> {};
+
+TEST_P(ThrowsPredicateTest, Describe) {
+  Matcher<std::function<void()>> matcher = GetParam();
+  std::stringstream ss;
+  matcher.DescribeTo(&ss);
+  auto explanation = ss.str();
+  EXPECT_THAT(explanation, HasSubstr("std::runtime_error"));
+  EXPECT_THAT(explanation, HasSubstr("error message"));
+}
+
+TEST_P(ThrowsPredicateTest, Success) {
+  Matcher<std::function<void()>> matcher = GetParam();
+  StringMatchResultListener listener;
+  EXPECT_TRUE(matcher.MatchAndExplain(
+      []() { throw std::runtime_error("error message"); }, &listener));
+  EXPECT_THAT(listener.str(), HasSubstr("std::runtime_error"));
+}
+
+TEST_P(ThrowsPredicateTest, FailWrongType) {
+  Matcher<std::function<void()>> matcher = GetParam();
+  StringMatchResultListener listener;
+  EXPECT_FALSE(matcher.MatchAndExplain(
+      []() { throw std::logic_error("error message"); }, &listener));
+  EXPECT_THAT(listener.str(), HasSubstr("std::logic_error"));
+  EXPECT_THAT(listener.str(), HasSubstr("\"error message\""));
+}
+
+TEST_P(ThrowsPredicateTest, FailWrongTypeNonStd) {
+  Matcher<std::function<void()>> matcher = GetParam();
+  StringMatchResultListener listener;
+  EXPECT_FALSE(matcher.MatchAndExplain([]() { throw 10; }, &listener));
+  EXPECT_THAT(listener.str(),
+              HasSubstr("throws an exception of an unknown type"));
+}
+
+TEST_P(ThrowsPredicateTest, FailNoThrow) {
+  Matcher<std::function<void()>> matcher = GetParam();
+  StringMatchResultListener listener;
+  EXPECT_FALSE(matcher.MatchAndExplain([]() {}, &listener));
+  EXPECT_THAT(listener.str(), HasSubstr("does not throw any exception"));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    AllMessagePredicates, ThrowsPredicateTest,
+    Values(Matcher<std::function<void()>>(
+        ThrowsMessage<std::runtime_error>(HasSubstr("error message")))));
+
+// Tests that Throws<E1>(Matcher<E2>{}) compiles even when E2 != const E1&.
+TEST(ThrowsPredicateCompilesTest, ExceptionMatcherAcceptsBroadType) {
+  {
+    Matcher<std::function<void()>> matcher =
+        ThrowsMessage<std::runtime_error>(HasSubstr("error message"));
+    EXPECT_TRUE(
+        matcher.Matches([]() { throw std::runtime_error("error message"); }));
+    EXPECT_FALSE(
+        matcher.Matches([]() { throw std::runtime_error("wrong message"); }));
+  }
+
+  {
+    Matcher<uint64_t> inner = Eq(10);
+    Matcher<std::function<void()>> matcher = Throws<uint32_t>(inner);
+    EXPECT_TRUE(matcher.Matches([]() { throw (uint32_t)10; }));
+    EXPECT_FALSE(matcher.Matches([]() { throw (uint32_t)11; }));
+  }
+}
+
+// Tests that ThrowsMessage("message") is equivalent
+// to ThrowsMessage(Eq<std::string>("message")).
+TEST(ThrowsPredicateCompilesTest, MessageMatcherAcceptsNonMatcher) {
+  Matcher<std::function<void()>> matcher =
+      ThrowsMessage<std::runtime_error>("error message");
+  EXPECT_TRUE(
+      matcher.Matches([]() { throw std::runtime_error("error message"); }));
+  EXPECT_FALSE(matcher.Matches(
+      []() { throw std::runtime_error("wrong error message"); }));
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+}  // namespace
+}  // namespace gmock_matchers_test
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4244 4100
diff --git a/3rd-party/googletest/googlemock/test/gmock-matchers_test.h b/3rd-party/googletest/googlemock/test/gmock-matchers_test.h
new file mode 100644
index 0000000..5695607
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-matchers_test.h
@@ -0,0 +1,192 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests some commonly used argument matchers.
+
+#ifndef GOOGLEMOCK_TEST_GMOCK_MATCHERS_TEST_H_
+#define GOOGLEMOCK_TEST_GMOCK_MATCHERS_TEST_H_
+
+#include <string.h>
+#include <time.h>
+
+#include <array>
+#include <cstdint>
+#include <deque>
+#include <forward_list>
+#include <functional>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-more-matchers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace gmock_matchers_test {
+
+using std::greater;
+using std::less;
+using std::list;
+using std::make_pair;
+using std::map;
+using std::multimap;
+using std::multiset;
+using std::ostream;
+using std::pair;
+using std::set;
+using std::stringstream;
+using std::vector;
+using testing::internal::DummyMatchResultListener;
+using testing::internal::ElementMatcherPair;
+using testing::internal::ElementMatcherPairs;
+using testing::internal::ElementsAreArrayMatcher;
+using testing::internal::ExplainMatchFailureTupleTo;
+using testing::internal::FloatingEqMatcher;
+using testing::internal::FormatMatcherDescription;
+using testing::internal::IsReadableTypeName;
+using testing::internal::MatchMatrix;
+using testing::internal::PredicateFormatterFromMatcher;
+using testing::internal::RE;
+using testing::internal::StreamMatchResultListener;
+using testing::internal::Strings;
+
+// Helper for testing container-valued matchers in mock method context. It is
+// important to test matchers in this context, since it requires additional type
+// deduction beyond what EXPECT_THAT does, thus making it more restrictive.
+struct ContainerHelper {
+  MOCK_METHOD1(Call, void(std::vector<std::unique_ptr<int>>));
+};
+
+// For testing ExplainMatchResultTo().
+template <typename T>
+struct GtestGreaterThanMatcher {
+  using is_gtest_matcher = void;
+
+  void DescribeTo(ostream* os) const { *os << "is > " << rhs; }
+  void DescribeNegationTo(ostream* os) const { *os << "is <= " << rhs; }
+
+  bool MatchAndExplain(T lhs, MatchResultListener* listener) const {
+    if (lhs > rhs) {
+      *listener << "which is " << (lhs - rhs) << " more than " << rhs;
+    } else if (lhs == rhs) {
+      *listener << "which is the same as " << rhs;
+    } else {
+      *listener << "which is " << (rhs - lhs) << " less than " << rhs;
+    }
+
+    return lhs > rhs;
+  }
+
+  T rhs;
+};
+
+template <typename T>
+GtestGreaterThanMatcher<typename std::decay<T>::type> GtestGreaterThan(
+    T&& rhs) {
+  return {rhs};
+}
+
+// As the matcher above, but using the base class with virtual functions.
+template <typename T>
+class GreaterThanMatcher : public MatcherInterface<T> {
+ public:
+  explicit GreaterThanMatcher(T rhs) : impl_{rhs} {}
+
+  void DescribeTo(ostream* os) const override { impl_.DescribeTo(os); }
+  void DescribeNegationTo(ostream* os) const override {
+    impl_.DescribeNegationTo(os);
+  }
+
+  bool MatchAndExplain(T lhs, MatchResultListener* listener) const override {
+    return impl_.MatchAndExplain(lhs, listener);
+  }
+
+ private:
+  const GtestGreaterThanMatcher<T> impl_;
+};
+
+// Names and instantiates a new instance of GTestMatcherTestP.
+#define INSTANTIATE_GTEST_MATCHER_TEST_P(TestSuite)                        \
+  using TestSuite##P = GTestMatcherTestP;                                  \
+  INSTANTIATE_TEST_SUITE_P(MatcherInterface, TestSuite##P, Values(false)); \
+  INSTANTIATE_TEST_SUITE_P(GtestMatcher, TestSuite##P, Values(true))
+
+class GTestMatcherTestP : public testing::TestWithParam<bool> {
+ public:
+  template <typename T>
+  Matcher<T> GreaterThan(T n) {
+    if (use_gtest_matcher_) {
+      return GtestGreaterThan(n);
+    } else {
+      return MakeMatcher(new GreaterThanMatcher<T>(n));
+    }
+  }
+  const bool use_gtest_matcher_ = GetParam();
+};
+
+// Returns the description of the given matcher.
+template <typename T>
+std::string Describe(const Matcher<T>& m) {
+  return DescribeMatcher<T>(m);
+}
+
+// Returns the description of the negation of the given matcher.
+template <typename T>
+std::string DescribeNegation(const Matcher<T>& m) {
+  return DescribeMatcher<T>(m, true);
+}
+
+// Returns the reason why x matches, or doesn't match, m.
+template <typename MatcherType, typename Value>
+std::string Explain(const MatcherType& m, const Value& x) {
+  StringMatchResultListener listener;
+  ExplainMatchResult(m, x, &listener);
+  return listener.str();
+}
+
+}  // namespace gmock_matchers_test
+}  // namespace testing
+
+#endif  // GOOGLEMOCK_TEST_GMOCK_MATCHERS_TEST_H_
diff --git a/3rd-party/googletest/googlemock/test/gmock-more-actions_test.cc b/3rd-party/googletest/googlemock/test/gmock-more-actions_test.cc
new file mode 100644
index 0000000..354a79b
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-more-actions_test.cc
@@ -0,0 +1,1588 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in actions in gmock-actions.h.
+
+#include "gmock/gmock-more-actions.h"
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4577)
+
+namespace testing {
+namespace gmock_more_actions_test {
+
+using ::std::plus;
+using ::std::string;
+using testing::Action;
+using testing::DeleteArg;
+using testing::Invoke;
+using testing::ReturnArg;
+using testing::ReturnPointee;
+using testing::SaveArg;
+using testing::SaveArgPointee;
+using testing::SetArgReferee;
+using testing::Unused;
+using testing::WithArg;
+using testing::WithoutArgs;
+
+// For suppressing compiler warnings on conversion possibly losing precision.
+inline short Short(short n) { return n; }  // NOLINT
+inline char Char(char ch) { return ch; }
+
+// Sample functions and functors for testing Invoke() and etc.
+int Nullary() { return 1; }
+
+bool g_done = false;
+
+bool Unary(int x) { return x < 0; }
+
+bool ByConstRef(const std::string& s) { return s == "Hi"; }
+
+const double g_double = 0;
+bool ReferencesGlobalDouble(const double& x) { return &x == &g_double; }
+
+struct UnaryFunctor {
+  int operator()(bool x) { return x ? 1 : -1; }
+};
+
+struct UnaryMoveOnlyFunctor : UnaryFunctor {
+  UnaryMoveOnlyFunctor() = default;
+  UnaryMoveOnlyFunctor(const UnaryMoveOnlyFunctor&) = delete;
+  UnaryMoveOnlyFunctor(UnaryMoveOnlyFunctor&&) = default;
+};
+
+struct OneShotUnaryFunctor {
+  int operator()(bool x) && { return x ? 1 : -1; }
+};
+
+const char* Binary(const char* input, short n) { return input + n; }  // NOLINT
+
+int Ternary(int x, char y, short z) { return x + y + z; }  // NOLINT
+
+int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
+
+int SumOfFirst2(int a, int b, Unused, Unused) { return a + b; }
+
+int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
+
+struct SumOf5Functor {
+  int operator()(int a, int b, int c, int d, int e) {
+    return a + b + c + d + e;
+  }
+};
+
+int SumOf6(int a, int b, int c, int d, int e, int f) {
+  return a + b + c + d + e + f;
+}
+
+struct SumOf6Functor {
+  int operator()(int a, int b, int c, int d, int e, int f) {
+    return a + b + c + d + e + f;
+  }
+};
+
+std::string Concat7(const char* s1, const char* s2, const char* s3,
+                    const char* s4, const char* s5, const char* s6,
+                    const char* s7) {
+  return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
+}
+
+std::string Concat8(const char* s1, const char* s2, const char* s3,
+                    const char* s4, const char* s5, const char* s6,
+                    const char* s7, const char* s8) {
+  return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
+}
+
+std::string Concat9(const char* s1, const char* s2, const char* s3,
+                    const char* s4, const char* s5, const char* s6,
+                    const char* s7, const char* s8, const char* s9) {
+  return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
+}
+
+std::string Concat10(const char* s1, const char* s2, const char* s3,
+                     const char* s4, const char* s5, const char* s6,
+                     const char* s7, const char* s8, const char* s9,
+                     const char* s10) {
+  return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
+}
+
+class Foo {
+ public:
+  Foo() : value_(123) {}
+
+  int Nullary() const { return value_; }
+
+  short Unary(long x) { return static_cast<short>(value_ + x); }  // NOLINT
+
+  std::string Binary(const std::string& str, char c) const { return str + c; }
+
+  int Ternary(int x, bool y, char z) { return value_ + x + y * z; }
+
+  int SumOf4(int a, int b, int c, int d) const {
+    return a + b + c + d + value_;
+  }
+
+  int SumOfLast2(Unused, Unused, int a, int b) const { return a + b; }
+
+  int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
+
+  int SumOf6(int a, int b, int c, int d, int e, int f) {
+    return a + b + c + d + e + f;
+  }
+
+  std::string Concat7(const char* s1, const char* s2, const char* s3,
+                      const char* s4, const char* s5, const char* s6,
+                      const char* s7) {
+    return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
+  }
+
+  std::string Concat8(const char* s1, const char* s2, const char* s3,
+                      const char* s4, const char* s5, const char* s6,
+                      const char* s7, const char* s8) {
+    return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
+  }
+
+  std::string Concat9(const char* s1, const char* s2, const char* s3,
+                      const char* s4, const char* s5, const char* s6,
+                      const char* s7, const char* s8, const char* s9) {
+    return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
+  }
+
+  std::string Concat10(const char* s1, const char* s2, const char* s3,
+                       const char* s4, const char* s5, const char* s6,
+                       const char* s7, const char* s8, const char* s9,
+                       const char* s10) {
+    return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
+  }
+
+ private:
+  int value_;
+};
+
+// Tests using Invoke() with a nullary function.
+TEST(InvokeTest, Nullary) {
+  Action<int()> a = Invoke(Nullary);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple()));
+}
+
+// Tests using Invoke() with a unary function.
+TEST(InvokeTest, Unary) {
+  Action<bool(int)> a = Invoke(Unary);  // NOLINT
+  EXPECT_FALSE(a.Perform(std::make_tuple(1)));
+  EXPECT_TRUE(a.Perform(std::make_tuple(-1)));
+}
+
+// Tests using Invoke() with a binary function.
+TEST(InvokeTest, Binary) {
+  Action<const char*(const char*, short)> a = Invoke(Binary);  // NOLINT
+  const char* p = "Hello";
+  EXPECT_EQ(p + 2, a.Perform(std::make_tuple(p, Short(2))));
+}
+
+// Tests using Invoke() with a ternary function.
+TEST(InvokeTest, Ternary) {
+  Action<int(int, char, short)> a = Invoke(Ternary);  // NOLINT
+  EXPECT_EQ(6, a.Perform(std::make_tuple(1, '\2', Short(3))));
+}
+
+// Tests using Invoke() with a 4-argument function.
+TEST(InvokeTest, FunctionThatTakes4Arguments) {
+  Action<int(int, int, int, int)> a = Invoke(SumOf4);  // NOLINT
+  EXPECT_EQ(1234, a.Perform(std::make_tuple(1000, 200, 30, 4)));
+}
+
+// Tests using Invoke() with a 5-argument function.
+TEST(InvokeTest, FunctionThatTakes5Arguments) {
+  Action<int(int, int, int, int, int)> a = Invoke(SumOf5);  // NOLINT
+  EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
+}
+
+// Tests using Invoke() with a 6-argument function.
+TEST(InvokeTest, FunctionThatTakes6Arguments) {
+  Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6);  // NOLINT
+  EXPECT_EQ(123456,
+            a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
+}
+
+// A helper that turns the type of a C-string literal from const
+// char[N] to const char*.
+inline const char* CharPtr(const char* s) { return s; }
+
+// Tests using Invoke() with a 7-argument function.
+TEST(InvokeTest, FunctionThatTakes7Arguments) {
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*)>
+      a = Invoke(Concat7);
+  EXPECT_EQ("1234567",
+            a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                      CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                      CharPtr("7"))));
+}
+
+// Tests using Invoke() with a 8-argument function.
+TEST(InvokeTest, FunctionThatTakes8Arguments) {
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*, const char*)>
+      a = Invoke(Concat8);
+  EXPECT_EQ("12345678",
+            a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                      CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                      CharPtr("7"), CharPtr("8"))));
+}
+
+// Tests using Invoke() with a 9-argument function.
+TEST(InvokeTest, FunctionThatTakes9Arguments) {
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*, const char*,
+                     const char*)>
+      a = Invoke(Concat9);
+  EXPECT_EQ("123456789", a.Perform(std::make_tuple(
+                             CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                             CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                             CharPtr("7"), CharPtr("8"), CharPtr("9"))));
+}
+
+// Tests using Invoke() with a 10-argument function.
+TEST(InvokeTest, FunctionThatTakes10Arguments) {
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*, const char*,
+                     const char*, const char*)>
+      a = Invoke(Concat10);
+  EXPECT_EQ("1234567890",
+            a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                      CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                      CharPtr("7"), CharPtr("8"), CharPtr("9"),
+                                      CharPtr("0"))));
+}
+
+// Tests using Invoke() with functions with parameters declared as Unused.
+TEST(InvokeTest, FunctionWithUnusedParameters) {
+  Action<int(int, int, double, const std::string&)> a1 = Invoke(SumOfFirst2);
+  std::tuple<int, int, double, std::string> dummy =
+      std::make_tuple(10, 2, 5.6, std::string("hi"));
+  EXPECT_EQ(12, a1.Perform(dummy));
+
+  Action<int(int, int, bool, int*)> a2 = Invoke(SumOfFirst2);
+  EXPECT_EQ(
+      23, a2.Perform(std::make_tuple(20, 3, true, static_cast<int*>(nullptr))));
+}
+
+// Tests using Invoke() with methods with parameters declared as Unused.
+TEST(InvokeTest, MethodWithUnusedParameters) {
+  Foo foo;
+  Action<int(std::string, bool, int, int)> a1 = Invoke(&foo, &Foo::SumOfLast2);
+  EXPECT_EQ(12, a1.Perform(std::make_tuple(CharPtr("hi"), true, 10, 2)));
+
+  Action<int(char, double, int, int)> a2 = Invoke(&foo, &Foo::SumOfLast2);
+  EXPECT_EQ(23, a2.Perform(std::make_tuple('a', 2.5, 20, 3)));
+}
+
+// Tests using Invoke() with a functor.
+TEST(InvokeTest, Functor) {
+  Action<long(long, int)> a = Invoke(plus<long>());  // NOLINT
+  EXPECT_EQ(3L, a.Perform(std::make_tuple(1, 2)));
+}
+
+// Tests using Invoke(f) as an action of a compatible type.
+TEST(InvokeTest, FunctionWithCompatibleType) {
+  Action<long(int, short, char, bool)> a = Invoke(SumOf4);  // NOLINT
+  EXPECT_EQ(4321, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
+}
+
+// Tests using Invoke() with an object pointer and a method pointer.
+
+// Tests using Invoke() with a nullary method.
+TEST(InvokeMethodTest, Nullary) {
+  Foo foo;
+  Action<int()> a = Invoke(&foo, &Foo::Nullary);  // NOLINT
+  EXPECT_EQ(123, a.Perform(std::make_tuple()));
+}
+
+// Tests using Invoke() with a unary method.
+TEST(InvokeMethodTest, Unary) {
+  Foo foo;
+  Action<short(long)> a = Invoke(&foo, &Foo::Unary);  // NOLINT
+  EXPECT_EQ(4123, a.Perform(std::make_tuple(4000)));
+}
+
+// Tests using Invoke() with a binary method.
+TEST(InvokeMethodTest, Binary) {
+  Foo foo;
+  Action<std::string(const std::string&, char)> a = Invoke(&foo, &Foo::Binary);
+  std::string s("Hell");
+  std::tuple<std::string, char> dummy = std::make_tuple(s, 'o');
+  EXPECT_EQ("Hello", a.Perform(dummy));
+}
+
+// Tests using Invoke() with a ternary method.
+TEST(InvokeMethodTest, Ternary) {
+  Foo foo;
+  Action<int(int, bool, char)> a = Invoke(&foo, &Foo::Ternary);  // NOLINT
+  EXPECT_EQ(1124, a.Perform(std::make_tuple(1000, true, Char(1))));
+}
+
+// Tests using Invoke() with a 4-argument method.
+TEST(InvokeMethodTest, MethodThatTakes4Arguments) {
+  Foo foo;
+  Action<int(int, int, int, int)> a = Invoke(&foo, &Foo::SumOf4);  // NOLINT
+  EXPECT_EQ(1357, a.Perform(std::make_tuple(1000, 200, 30, 4)));
+}
+
+// Tests using Invoke() with a 5-argument method.
+TEST(InvokeMethodTest, MethodThatTakes5Arguments) {
+  Foo foo;
+  Action<int(int, int, int, int, int)> a =
+      Invoke(&foo, &Foo::SumOf5);  // NOLINT
+  EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
+}
+
+// Tests using Invoke() with a 6-argument method.
+TEST(InvokeMethodTest, MethodThatTakes6Arguments) {
+  Foo foo;
+  Action<int(int, int, int, int, int, int)> a =  // NOLINT
+      Invoke(&foo, &Foo::SumOf6);
+  EXPECT_EQ(123456,
+            a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
+}
+
+// Tests using Invoke() with a 7-argument method.
+TEST(InvokeMethodTest, MethodThatTakes7Arguments) {
+  Foo foo;
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*)>
+      a = Invoke(&foo, &Foo::Concat7);
+  EXPECT_EQ("1234567",
+            a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                      CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                      CharPtr("7"))));
+}
+
+// Tests using Invoke() with a 8-argument method.
+TEST(InvokeMethodTest, MethodThatTakes8Arguments) {
+  Foo foo;
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*, const char*)>
+      a = Invoke(&foo, &Foo::Concat8);
+  EXPECT_EQ("12345678",
+            a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                      CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                      CharPtr("7"), CharPtr("8"))));
+}
+
+// Tests using Invoke() with a 9-argument method.
+TEST(InvokeMethodTest, MethodThatTakes9Arguments) {
+  Foo foo;
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*, const char*,
+                     const char*)>
+      a = Invoke(&foo, &Foo::Concat9);
+  EXPECT_EQ("123456789", a.Perform(std::make_tuple(
+                             CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                             CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                             CharPtr("7"), CharPtr("8"), CharPtr("9"))));
+}
+
+// Tests using Invoke() with a 10-argument method.
+TEST(InvokeMethodTest, MethodThatTakes10Arguments) {
+  Foo foo;
+  Action<std::string(const char*, const char*, const char*, const char*,
+                     const char*, const char*, const char*, const char*,
+                     const char*, const char*)>
+      a = Invoke(&foo, &Foo::Concat10);
+  EXPECT_EQ("1234567890",
+            a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                      CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                      CharPtr("7"), CharPtr("8"), CharPtr("9"),
+                                      CharPtr("0"))));
+}
+
+// Tests using Invoke(f) as an action of a compatible type.
+TEST(InvokeMethodTest, MethodWithCompatibleType) {
+  Foo foo;
+  Action<long(int, short, char, bool)> a =  // NOLINT
+      Invoke(&foo, &Foo::SumOf4);
+  EXPECT_EQ(4444, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
+}
+
+// Tests using WithoutArgs with an action that takes no argument.
+TEST(WithoutArgsTest, NoArg) {
+  Action<int(int n)> a = WithoutArgs(Invoke(Nullary));  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
+}
+
+// Tests using WithArg with an action that takes 1 argument.
+TEST(WithArgTest, OneArg) {
+  Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary));  // NOLINT
+  EXPECT_TRUE(b.Perform(std::make_tuple(1.5, -1)));
+  EXPECT_FALSE(b.Perform(std::make_tuple(1.5, 1)));
+}
+
+TEST(ReturnArgActionTest, WorksForOneArgIntArg0) {
+  const Action<int(int)> a = ReturnArg<0>();
+  EXPECT_EQ(5, a.Perform(std::make_tuple(5)));
+}
+
+TEST(ReturnArgActionTest, WorksForMultiArgBoolArg0) {
+  const Action<bool(bool, bool, bool)> a = ReturnArg<0>();
+  EXPECT_TRUE(a.Perform(std::make_tuple(true, false, false)));
+}
+
+TEST(ReturnArgActionTest, WorksForMultiArgStringArg2) {
+  const Action<std::string(int, int, std::string, int)> a = ReturnArg<2>();
+  EXPECT_EQ("seven", a.Perform(std::make_tuple(5, 6, std::string("seven"), 8)));
+}
+
+TEST(ReturnArgActionTest, WorksForNonConstRefArg0) {
+  const Action<std::string&(std::string&)> a = ReturnArg<0>();
+  std::string s = "12345";
+  EXPECT_EQ(&s, &a.Perform(std::forward_as_tuple(s)));
+}
+
+TEST(SaveArgActionTest, WorksForSameType) {
+  int result = 0;
+  const Action<void(int n)> a1 = SaveArg<0>(&result);
+  a1.Perform(std::make_tuple(5));
+  EXPECT_EQ(5, result);
+}
+
+TEST(SaveArgActionTest, WorksForCompatibleType) {
+  int result = 0;
+  const Action<void(bool, char)> a1 = SaveArg<1>(&result);
+  a1.Perform(std::make_tuple(true, 'a'));
+  EXPECT_EQ('a', result);
+}
+
+TEST(SaveArgPointeeActionTest, WorksForSameType) {
+  int result = 0;
+  const int value = 5;
+  const Action<void(const int*)> a1 = SaveArgPointee<0>(&result);
+  a1.Perform(std::make_tuple(&value));
+  EXPECT_EQ(5, result);
+}
+
+TEST(SaveArgPointeeActionTest, WorksForCompatibleType) {
+  int result = 0;
+  char value = 'a';
+  const Action<void(bool, char*)> a1 = SaveArgPointee<1>(&result);
+  a1.Perform(std::make_tuple(true, &value));
+  EXPECT_EQ('a', result);
+}
+
+TEST(SetArgRefereeActionTest, WorksForSameType) {
+  int value = 0;
+  const Action<void(int&)> a1 = SetArgReferee<0>(1);
+  a1.Perform(std::tuple<int&>(value));
+  EXPECT_EQ(1, value);
+}
+
+TEST(SetArgRefereeActionTest, WorksForCompatibleType) {
+  int value = 0;
+  const Action<void(int, int&)> a1 = SetArgReferee<1>('a');
+  a1.Perform(std::tuple<int, int&>(0, value));
+  EXPECT_EQ('a', value);
+}
+
+TEST(SetArgRefereeActionTest, WorksWithExtraArguments) {
+  int value = 0;
+  const Action<void(bool, int, int&, const char*)> a1 = SetArgReferee<2>('a');
+  a1.Perform(std::tuple<bool, int, int&, const char*>(true, 0, value, "hi"));
+  EXPECT_EQ('a', value);
+}
+
+// A class that can be used to verify that its destructor is called: it will set
+// the bool provided to the constructor to true when destroyed.
+class DeletionTester {
+ public:
+  explicit DeletionTester(bool* is_deleted) : is_deleted_(is_deleted) {
+    // Make sure the bit is set to false.
+    *is_deleted_ = false;
+  }
+
+  ~DeletionTester() { *is_deleted_ = true; }
+
+ private:
+  bool* is_deleted_;
+};
+
+TEST(DeleteArgActionTest, OneArg) {
+  bool is_deleted = false;
+  DeletionTester* t = new DeletionTester(&is_deleted);
+  const Action<void(DeletionTester*)> a1 = DeleteArg<0>();  // NOLINT
+  EXPECT_FALSE(is_deleted);
+  a1.Perform(std::make_tuple(t));
+  EXPECT_TRUE(is_deleted);
+}
+
+TEST(DeleteArgActionTest, TenArgs) {
+  bool is_deleted = false;
+  DeletionTester* t = new DeletionTester(&is_deleted);
+  const Action<void(bool, int, int, const char*, bool, int, int, int, int,
+                    DeletionTester*)>
+      a1 = DeleteArg<9>();
+  EXPECT_FALSE(is_deleted);
+  a1.Perform(std::make_tuple(true, 5, 6, CharPtr("hi"), false, 7, 8, 9, 10, t));
+  EXPECT_TRUE(is_deleted);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+TEST(ThrowActionTest, ThrowsGivenExceptionInVoidFunction) {
+  const Action<void(int n)> a = Throw('a');
+  EXPECT_THROW(a.Perform(std::make_tuple(0)), char);
+}
+
+class MyException {};
+
+TEST(ThrowActionTest, ThrowsGivenExceptionInNonVoidFunction) {
+  const Action<double(char ch)> a = Throw(MyException());
+  EXPECT_THROW(a.Perform(std::make_tuple('0')), MyException);
+}
+
+TEST(ThrowActionTest, ThrowsGivenExceptionInNullaryFunction) {
+  const Action<double()> a = Throw(MyException());
+  EXPECT_THROW(a.Perform(std::make_tuple()), MyException);
+}
+
+class Object {
+ public:
+  virtual ~Object() {}
+  virtual void Func() {}
+};
+
+class MockObject : public Object {
+ public:
+  ~MockObject() override {}
+  MOCK_METHOD(void, Func, (), (override));
+};
+
+TEST(ThrowActionTest, Times0) {
+  EXPECT_NONFATAL_FAILURE(
+      [] {
+        try {
+          MockObject m;
+          ON_CALL(m, Func()).WillByDefault([] { throw "something"; });
+          EXPECT_CALL(m, Func()).Times(0);
+          m.Func();
+        } catch (...) {
+          // Exception is caught but Times(0) still triggers a failure.
+        }
+      }(),
+      "");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that SetArrayArgument<N>(first, last) sets the elements of the array
+// pointed to by the N-th (0-based) argument to values in range [first, last).
+TEST(SetArrayArgumentTest, SetsTheNthArray) {
+  using MyFunction = void(bool, int*, char*);
+  int numbers[] = {1, 2, 3};
+  Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers + 3);
+
+  int n[4] = {};
+  int* pn = n;
+  char ch[4] = {};
+  char* pch = ch;
+  a.Perform(std::make_tuple(true, pn, pch));
+  EXPECT_EQ(1, n[0]);
+  EXPECT_EQ(2, n[1]);
+  EXPECT_EQ(3, n[2]);
+  EXPECT_EQ(0, n[3]);
+  EXPECT_EQ('\0', ch[0]);
+  EXPECT_EQ('\0', ch[1]);
+  EXPECT_EQ('\0', ch[2]);
+  EXPECT_EQ('\0', ch[3]);
+
+  // Tests first and last are iterators.
+  std::string letters = "abc";
+  a = SetArrayArgument<2>(letters.begin(), letters.end());
+  std::fill_n(n, 4, 0);
+  std::fill_n(ch, 4, '\0');
+  a.Perform(std::make_tuple(true, pn, pch));
+  EXPECT_EQ(0, n[0]);
+  EXPECT_EQ(0, n[1]);
+  EXPECT_EQ(0, n[2]);
+  EXPECT_EQ(0, n[3]);
+  EXPECT_EQ('a', ch[0]);
+  EXPECT_EQ('b', ch[1]);
+  EXPECT_EQ('c', ch[2]);
+  EXPECT_EQ('\0', ch[3]);
+}
+
+// Tests SetArrayArgument<N>(first, last) where first == last.
+TEST(SetArrayArgumentTest, SetsTheNthArrayWithEmptyRange) {
+  using MyFunction = void(bool, int*);
+  int numbers[] = {1, 2, 3};
+  Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers);
+
+  int n[4] = {};
+  int* pn = n;
+  a.Perform(std::make_tuple(true, pn));
+  EXPECT_EQ(0, n[0]);
+  EXPECT_EQ(0, n[1]);
+  EXPECT_EQ(0, n[2]);
+  EXPECT_EQ(0, n[3]);
+}
+
+// Tests SetArrayArgument<N>(first, last) where *first is convertible
+// (but not equal) to the argument type.
+TEST(SetArrayArgumentTest, SetsTheNthArrayWithConvertibleType) {
+  using MyFunction = void(bool, int*);
+  char chars[] = {97, 98, 99};
+  Action<MyFunction> a = SetArrayArgument<1>(chars, chars + 3);
+
+  int codes[4] = {111, 222, 333, 444};
+  int* pcodes = codes;
+  a.Perform(std::make_tuple(true, pcodes));
+  EXPECT_EQ(97, codes[0]);
+  EXPECT_EQ(98, codes[1]);
+  EXPECT_EQ(99, codes[2]);
+  EXPECT_EQ(444, codes[3]);
+}
+
+// Test SetArrayArgument<N>(first, last) with iterator as argument.
+TEST(SetArrayArgumentTest, SetsTheNthArrayWithIteratorArgument) {
+  using MyFunction = void(bool, std::back_insert_iterator<std::string>);
+  std::string letters = "abc";
+  Action<MyFunction> a = SetArrayArgument<1>(letters.begin(), letters.end());
+
+  std::string s;
+  a.Perform(std::make_tuple(true, std::back_inserter(s)));
+  EXPECT_EQ(letters, s);
+}
+
+TEST(ReturnPointeeTest, Works) {
+  int n = 42;
+  const Action<int()> a = ReturnPointee(&n);
+  EXPECT_EQ(42, a.Perform(std::make_tuple()));
+
+  n = 43;
+  EXPECT_EQ(43, a.Perform(std::make_tuple()));
+}
+
+// Tests InvokeArgument<N>(...).
+
+// Tests using InvokeArgument with a nullary function.
+TEST(InvokeArgumentTest, Function0) {
+  Action<int(int, int (*)())> a = InvokeArgument<1>();  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(2, &Nullary)));
+}
+
+// Tests using InvokeArgument with a unary functor.
+TEST(InvokeArgumentTest, Functor1) {
+  Action<int(UnaryFunctor)> a = InvokeArgument<0>(true);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(UnaryFunctor())));
+}
+
+// Tests using InvokeArgument with a unary move-only functor.
+TEST(InvokeArgumentTest, Functor1MoveOnly) {
+  Action<int(UnaryMoveOnlyFunctor)> a = InvokeArgument<0>(true);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(UnaryMoveOnlyFunctor())));
+}
+
+// Tests using InvokeArgument with a one-shot unary functor.
+TEST(InvokeArgumentTest, OneShotFunctor1) {
+  Action<int(OneShotUnaryFunctor)> a = InvokeArgument<0>(true);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(OneShotUnaryFunctor())));
+}
+
+// Tests using InvokeArgument with a 5-ary function.
+TEST(InvokeArgumentTest, Function5) {
+  Action<int(int (*)(int, int, int, int, int))> a =  // NOLINT
+      InvokeArgument<0>(10000, 2000, 300, 40, 5);
+  EXPECT_EQ(12345, a.Perform(std::make_tuple(&SumOf5)));
+}
+
+// Tests using InvokeArgument with a 5-ary functor.
+TEST(InvokeArgumentTest, Functor5) {
+  Action<int(SumOf5Functor)> a =  // NOLINT
+      InvokeArgument<0>(10000, 2000, 300, 40, 5);
+  EXPECT_EQ(12345, a.Perform(std::make_tuple(SumOf5Functor())));
+}
+
+// Tests using InvokeArgument with a 6-ary function.
+TEST(InvokeArgumentTest, Function6) {
+  Action<int(int (*)(int, int, int, int, int, int))> a =  // NOLINT
+      InvokeArgument<0>(100000, 20000, 3000, 400, 50, 6);
+  EXPECT_EQ(123456, a.Perform(std::make_tuple(&SumOf6)));
+}
+
+// Tests using InvokeArgument with a 6-ary functor.
+TEST(InvokeArgumentTest, Functor6) {
+  Action<int(SumOf6Functor)> a =  // NOLINT
+      InvokeArgument<0>(100000, 20000, 3000, 400, 50, 6);
+  EXPECT_EQ(123456, a.Perform(std::make_tuple(SumOf6Functor())));
+}
+
+// Tests using InvokeArgument with a 7-ary function.
+TEST(InvokeArgumentTest, Function7) {
+  Action<std::string(std::string(*)(const char*, const char*, const char*,
+                                    const char*, const char*, const char*,
+                                    const char*))>
+      a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
+  EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
+}
+
+// Tests using InvokeArgument with a 8-ary function.
+TEST(InvokeArgumentTest, Function8) {
+  Action<std::string(std::string(*)(const char*, const char*, const char*,
+                                    const char*, const char*, const char*,
+                                    const char*, const char*))>
+      a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
+  EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
+}
+
+// Tests using InvokeArgument with a 9-ary function.
+TEST(InvokeArgumentTest, Function9) {
+  Action<std::string(std::string(*)(const char*, const char*, const char*,
+                                    const char*, const char*, const char*,
+                                    const char*, const char*, const char*))>
+      a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
+  EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
+}
+
+// Tests using InvokeArgument with a 10-ary function.
+TEST(InvokeArgumentTest, Function10) {
+  Action<std::string(std::string(*)(
+      const char*, const char*, const char*, const char*, const char*,
+      const char*, const char*, const char*, const char*, const char*))>
+      a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
+  EXPECT_EQ("1234567890", a.Perform(std::make_tuple(&Concat10)));
+}
+
+// Tests using InvokeArgument with a function that takes a pointer argument.
+TEST(InvokeArgumentTest, ByPointerFunction) {
+  Action<const char*(const char* (*)(const char* input, short n))>  // NOLINT
+      a = InvokeArgument<0>(static_cast<const char*>("Hi"), Short(1));
+  EXPECT_STREQ("i", a.Perform(std::make_tuple(&Binary)));
+}
+
+// Tests using InvokeArgument with a function that takes a const char*
+// by passing it a C-string literal.
+TEST(InvokeArgumentTest, FunctionWithCStringLiteral) {
+  Action<const char*(const char* (*)(const char* input, short n))>  // NOLINT
+      a = InvokeArgument<0>("Hi", Short(1));
+  EXPECT_STREQ("i", a.Perform(std::make_tuple(&Binary)));
+}
+
+// Tests using InvokeArgument with a function that takes a const reference.
+TEST(InvokeArgumentTest, ByConstReferenceFunction) {
+  Action<bool(bool (*function)(const std::string& s))> a =  // NOLINT
+      InvokeArgument<0>(std::string("Hi"));
+  // When action 'a' is constructed, it makes a copy of the temporary
+  // string object passed to it, so it's OK to use 'a' later, when the
+  // temporary object has already died.
+  EXPECT_TRUE(a.Perform(std::make_tuple(&ByConstRef)));
+}
+
+// Tests using InvokeArgument with ByRef() and a function that takes a
+// const reference.
+TEST(InvokeArgumentTest, ByExplicitConstReferenceFunction) {
+  Action<bool(bool (*)(const double& x))> a =  // NOLINT
+      InvokeArgument<0>(ByRef(g_double));
+  // The above line calls ByRef() on a const value.
+  EXPECT_TRUE(a.Perform(std::make_tuple(&ReferencesGlobalDouble)));
+
+  double x = 0;
+  a = InvokeArgument<0>(ByRef(x));  // This calls ByRef() on a non-const.
+  EXPECT_FALSE(a.Perform(std::make_tuple(&ReferencesGlobalDouble)));
+}
+
+TEST(InvokeArgumentTest, MoveOnlyType) {
+  struct Marker {};
+  struct {
+    // Method takes a unique_ptr (to a type we don't care about), and an
+    // invocable type.
+    MOCK_METHOD(bool, MockMethod,
+                (std::unique_ptr<Marker>, std::function<int()>), ());
+  } mock;
+
+  ON_CALL(mock, MockMethod(_, _)).WillByDefault(InvokeArgument<1>());
+
+  // This compiles, but is a little opaque as a workaround:
+  ON_CALL(mock, MockMethod(_, _))
+      .WillByDefault(WithArg<1>(InvokeArgument<0>()));
+}
+
+// Tests DoAll(a1, a2).
+TEST(DoAllTest, TwoActions) {
+  int n = 0;
+  Action<int(int*)> a = DoAll(SetArgPointee<0>(1),  // NOLINT
+                              Return(2));
+  EXPECT_EQ(2, a.Perform(std::make_tuple(&n)));
+  EXPECT_EQ(1, n);
+}
+
+// Tests DoAll(a1, a2, a3).
+TEST(DoAllTest, ThreeActions) {
+  int m = 0, n = 0;
+  Action<int(int*, int*)> a = DoAll(SetArgPointee<0>(1),  // NOLINT
+                                    SetArgPointee<1>(2), Return(3));
+  EXPECT_EQ(3, a.Perform(std::make_tuple(&m, &n)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+}
+
+// Tests DoAll(a1, a2, a3, a4).
+TEST(DoAllTest, FourActions) {
+  int m = 0, n = 0;
+  char ch = '\0';
+  Action<int(int*, int*, char*)> a =  // NOLINT
+      DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2), SetArgPointee<2>('a'),
+            Return(3));
+  EXPECT_EQ(3, a.Perform(std::make_tuple(&m, &n, &ch)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', ch);
+}
+
+// Tests DoAll(a1, a2, a3, a4, a5).
+TEST(DoAllTest, FiveActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0';
+  Action<int(int*, int*, char*, char*)> action =  // NOLINT
+      DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2), SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'), Return(3));
+  EXPECT_EQ(3, action.Perform(std::make_tuple(&m, &n, &a, &b)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+}
+
+// Tests DoAll(a1, a2, ..., a6).
+TEST(DoAllTest, SixActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0';
+  Action<int(int*, int*, char*, char*, char*)> action =  // NOLINT
+      DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2), SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'), SetArgPointee<4>('c'), Return(3));
+  EXPECT_EQ(3, action.Perform(std::make_tuple(&m, &n, &a, &b, &c)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+}
+
+// Tests DoAll(a1, a2, ..., a7).
+TEST(DoAllTest, SevenActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*)> action =  // NOLINT
+      DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2), SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'), SetArgPointee<4>('c'), SetArgPointee<5>('d'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(std::make_tuple(&m, &n, &a, &b, &c, &d)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+}
+
+// Tests DoAll(a1, a2, ..., a8).
+TEST(DoAllTest, EightActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0', e = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*,  // NOLINT
+             char*)>
+      action =
+          DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2), SetArgPointee<2>('a'),
+                SetArgPointee<3>('b'), SetArgPointee<4>('c'),
+                SetArgPointee<5>('d'), SetArgPointee<6>('e'), Return(3));
+  EXPECT_EQ(3, action.Perform(std::make_tuple(&m, &n, &a, &b, &c, &d, &e)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+  EXPECT_EQ('e', e);
+}
+
+// Tests DoAll(a1, a2, ..., a9).
+TEST(DoAllTest, NineActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0', e = '\0', f = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*,  // NOLINT
+             char*, char*)>
+      action = DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2),
+                     SetArgPointee<2>('a'), SetArgPointee<3>('b'),
+                     SetArgPointee<4>('c'), SetArgPointee<5>('d'),
+                     SetArgPointee<6>('e'), SetArgPointee<7>('f'), Return(3));
+  EXPECT_EQ(3, action.Perform(std::make_tuple(&m, &n, &a, &b, &c, &d, &e, &f)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+  EXPECT_EQ('e', e);
+  EXPECT_EQ('f', f);
+}
+
+// Tests DoAll(a1, a2, ..., a10).
+TEST(DoAllTest, TenActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0';
+  char e = '\0', f = '\0', g = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*,  // NOLINT
+             char*, char*, char*)>
+      action =
+          DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2), SetArgPointee<2>('a'),
+                SetArgPointee<3>('b'), SetArgPointee<4>('c'),
+                SetArgPointee<5>('d'), SetArgPointee<6>('e'),
+                SetArgPointee<7>('f'), SetArgPointee<8>('g'), Return(3));
+  EXPECT_EQ(
+      3, action.Perform(std::make_tuple(&m, &n, &a, &b, &c, &d, &e, &f, &g)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+  EXPECT_EQ('e', e);
+  EXPECT_EQ('f', f);
+  EXPECT_EQ('g', g);
+}
+
+TEST(DoAllTest, NoArgs) {
+  bool ran_first = false;
+  Action<bool()> a =
+      DoAll([&] { ran_first = true; }, [&] { return ran_first; });
+  EXPECT_TRUE(a.Perform({}));
+}
+
+TEST(DoAllTest, MoveOnlyArgs) {
+  bool ran_first = false;
+  Action<int(std::unique_ptr<int>)> a =
+      DoAll(InvokeWithoutArgs([&] { ran_first = true; }),
+            [](std::unique_ptr<int> p) { return *p; });
+  EXPECT_EQ(7, a.Perform(std::make_tuple(std::unique_ptr<int>(new int(7)))));
+  EXPECT_TRUE(ran_first);
+}
+
+TEST(DoAllTest, ImplicitlyConvertsActionArguments) {
+  bool ran_first = false;
+  // Action<void(std::vector<int>)> isn't an
+  // Action<void(const std::vector<int>&) but can be converted.
+  Action<void(std::vector<int>)> first = [&] { ran_first = true; };
+  Action<int(std::vector<int>)> a =
+      DoAll(first, [](std::vector<int> arg) { return arg.front(); });
+  EXPECT_EQ(7, a.Perform(std::make_tuple(std::vector<int>{7})));
+  EXPECT_TRUE(ran_first);
+}
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+// Also suppress C4503 decorated name length exceeded, name was truncated
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100 4503)
+// Tests the ACTION*() macro family.
+
+// Tests that ACTION() can define an action that doesn't reference the
+// mock function arguments.
+ACTION(Return5) { return 5; }
+
+TEST(ActionMacroTest, WorksWhenNotReferencingArguments) {
+  Action<double()> a1 = Return5();
+  EXPECT_DOUBLE_EQ(5, a1.Perform(std::make_tuple()));
+
+  Action<int(double, bool)> a2 = Return5();
+  EXPECT_EQ(5, a2.Perform(std::make_tuple(1, true)));
+}
+
+// Tests that ACTION() can define an action that returns void.
+ACTION(IncrementArg1) { (*arg1)++; }
+
+TEST(ActionMacroTest, WorksWhenReturningVoid) {
+  Action<void(int, int*)> a1 = IncrementArg1();
+  int n = 0;
+  a1.Perform(std::make_tuple(5, &n));
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the body of ACTION() can reference the type of the
+// argument.
+ACTION(IncrementArg2) {
+  StaticAssertTypeEq<int*, arg2_type>();
+  arg2_type temp = arg2;
+  (*temp)++;
+}
+
+TEST(ActionMacroTest, CanReferenceArgumentType) {
+  Action<void(int, bool, int*)> a1 = IncrementArg2();
+  int n = 0;
+  a1.Perform(std::make_tuple(5, false, &n));
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the body of ACTION() can reference the argument tuple
+// via args_type and args.
+ACTION(Sum2) {
+  StaticAssertTypeEq<std::tuple<int, char, int*>, args_type>();
+  args_type args_copy = args;
+  return std::get<0>(args_copy) + std::get<1>(args_copy);
+}
+
+TEST(ActionMacroTest, CanReferenceArgumentTuple) {
+  Action<int(int, char, int*)> a1 = Sum2();
+  int dummy = 0;
+  EXPECT_EQ(11, a1.Perform(std::make_tuple(5, Char(6), &dummy)));
+}
+
+namespace {
+
+// Tests that the body of ACTION() can reference the mock function
+// type.
+int Dummy(bool flag) { return flag ? 1 : 0; }
+
+}  // namespace
+
+ACTION(InvokeDummy) {
+  StaticAssertTypeEq<int(bool), function_type>();
+  function_type* fp = &Dummy;
+  return (*fp)(true);
+}
+
+TEST(ActionMacroTest, CanReferenceMockFunctionType) {
+  Action<int(bool)> a1 = InvokeDummy();
+  EXPECT_EQ(1, a1.Perform(std::make_tuple(true)));
+  EXPECT_EQ(1, a1.Perform(std::make_tuple(false)));
+}
+
+// Tests that the body of ACTION() can reference the mock function's
+// return type.
+ACTION(InvokeDummy2) {
+  StaticAssertTypeEq<int, return_type>();
+  return_type result = Dummy(true);
+  return result;
+}
+
+TEST(ActionMacroTest, CanReferenceMockFunctionReturnType) {
+  Action<int(bool)> a1 = InvokeDummy2();
+  EXPECT_EQ(1, a1.Perform(std::make_tuple(true)));
+  EXPECT_EQ(1, a1.Perform(std::make_tuple(false)));
+}
+
+// Tests that ACTION() works for arguments passed by const reference.
+ACTION(ReturnAddrOfConstBoolReferenceArg) {
+  StaticAssertTypeEq<const bool&, arg1_type>();
+  return &arg1;
+}
+
+TEST(ActionMacroTest, WorksForConstReferenceArg) {
+  Action<const bool*(int, const bool&)> a = ReturnAddrOfConstBoolReferenceArg();
+  const bool b = false;
+  EXPECT_EQ(&b, a.Perform(std::tuple<int, const bool&>(0, b)));
+}
+
+// Tests that ACTION() works for arguments passed by non-const reference.
+ACTION(ReturnAddrOfIntReferenceArg) {
+  StaticAssertTypeEq<int&, arg0_type>();
+  return &arg0;
+}
+
+TEST(ActionMacroTest, WorksForNonConstReferenceArg) {
+  Action<int*(int&, bool, int)> a = ReturnAddrOfIntReferenceArg();
+  int n = 0;
+  EXPECT_EQ(&n, a.Perform(std::tuple<int&, bool, int>(n, true, 1)));
+}
+
+// Tests that ACTION() can be used in a namespace.
+namespace action_test {
+ACTION(Sum) { return arg0 + arg1; }
+}  // namespace action_test
+
+TEST(ActionMacroTest, WorksInNamespace) {
+  Action<int(int, int)> a1 = action_test::Sum();
+  EXPECT_EQ(3, a1.Perform(std::make_tuple(1, 2)));
+}
+
+// Tests that the same ACTION definition works for mock functions with
+// different argument numbers.
+ACTION(PlusTwo) { return arg0 + 2; }
+
+TEST(ActionMacroTest, WorksForDifferentArgumentNumbers) {
+  Action<int(int)> a1 = PlusTwo();
+  EXPECT_EQ(4, a1.Perform(std::make_tuple(2)));
+
+  Action<double(float, void*)> a2 = PlusTwo();
+  int dummy;
+  EXPECT_DOUBLE_EQ(6, a2.Perform(std::make_tuple(4.0f, &dummy)));
+}
+
+// Tests that ACTION_P can define a parameterized action.
+ACTION_P(Plus, n) { return arg0 + n; }
+
+TEST(ActionPMacroTest, DefinesParameterizedAction) {
+  Action<int(int m, bool t)> a1 = Plus(9);
+  EXPECT_EQ(10, a1.Perform(std::make_tuple(1, true)));
+}
+
+// Tests that the body of ACTION_P can reference the argument types
+// and the parameter type.
+ACTION_P(TypedPlus, n) {
+  arg0_type t1 = arg0;
+  n_type t2 = n;
+  return t1 + t2;
+}
+
+TEST(ActionPMacroTest, CanReferenceArgumentAndParameterTypes) {
+  Action<int(char m, bool t)> a1 = TypedPlus(9);
+  EXPECT_EQ(10, a1.Perform(std::make_tuple(Char(1), true)));
+}
+
+// Tests that a parameterized action can be used in any mock function
+// whose type is compatible.
+TEST(ActionPMacroTest, WorksInCompatibleMockFunction) {
+  Action<std::string(const std::string& s)> a1 = Plus("tail");
+  const std::string re = "re";
+  std::tuple<const std::string> dummy = std::make_tuple(re);
+  EXPECT_EQ("retail", a1.Perform(dummy));
+}
+
+// Tests that we can use ACTION*() to define actions overloaded on the
+// number of parameters.
+
+ACTION(OverloadedAction) { return arg0 ? arg1 : "hello"; }
+
+ACTION_P(OverloadedAction, default_value) {
+  return arg0 ? arg1 : default_value;
+}
+
+ACTION_P2(OverloadedAction, true_value, false_value) {
+  return arg0 ? true_value : false_value;
+}
+
+TEST(ActionMacroTest, CanDefineOverloadedActions) {
+  using MyAction = Action<const char*(bool, const char*)>;
+
+  const MyAction a1 = OverloadedAction();
+  EXPECT_STREQ("hello", a1.Perform(std::make_tuple(false, CharPtr("world"))));
+  EXPECT_STREQ("world", a1.Perform(std::make_tuple(true, CharPtr("world"))));
+
+  const MyAction a2 = OverloadedAction("hi");
+  EXPECT_STREQ("hi", a2.Perform(std::make_tuple(false, CharPtr("world"))));
+  EXPECT_STREQ("world", a2.Perform(std::make_tuple(true, CharPtr("world"))));
+
+  const MyAction a3 = OverloadedAction("hi", "you");
+  EXPECT_STREQ("hi", a3.Perform(std::make_tuple(true, CharPtr("world"))));
+  EXPECT_STREQ("you", a3.Perform(std::make_tuple(false, CharPtr("world"))));
+}
+
+// Tests ACTION_Pn where n >= 3.
+
+ACTION_P3(Plus, m, n, k) { return arg0 + m + n + k; }
+
+TEST(ActionPnMacroTest, WorksFor3Parameters) {
+  Action<double(int m, bool t)> a1 = Plus(100, 20, 3.4);
+  EXPECT_DOUBLE_EQ(3123.4, a1.Perform(std::make_tuple(3000, true)));
+
+  Action<std::string(const std::string& s)> a2 = Plus("tail", "-", ">");
+  const std::string re = "re";
+  std::tuple<const std::string> dummy = std::make_tuple(re);
+  EXPECT_EQ("retail->", a2.Perform(dummy));
+}
+
+ACTION_P4(Plus, p0, p1, p2, p3) { return arg0 + p0 + p1 + p2 + p3; }
+
+TEST(ActionPnMacroTest, WorksFor4Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4, a1.Perform(std::make_tuple(10)));
+}
+
+ACTION_P5(Plus, p0, p1, p2, p3, p4) { return arg0 + p0 + p1 + p2 + p3 + p4; }
+
+TEST(ActionPnMacroTest, WorksFor5Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5, a1.Perform(std::make_tuple(10)));
+}
+
+ACTION_P6(Plus, p0, p1, p2, p3, p4, p5) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5;
+}
+
+TEST(ActionPnMacroTest, WorksFor6Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6, a1.Perform(std::make_tuple(10)));
+}
+
+ACTION_P7(Plus, p0, p1, p2, p3, p4, p5, p6) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5 + p6;
+}
+
+TEST(ActionPnMacroTest, WorksFor7Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7, a1.Perform(std::make_tuple(10)));
+}
+
+ACTION_P8(Plus, p0, p1, p2, p3, p4, p5, p6, p7) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7;
+}
+
+TEST(ActionPnMacroTest, WorksFor8Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7, 8);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
+            a1.Perform(std::make_tuple(10)));
+}
+
+ACTION_P9(Plus, p0, p1, p2, p3, p4, p5, p6, p7, p8) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8;
+}
+
+TEST(ActionPnMacroTest, WorksFor9Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7, 8, 9);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9,
+            a1.Perform(std::make_tuple(10)));
+}
+
+ACTION_P10(Plus, p0, p1, p2, p3, p4, p5, p6, p7, p8, last_param) {
+  arg0_type t0 = arg0;
+  last_param_type t9 = last_param;
+  return t0 + p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + t9;
+}
+
+TEST(ActionPnMacroTest, WorksFor10Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10,
+            a1.Perform(std::make_tuple(10)));
+}
+
+// Tests that the action body can promote the parameter types.
+
+ACTION_P2(PadArgument, prefix, suffix) {
+  // The following lines promote the two parameters to desired types.
+  std::string prefix_str(prefix);
+  char suffix_char = static_cast<char>(suffix);
+  return prefix_str + arg0 + suffix_char;
+}
+
+TEST(ActionPnMacroTest, SimpleTypePromotion) {
+  Action<std::string(const char*)> no_promo =
+      PadArgument(std::string("foo"), 'r');
+  Action<std::string(const char*)> promo =
+      PadArgument("foo", static_cast<int>('r'));
+  EXPECT_EQ("foobar", no_promo.Perform(std::make_tuple(CharPtr("ba"))));
+  EXPECT_EQ("foobar", promo.Perform(std::make_tuple(CharPtr("ba"))));
+}
+
+// Tests that we can partially restrict parameter types using a
+// straight-forward pattern.
+
+// Defines a generic action that doesn't restrict the types of its
+// parameters.
+ACTION_P3(ConcatImpl, a, b, c) {
+  std::stringstream ss;
+  ss << a << b << c;
+  return ss.str();
+}
+
+// Next, we try to restrict that either the first parameter is a
+// string, or the second parameter is an int.
+
+// Defines a partially specialized wrapper that restricts the first
+// parameter to std::string.
+template <typename T1, typename T2>
+// ConcatImplActionP3 is the class template ACTION_P3 uses to
+// implement ConcatImpl.  We shouldn't change the name as this
+// pattern requires the user to use it directly.
+ConcatImplActionP3<std::string, T1, T2> Concat(const std::string& a, T1 b,
+                                               T2 c) {
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (true) {
+    GTEST_INTENTIONAL_CONST_COND_POP_()
+    // This branch verifies that ConcatImpl() can be invoked without
+    // explicit template arguments.
+    return ConcatImpl(a, b, c);
+  } else {
+    // This branch verifies that ConcatImpl() can also be invoked with
+    // explicit template arguments.  It doesn't really need to be
+    // executed as this is a compile-time verification.
+    return ConcatImpl<std::string, T1, T2>(a, b, c);
+  }
+}
+
+// Defines another partially specialized wrapper that restricts the
+// second parameter to int.
+template <typename T1, typename T2>
+ConcatImplActionP3<T1, int, T2> Concat(T1 a, int b, T2 c) {
+  return ConcatImpl(a, b, c);
+}
+
+TEST(ActionPnMacroTest, CanPartiallyRestrictParameterTypes) {
+  Action<const std::string()> a1 = Concat("Hello", "1", 2);
+  EXPECT_EQ("Hello12", a1.Perform(std::make_tuple()));
+
+  a1 = Concat(1, 2, 3);
+  EXPECT_EQ("123", a1.Perform(std::make_tuple()));
+}
+
+// Verifies the type of an ACTION*.
+
+ACTION(DoFoo) {}
+ACTION_P(DoFoo, p) {}
+ACTION_P2(DoFoo, p0, p1) {}
+
+TEST(ActionPnMacroTest, TypesAreCorrect) {
+  // DoFoo() must be assignable to a DoFooAction variable.
+  DoFooAction a0 = DoFoo();
+
+  // DoFoo(1) must be assignable to a DoFooActionP variable.
+  DoFooActionP<int> a1 = DoFoo(1);
+
+  // DoFoo(p1, ..., pk) must be assignable to a DoFooActionPk
+  // variable, and so on.
+  DoFooActionP2<int, char> a2 = DoFoo(1, '2');
+  PlusActionP3<int, int, char> a3 = Plus(1, 2, '3');
+  PlusActionP4<int, int, int, char> a4 = Plus(1, 2, 3, '4');
+  PlusActionP5<int, int, int, int, char> a5 = Plus(1, 2, 3, 4, '5');
+  PlusActionP6<int, int, int, int, int, char> a6 = Plus(1, 2, 3, 4, 5, '6');
+  PlusActionP7<int, int, int, int, int, int, char> a7 =
+      Plus(1, 2, 3, 4, 5, 6, '7');
+  PlusActionP8<int, int, int, int, int, int, int, char> a8 =
+      Plus(1, 2, 3, 4, 5, 6, 7, '8');
+  PlusActionP9<int, int, int, int, int, int, int, int, char> a9 =
+      Plus(1, 2, 3, 4, 5, 6, 7, 8, '9');
+  PlusActionP10<int, int, int, int, int, int, int, int, int, char> a10 =
+      Plus(1, 2, 3, 4, 5, 6, 7, 8, 9, '0');
+
+  // Avoid "unused variable" warnings.
+  (void)a0;
+  (void)a1;
+  (void)a2;
+  (void)a3;
+  (void)a4;
+  (void)a5;
+  (void)a6;
+  (void)a7;
+  (void)a8;
+  (void)a9;
+  (void)a10;
+}
+
+// Tests that an ACTION_P*() action can be explicitly instantiated
+// with reference-typed parameters.
+
+ACTION_P(Plus1, x) { return x; }
+ACTION_P2(Plus2, x, y) { return x + y; }
+ACTION_P3(Plus3, x, y, z) { return x + y + z; }
+ACTION_P10(Plus10, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+  return a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+TEST(ActionPnMacroTest, CanExplicitlyInstantiateWithReferenceTypes) {
+  int x = 1, y = 2, z = 3;
+  const std::tuple<> empty = std::make_tuple();
+
+  Action<int()> a = Plus1<int&>(x);
+  EXPECT_EQ(1, a.Perform(empty));
+
+  a = Plus2<const int&, int&>(x, y);
+  EXPECT_EQ(3, a.Perform(empty));
+
+  a = Plus3<int&, const int&, int&>(x, y, z);
+  EXPECT_EQ(6, a.Perform(empty));
+
+  int n[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+  a = Plus10<const int&, int&, const int&, int&, const int&, int&, const int&,
+             int&, const int&, int&>(n[0], n[1], n[2], n[3], n[4], n[5], n[6],
+                                     n[7], n[8], n[9]);
+  EXPECT_EQ(55, a.Perform(empty));
+}
+
+class TenArgConstructorClass {
+ public:
+  TenArgConstructorClass(int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+                         int a8, int a9, int a10)
+      : value_(a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10) {}
+  int value_;
+};
+
+// Tests that ACTION_TEMPLATE works when there is no value parameter.
+ACTION_TEMPLATE(CreateNew, HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_0_VALUE_PARAMS()) {
+  return new T;
+}
+
+TEST(ActionTemplateTest, WorksWithoutValueParam) {
+  const Action<int*()> a = CreateNew<int>();
+  int* p = a.Perform(std::make_tuple());
+  delete p;
+}
+
+// Tests that ACTION_TEMPLATE works when there are value parameters.
+ACTION_TEMPLATE(CreateNew, HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_1_VALUE_PARAMS(a0)) {
+  return new T(a0);
+}
+
+TEST(ActionTemplateTest, WorksWithValueParams) {
+  const Action<int*()> a = CreateNew<int>(42);
+  int* p = a.Perform(std::make_tuple());
+  EXPECT_EQ(42, *p);
+  delete p;
+}
+
+// Tests that ACTION_TEMPLATE works for integral template parameters.
+ACTION_TEMPLATE(MyDeleteArg, HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  delete std::get<k>(args);
+}
+
+// Resets a bool variable in the destructor.
+class BoolResetter {
+ public:
+  explicit BoolResetter(bool* value) : value_(value) {}
+  ~BoolResetter() { *value_ = false; }
+
+ private:
+  bool* value_;
+};
+
+TEST(ActionTemplateTest, WorksForIntegralTemplateParams) {
+  const Action<void(int*, BoolResetter*)> a = MyDeleteArg<1>();
+  int n = 0;
+  bool b = true;
+  auto* resetter = new BoolResetter(&b);
+  a.Perform(std::make_tuple(&n, resetter));
+  EXPECT_FALSE(b);  // Verifies that resetter is deleted.
+}
+
+// Tests that ACTION_TEMPLATES works for template template parameters.
+ACTION_TEMPLATE(ReturnSmartPointer,
+                HAS_1_TEMPLATE_PARAMS(template <typename Pointee> class,
+                                      Pointer),
+                AND_1_VALUE_PARAMS(pointee)) {
+  return Pointer<pointee_type>(new pointee_type(pointee));
+}
+
+TEST(ActionTemplateTest, WorksForTemplateTemplateParameters) {
+  const Action<std::shared_ptr<int>()> a =
+      ReturnSmartPointer<std::shared_ptr>(42);
+  std::shared_ptr<int> p = a.Perform(std::make_tuple());
+  EXPECT_EQ(42, *p);
+}
+
+// Tests that ACTION_TEMPLATE works for 10 template parameters.
+template <typename T1, typename T2, typename T3, int k4, bool k5,
+          unsigned int k6, typename T7, typename T8, typename T9>
+struct GiantTemplate {
+ public:
+  explicit GiantTemplate(int a_value) : value(a_value) {}
+  int value;
+};
+
+ACTION_TEMPLATE(ReturnGiant,
+                HAS_10_TEMPLATE_PARAMS(typename, T1, typename, T2, typename, T3,
+                                       int, k4, bool, k5, unsigned int, k6,
+                                       class, T7, class, T8, class, T9,
+                                       template <typename T> class, T10),
+                AND_1_VALUE_PARAMS(value)) {
+  return GiantTemplate<T10<T1>, T2, T3, k4, k5, k6, T7, T8, T9>(value);
+}
+
+TEST(ActionTemplateTest, WorksFor10TemplateParameters) {
+  using Giant = GiantTemplate<std::shared_ptr<int>, bool, double, 5, true, 6,
+                              char, unsigned, int>;
+  const Action<Giant()> a = ReturnGiant<int, bool, double, 5, true, 6, char,
+                                        unsigned, int, std::shared_ptr>(42);
+  Giant giant = a.Perform(std::make_tuple());
+  EXPECT_EQ(42, giant.value);
+}
+
+// Tests that ACTION_TEMPLATE works for 10 value parameters.
+ACTION_TEMPLATE(ReturnSum, HAS_1_TEMPLATE_PARAMS(typename, Number),
+                AND_10_VALUE_PARAMS(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)) {
+  return static_cast<Number>(v1) + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10;
+}
+
+TEST(ActionTemplateTest, WorksFor10ValueParameters) {
+  const Action<int()> a = ReturnSum<int>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+  EXPECT_EQ(55, a.Perform(std::make_tuple()));
+}
+
+// Tests that ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded
+// on the number of value parameters.
+
+ACTION(ReturnSum) { return 0; }
+
+ACTION_P(ReturnSum, x) { return x; }
+
+ACTION_TEMPLATE(ReturnSum, HAS_1_TEMPLATE_PARAMS(typename, Number),
+                AND_2_VALUE_PARAMS(v1, v2)) {
+  return static_cast<Number>(v1) + v2;
+}
+
+ACTION_TEMPLATE(ReturnSum, HAS_1_TEMPLATE_PARAMS(typename, Number),
+                AND_3_VALUE_PARAMS(v1, v2, v3)) {
+  return static_cast<Number>(v1) + v2 + v3;
+}
+
+ACTION_TEMPLATE(ReturnSum, HAS_2_TEMPLATE_PARAMS(typename, Number, int, k),
+                AND_4_VALUE_PARAMS(v1, v2, v3, v4)) {
+  return static_cast<Number>(v1) + v2 + v3 + v4 + k;
+}
+
+TEST(ActionTemplateTest, CanBeOverloadedOnNumberOfValueParameters) {
+  const Action<int()> a0 = ReturnSum();
+  const Action<int()> a1 = ReturnSum(1);
+  const Action<int()> a2 = ReturnSum<int>(1, 2);
+  const Action<int()> a3 = ReturnSum<int>(1, 2, 3);
+  const Action<int()> a4 = ReturnSum<int, 10000>(2000, 300, 40, 5);
+  EXPECT_EQ(0, a0.Perform(std::make_tuple()));
+  EXPECT_EQ(1, a1.Perform(std::make_tuple()));
+  EXPECT_EQ(3, a2.Perform(std::make_tuple()));
+  EXPECT_EQ(6, a3.Perform(std::make_tuple()));
+  EXPECT_EQ(12345, a4.Perform(std::make_tuple()));
+}
+
+}  // namespace gmock_more_actions_test
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100 4503
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4577
diff --git a/3rd-party/googletest/googlemock/test/gmock-nice-strict_test.cc b/3rd-party/googletest/googlemock/test/gmock-nice-strict_test.cc
new file mode 100644
index 0000000..95f0969
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-nice-strict_test.cc
@@ -0,0 +1,541 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gmock/gmock-nice-strict.h"
+
+#include <string>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+// This must not be defined inside the ::testing namespace, or it will
+// clash with ::testing::Mock.
+class Mock {
+ public:
+  Mock() = default;
+
+  MOCK_METHOD0(DoThis, void());
+
+ private:
+  Mock(const Mock&) = delete;
+  Mock& operator=(const Mock&) = delete;
+};
+
+namespace testing {
+namespace gmock_nice_strict_test {
+
+using testing::HasSubstr;
+using testing::NaggyMock;
+using testing::NiceMock;
+using testing::StrictMock;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using testing::internal::CaptureStdout;
+using testing::internal::GetCapturedStdout;
+#endif
+
+// Class without default constructor.
+class NotDefaultConstructible {
+ public:
+  explicit NotDefaultConstructible(int) {}
+};
+
+class CallsMockMethodInDestructor {
+ public:
+  ~CallsMockMethodInDestructor() { OnDestroy(); }
+  MOCK_METHOD(void, OnDestroy, ());
+};
+
+// Defines some mock classes needed by the tests.
+
+class Foo {
+ public:
+  virtual ~Foo() = default;
+
+  virtual void DoThis() = 0;
+  virtual int DoThat(bool flag) = 0;
+};
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() = default;
+  void Delete() { delete this; }
+
+  MOCK_METHOD0(DoThis, void());
+  MOCK_METHOD1(DoThat, int(bool flag));
+  MOCK_METHOD0(ReturnNonDefaultConstructible, NotDefaultConstructible());
+
+ private:
+  MockFoo(const MockFoo&) = delete;
+  MockFoo& operator=(const MockFoo&) = delete;
+};
+
+class MockBar {
+ public:
+  explicit MockBar(const std::string& s) : str_(s) {}
+
+  MockBar(char a1, char a2, std::string a3, std::string a4, int a5, int a6,
+          const std::string& a7, const std::string& a8, bool a9, bool a10) {
+    str_ = std::string() + a1 + a2 + a3 + a4 + static_cast<char>(a5) +
+           static_cast<char>(a6) + a7 + a8 + (a9 ? 'T' : 'F') +
+           (a10 ? 'T' : 'F');
+  }
+
+  virtual ~MockBar() = default;
+
+  const std::string& str() const { return str_; }
+
+  MOCK_METHOD0(This, int());
+  MOCK_METHOD2(That, std::string(int, bool));
+
+ private:
+  std::string str_;
+
+  MockBar(const MockBar&) = delete;
+  MockBar& operator=(const MockBar&) = delete;
+};
+
+class MockBaz {
+ public:
+  class MoveOnly {
+   public:
+    MoveOnly() = default;
+
+    MoveOnly(const MoveOnly&) = delete;
+    MoveOnly& operator=(const MoveOnly&) = delete;
+
+    MoveOnly(MoveOnly&&) = default;
+    MoveOnly& operator=(MoveOnly&&) = default;
+  };
+
+  MockBaz(MoveOnly) {}
+};
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a raw mock generates warnings for uninteresting calls.
+TEST(RawMockTest, WarningForUninterestingCall) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "warning");
+
+  MockFoo raw_foo;
+
+  CaptureStdout();
+  raw_foo.DoThis();
+  raw_foo.DoThat(true);
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+// Tests that a raw mock generates warnings for uninteresting calls
+// that delete the mock object.
+TEST(RawMockTest, WarningForUninterestingCallAfterDeath) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "warning");
+
+  MockFoo* const raw_foo = new MockFoo;
+
+  ON_CALL(*raw_foo, DoThis()).WillByDefault(Invoke(raw_foo, &MockFoo::Delete));
+
+  CaptureStdout();
+  raw_foo->DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+// Tests that a raw mock generates informational logs for
+// uninteresting calls.
+TEST(RawMockTest, InfoForUninterestingCall) {
+  MockFoo raw_foo;
+
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "info");
+  CaptureStdout();
+  raw_foo.DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+TEST(RawMockTest, IsNaggy_IsNice_IsStrict) {
+  MockFoo raw_foo;
+  EXPECT_TRUE(Mock::IsNaggy(&raw_foo));
+  EXPECT_FALSE(Mock::IsNice(&raw_foo));
+  EXPECT_FALSE(Mock::IsStrict(&raw_foo));
+}
+
+// Tests that a nice mock generates no warning for uninteresting calls.
+TEST(NiceMockTest, NoWarningForUninterestingCall) {
+  NiceMock<MockFoo> nice_foo;
+
+  CaptureStdout();
+  nice_foo.DoThis();
+  nice_foo.DoThat(true);
+  EXPECT_EQ("", GetCapturedStdout());
+}
+
+// Tests that a nice mock generates no warning for uninteresting calls
+// that delete the mock object.
+TEST(NiceMockTest, NoWarningForUninterestingCallAfterDeath) {
+  NiceMock<MockFoo>* const nice_foo = new NiceMock<MockFoo>;
+
+  ON_CALL(*nice_foo, DoThis())
+      .WillByDefault(Invoke(nice_foo, &MockFoo::Delete));
+
+  CaptureStdout();
+  nice_foo->DoThis();
+  EXPECT_EQ("", GetCapturedStdout());
+}
+
+// Tests that a nice mock generates informational logs for
+// uninteresting calls.
+TEST(NiceMockTest, InfoForUninterestingCall) {
+  NiceMock<MockFoo> nice_foo;
+
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "info");
+  CaptureStdout();
+  nice_foo.DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a nice mock allows expected calls.
+TEST(NiceMockTest, AllowsExpectedCall) {
+  NiceMock<MockFoo> nice_foo;
+
+  EXPECT_CALL(nice_foo, DoThis());
+  nice_foo.DoThis();
+}
+
+// Tests that an unexpected call on a nice mock which returns a
+// not-default-constructible type throws an exception and the exception contains
+// the method's name.
+TEST(NiceMockTest, ThrowsExceptionForUnknownReturnTypes) {
+  NiceMock<MockFoo> nice_foo;
+#if GTEST_HAS_EXCEPTIONS
+  try {
+    nice_foo.ReturnNonDefaultConstructible();
+    FAIL();
+  } catch (const std::runtime_error& ex) {
+    EXPECT_THAT(ex.what(), HasSubstr("ReturnNonDefaultConstructible"));
+  }
+#else
+  EXPECT_DEATH_IF_SUPPORTED({ nice_foo.ReturnNonDefaultConstructible(); }, "");
+#endif
+}
+
+// Tests that an unexpected call on a nice mock fails.
+TEST(NiceMockTest, UnexpectedCallFails) {
+  NiceMock<MockFoo> nice_foo;
+
+  EXPECT_CALL(nice_foo, DoThis()).Times(0);
+  EXPECT_NONFATAL_FAILURE(nice_foo.DoThis(), "called more times than expected");
+}
+
+// Tests that NiceMock works with a mock class that has a non-default
+// constructor.
+TEST(NiceMockTest, NonDefaultConstructor) {
+  NiceMock<MockBar> nice_bar("hi");
+  EXPECT_EQ("hi", nice_bar.str());
+
+  nice_bar.This();
+  nice_bar.That(5, true);
+}
+
+// Tests that NiceMock works with a mock class that has a 10-ary
+// non-default constructor.
+TEST(NiceMockTest, NonDefaultConstructor10) {
+  NiceMock<MockBar> nice_bar('a', 'b', "c", "d", 'e', 'f', "g", "h", true,
+                             false);
+  EXPECT_EQ("abcdefghTF", nice_bar.str());
+
+  nice_bar.This();
+  nice_bar.That(5, true);
+}
+
+TEST(NiceMockTest, AllowLeak) {
+  NiceMock<MockFoo>* leaked = new NiceMock<MockFoo>;
+  Mock::AllowLeak(leaked);
+  EXPECT_CALL(*leaked, DoThis());
+  leaked->DoThis();
+}
+
+TEST(NiceMockTest, MoveOnlyConstructor) {
+  NiceMock<MockBaz> nice_baz(MockBaz::MoveOnly{});
+}
+
+// Tests that NiceMock<Mock> compiles where Mock is a user-defined
+// class (as opposed to ::testing::Mock).
+TEST(NiceMockTest, AcceptsClassNamedMock) {
+  NiceMock< ::Mock> nice;
+  EXPECT_CALL(nice, DoThis());
+  nice.DoThis();
+}
+
+TEST(NiceMockTest, IsNiceInDestructor) {
+  {
+    NiceMock<CallsMockMethodInDestructor> nice_on_destroy;
+    // Don't add an expectation for the call before the mock goes out of scope.
+  }
+}
+
+TEST(NiceMockTest, IsNaggy_IsNice_IsStrict) {
+  NiceMock<MockFoo> nice_foo;
+  EXPECT_FALSE(Mock::IsNaggy(&nice_foo));
+  EXPECT_TRUE(Mock::IsNice(&nice_foo));
+  EXPECT_FALSE(Mock::IsStrict(&nice_foo));
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a naggy mock generates warnings for uninteresting calls.
+TEST(NaggyMockTest, WarningForUninterestingCall) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "warning");
+
+  NaggyMock<MockFoo> naggy_foo;
+
+  CaptureStdout();
+  naggy_foo.DoThis();
+  naggy_foo.DoThat(true);
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+// Tests that a naggy mock generates a warning for an uninteresting call
+// that deletes the mock object.
+TEST(NaggyMockTest, WarningForUninterestingCallAfterDeath) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "warning");
+
+  NaggyMock<MockFoo>* const naggy_foo = new NaggyMock<MockFoo>;
+
+  ON_CALL(*naggy_foo, DoThis())
+      .WillByDefault(Invoke(naggy_foo, &MockFoo::Delete));
+
+  CaptureStdout();
+  naggy_foo->DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a naggy mock allows expected calls.
+TEST(NaggyMockTest, AllowsExpectedCall) {
+  NaggyMock<MockFoo> naggy_foo;
+
+  EXPECT_CALL(naggy_foo, DoThis());
+  naggy_foo.DoThis();
+}
+
+// Tests that an unexpected call on a naggy mock fails.
+TEST(NaggyMockTest, UnexpectedCallFails) {
+  NaggyMock<MockFoo> naggy_foo;
+
+  EXPECT_CALL(naggy_foo, DoThis()).Times(0);
+  EXPECT_NONFATAL_FAILURE(naggy_foo.DoThis(),
+                          "called more times than expected");
+}
+
+// Tests that NaggyMock works with a mock class that has a non-default
+// constructor.
+TEST(NaggyMockTest, NonDefaultConstructor) {
+  NaggyMock<MockBar> naggy_bar("hi");
+  EXPECT_EQ("hi", naggy_bar.str());
+
+  naggy_bar.This();
+  naggy_bar.That(5, true);
+}
+
+// Tests that NaggyMock works with a mock class that has a 10-ary
+// non-default constructor.
+TEST(NaggyMockTest, NonDefaultConstructor10) {
+  NaggyMock<MockBar> naggy_bar('0', '1', "2", "3", '4', '5', "6", "7", true,
+                               false);
+  EXPECT_EQ("01234567TF", naggy_bar.str());
+
+  naggy_bar.This();
+  naggy_bar.That(5, true);
+}
+
+TEST(NaggyMockTest, AllowLeak) {
+  NaggyMock<MockFoo>* leaked = new NaggyMock<MockFoo>;
+  Mock::AllowLeak(leaked);
+  EXPECT_CALL(*leaked, DoThis());
+  leaked->DoThis();
+}
+
+TEST(NaggyMockTest, MoveOnlyConstructor) {
+  NaggyMock<MockBaz> naggy_baz(MockBaz::MoveOnly{});
+}
+
+// Tests that NaggyMock<Mock> compiles where Mock is a user-defined
+// class (as opposed to ::testing::Mock).
+TEST(NaggyMockTest, AcceptsClassNamedMock) {
+  NaggyMock< ::Mock> naggy;
+  EXPECT_CALL(naggy, DoThis());
+  naggy.DoThis();
+}
+
+TEST(NaggyMockTest, IsNaggyInDestructor) {
+  const std::string saved_flag = GMOCK_FLAG_GET(verbose);
+  GMOCK_FLAG_SET(verbose, "warning");
+  CaptureStdout();
+
+  {
+    NaggyMock<CallsMockMethodInDestructor> naggy_on_destroy;
+    // Don't add an expectation for the call before the mock goes out of scope.
+  }
+
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG_SET(verbose, saved_flag);
+}
+
+TEST(NaggyMockTest, IsNaggy_IsNice_IsStrict) {
+  NaggyMock<MockFoo> naggy_foo;
+  EXPECT_TRUE(Mock::IsNaggy(&naggy_foo));
+  EXPECT_FALSE(Mock::IsNice(&naggy_foo));
+  EXPECT_FALSE(Mock::IsStrict(&naggy_foo));
+}
+
+// Tests that a strict mock allows expected calls.
+TEST(StrictMockTest, AllowsExpectedCall) {
+  StrictMock<MockFoo> strict_foo;
+
+  EXPECT_CALL(strict_foo, DoThis());
+  strict_foo.DoThis();
+}
+
+// Tests that an unexpected call on a strict mock fails.
+TEST(StrictMockTest, UnexpectedCallFails) {
+  StrictMock<MockFoo> strict_foo;
+
+  EXPECT_CALL(strict_foo, DoThis()).Times(0);
+  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
+                          "called more times than expected");
+}
+
+// Tests that an uninteresting call on a strict mock fails.
+TEST(StrictMockTest, UninterestingCallFails) {
+  StrictMock<MockFoo> strict_foo;
+
+  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
+                          "Uninteresting mock function call");
+}
+
+// Tests that an uninteresting call on a strict mock fails, even if
+// the call deletes the mock object.
+TEST(StrictMockTest, UninterestingCallFailsAfterDeath) {
+  StrictMock<MockFoo>* const strict_foo = new StrictMock<MockFoo>;
+
+  ON_CALL(*strict_foo, DoThis())
+      .WillByDefault(Invoke(strict_foo, &MockFoo::Delete));
+
+  EXPECT_NONFATAL_FAILURE(strict_foo->DoThis(),
+                          "Uninteresting mock function call");
+}
+
+// Tests that StrictMock works with a mock class that has a
+// non-default constructor.
+TEST(StrictMockTest, NonDefaultConstructor) {
+  StrictMock<MockBar> strict_bar("hi");
+  EXPECT_EQ("hi", strict_bar.str());
+
+  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
+                          "Uninteresting mock function call");
+}
+
+// Tests that StrictMock works with a mock class that has a 10-ary
+// non-default constructor.
+TEST(StrictMockTest, NonDefaultConstructor10) {
+  StrictMock<MockBar> strict_bar('a', 'b', "c", "d", 'e', 'f', "g", "h", true,
+                                 false);
+  EXPECT_EQ("abcdefghTF", strict_bar.str());
+
+  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
+                          "Uninteresting mock function call");
+}
+
+TEST(StrictMockTest, AllowLeak) {
+  StrictMock<MockFoo>* leaked = new StrictMock<MockFoo>;
+  Mock::AllowLeak(leaked);
+  EXPECT_CALL(*leaked, DoThis());
+  leaked->DoThis();
+}
+
+TEST(StrictMockTest, MoveOnlyConstructor) {
+  StrictMock<MockBaz> strict_baz(MockBaz::MoveOnly{});
+}
+
+// Tests that StrictMock<Mock> compiles where Mock is a user-defined
+// class (as opposed to ::testing::Mock).
+TEST(StrictMockTest, AcceptsClassNamedMock) {
+  StrictMock< ::Mock> strict;
+  EXPECT_CALL(strict, DoThis());
+  strict.DoThis();
+}
+
+TEST(StrictMockTest, IsStrictInDestructor) {
+  EXPECT_NONFATAL_FAILURE(
+      {
+        StrictMock<CallsMockMethodInDestructor> strict_on_destroy;
+        // Don't add an expectation for the call before the mock goes out of
+        // scope.
+      },
+      "Uninteresting mock function call");
+}
+
+TEST(StrictMockTest, IsNaggy_IsNice_IsStrict) {
+  StrictMock<MockFoo> strict_foo;
+  EXPECT_FALSE(Mock::IsNaggy(&strict_foo));
+  EXPECT_FALSE(Mock::IsNice(&strict_foo));
+  EXPECT_TRUE(Mock::IsStrict(&strict_foo));
+}
+
+}  // namespace gmock_nice_strict_test
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/test/gmock-port_test.cc b/3rd-party/googletest/googlemock/test/gmock-port_test.cc
new file mode 100644
index 0000000..c31af82
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-port_test.cc
@@ -0,0 +1,42 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the internal cross-platform support utilities.
+
+#include "gmock/internal/gmock-port.h"
+
+#include "gtest/gtest.h"
+
+// NOTE: if this file is left without tests for some reason, put a dummy
+// test here to make references to symbols in the gtest library and avoid
+// 'undefined symbol' linker errors in gmock_main:
+
+TEST(DummyTest, Dummy) {}
diff --git a/3rd-party/googletest/googlemock/test/gmock-pp-string_test.cc b/3rd-party/googletest/googlemock/test/gmock-pp-string_test.cc
new file mode 100644
index 0000000..53c80f4
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-pp-string_test.cc
@@ -0,0 +1,205 @@
+// Copyright 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the internal preprocessor macro library.
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-pp.h"
+
+namespace testing {
+namespace {
+
+// Matcher to verify that to strings are identical up to whitespace
+// Not 100% correct, because it treats "AB" as equal to "A B".
+::testing::Matcher<const std::string&> SameExceptSpaces(const std::string& s) {
+  auto remove_spaces = [](std::string to_split) {
+    to_split.erase(std::remove(to_split.begin(), to_split.end(), ' '),
+                   to_split.end());
+    return to_split;
+  };
+  return ::testing::ResultOf(remove_spaces, remove_spaces(s));
+}
+
+// Verify that a macro expands to a given text. Ignores whitespace difference.
+// In MSVC, GMOCK_PP_STRINGIZE() returns nothing, rather than "". So concatenate
+// with an empty string.
+#define EXPECT_EXPANSION(Result, Macro) \
+  EXPECT_THAT("" GMOCK_PP_STRINGIZE(Macro), SameExceptSpaces(Result))
+
+TEST(Macros, Cat) {
+  EXPECT_EXPANSION("14", GMOCK_PP_CAT(1, 4));
+  EXPECT_EXPANSION("+=", GMOCK_PP_CAT(+, =));
+}
+
+TEST(Macros, Narg) {
+  EXPECT_EXPANSION("1", GMOCK_PP_NARG());
+  EXPECT_EXPANSION("1", GMOCK_PP_NARG(x));
+  EXPECT_EXPANSION("2", GMOCK_PP_NARG(x, y));
+  EXPECT_EXPANSION("3", GMOCK_PP_NARG(x, y, z));
+  EXPECT_EXPANSION("4", GMOCK_PP_NARG(x, y, z, w));
+
+  EXPECT_EXPANSION("0", GMOCK_PP_NARG0());
+  EXPECT_EXPANSION("1", GMOCK_PP_NARG0(x));
+  EXPECT_EXPANSION("2", GMOCK_PP_NARG0(x, y));
+}
+
+TEST(Macros, Comma) {
+  EXPECT_EXPANSION("0", GMOCK_PP_HAS_COMMA());
+  EXPECT_EXPANSION("1", GMOCK_PP_HAS_COMMA(, ));
+  EXPECT_EXPANSION("0", GMOCK_PP_HAS_COMMA((, )));
+}
+
+TEST(Macros, IsEmpty) {
+  EXPECT_EXPANSION("1", GMOCK_PP_IS_EMPTY());
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_EMPTY(, ));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_EMPTY(a));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_EMPTY(()));
+
+#define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
+  EXPECT_EXPANSION("1", GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1));
+}
+
+TEST(Macros, If) {
+  EXPECT_EXPANSION("1", GMOCK_PP_IF(1, 1, 2));
+  EXPECT_EXPANSION("2", GMOCK_PP_IF(0, 1, 2));
+}
+
+TEST(Macros, HeadTail) {
+  EXPECT_EXPANSION("1", GMOCK_PP_HEAD(1));
+  EXPECT_EXPANSION("1", GMOCK_PP_HEAD(1, 2));
+  EXPECT_EXPANSION("1", GMOCK_PP_HEAD(1, 2, 3));
+
+  EXPECT_EXPANSION("", GMOCK_PP_TAIL(1));
+  EXPECT_EXPANSION("2", GMOCK_PP_TAIL(1, 2));
+  EXPECT_EXPANSION("2", GMOCK_PP_HEAD(GMOCK_PP_TAIL(1, 2, 3)));
+}
+
+TEST(Macros, Parentheses) {
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_BEGIN_PARENS(sss));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_BEGIN_PARENS(sss()));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_BEGIN_PARENS(sss() sss));
+  EXPECT_EXPANSION("1", GMOCK_PP_IS_BEGIN_PARENS((sss)));
+  EXPECT_EXPANSION("1", GMOCK_PP_IS_BEGIN_PARENS((sss)ss));
+
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_ENCLOSED_PARENS(sss));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_ENCLOSED_PARENS(sss()));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_ENCLOSED_PARENS(sss() sss));
+  EXPECT_EXPANSION("1", GMOCK_PP_IS_ENCLOSED_PARENS((sss)));
+  EXPECT_EXPANSION("0", GMOCK_PP_IS_ENCLOSED_PARENS((sss)ss));
+
+  EXPECT_EXPANSION("1 + 1", GMOCK_PP_REMOVE_PARENS((1 + 1)));
+}
+
+TEST(Macros, Increment) {
+  EXPECT_EXPANSION("1", GMOCK_PP_INC(0));
+  EXPECT_EXPANSION("2", GMOCK_PP_INC(1));
+  EXPECT_EXPANSION("3", GMOCK_PP_INC(2));
+  EXPECT_EXPANSION("4", GMOCK_PP_INC(3));
+  EXPECT_EXPANSION("5", GMOCK_PP_INC(4));
+
+  EXPECT_EXPANSION("16", GMOCK_PP_INC(15));
+}
+
+#define JOINER_CAT(a, b) a##b
+#define JOINER(_N, _Data, _Elem) JOINER_CAT(_Data, _N) = _Elem
+
+TEST(Macros, Repeat) {
+  EXPECT_EXPANSION("", GMOCK_PP_REPEAT(JOINER, X, 0));
+  EXPECT_EXPANSION("X0=", GMOCK_PP_REPEAT(JOINER, X, 1));
+  EXPECT_EXPANSION("X0= X1=", GMOCK_PP_REPEAT(JOINER, X, 2));
+  EXPECT_EXPANSION("X0= X1= X2=", GMOCK_PP_REPEAT(JOINER, X, 3));
+  EXPECT_EXPANSION("X0= X1= X2= X3=", GMOCK_PP_REPEAT(JOINER, X, 4));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4=", GMOCK_PP_REPEAT(JOINER, X, 5));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5=", GMOCK_PP_REPEAT(JOINER, X, 6));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6=",
+                   GMOCK_PP_REPEAT(JOINER, X, 7));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6= X7=",
+                   GMOCK_PP_REPEAT(JOINER, X, 8));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6= X7= X8=",
+                   GMOCK_PP_REPEAT(JOINER, X, 9));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6= X7= X8= X9=",
+                   GMOCK_PP_REPEAT(JOINER, X, 10));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6= X7= X8= X9= X10=",
+                   GMOCK_PP_REPEAT(JOINER, X, 11));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6= X7= X8= X9= X10= X11=",
+                   GMOCK_PP_REPEAT(JOINER, X, 12));
+  EXPECT_EXPANSION("X0= X1= X2= X3= X4= X5= X6= X7= X8= X9= X10= X11= X12=",
+                   GMOCK_PP_REPEAT(JOINER, X, 13));
+  EXPECT_EXPANSION(
+      "X0= X1= X2= X3= X4= X5= X6= X7= X8= X9= X10= X11= X12= X13=",
+      GMOCK_PP_REPEAT(JOINER, X, 14));
+  EXPECT_EXPANSION(
+      "X0= X1= X2= X3= X4= X5= X6= X7= X8= X9= X10= X11= X12= X13= X14=",
+      GMOCK_PP_REPEAT(JOINER, X, 15));
+}
+TEST(Macros, ForEach) {
+  EXPECT_EXPANSION("", GMOCK_PP_FOR_EACH(JOINER, X, ()));
+  EXPECT_EXPANSION("X0=a", GMOCK_PP_FOR_EACH(JOINER, X, (a)));
+  EXPECT_EXPANSION("X0=a X1=b", GMOCK_PP_FOR_EACH(JOINER, X, (a, b)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c", GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c X3=d",
+                   GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c X3=d X4=e",
+                   GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c X3=d X4=e X5=f",
+                   GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c X3=d X4=e X5=f X6=g",
+                   GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h",
+                   GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h)));
+  EXPECT_EXPANSION("X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i",
+                   GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h, i)));
+  EXPECT_EXPANSION(
+      "X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i X9=j",
+      GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h, i, j)));
+  EXPECT_EXPANSION(
+      "X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i X9=j X10=k",
+      GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h, i, j, k)));
+  EXPECT_EXPANSION(
+      "X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i X9=j X10=k X11=l",
+      GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h, i, j, k, l)));
+  EXPECT_EXPANSION(
+      "X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i X9=j X10=k X11=l X12=m",
+      GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h, i, j, k, l, m)));
+  EXPECT_EXPANSION(
+      "X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i X9=j X10=k X11=l X12=m "
+      "X13=n",
+      GMOCK_PP_FOR_EACH(JOINER, X, (a, b, c, d, e, f, g, h, i, j, k, l, m, n)));
+  EXPECT_EXPANSION(
+      "X0=a X1=b X2=c X3=d X4=e X5=f X6=g X7=h X8=i X9=j X10=k X11=l X12=m "
+      "X13=n X14=o",
+      GMOCK_PP_FOR_EACH(JOINER, X,
+                        (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)));
+}
+
+}  // namespace
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/test/gmock-pp_test.cc b/3rd-party/googletest/googlemock/test/gmock-pp_test.cc
new file mode 100644
index 0000000..5d1566e
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-pp_test.cc
@@ -0,0 +1,83 @@
+#include "gmock/internal/gmock-pp.h"
+
+// Used to test MSVC treating __VA_ARGS__ with a comma in it as one value
+#define GMOCK_TEST_REPLACE_comma_WITH_COMMA_I_comma ,
+#define GMOCK_TEST_REPLACE_comma_WITH_COMMA(x) \
+  GMOCK_PP_CAT(GMOCK_TEST_REPLACE_comma_WITH_COMMA_I_, x)
+
+// Static assertions.
+namespace testing {
+namespace internal {
+namespace gmockpp {
+
+static_assert(GMOCK_PP_CAT(1, 4) == 14, "");
+static_assert(GMOCK_PP_INTERNAL_INTERNAL_16TH(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+                                              12, 13, 14, 15, 16, 17, 18) == 16,
+              "");
+static_assert(GMOCK_PP_NARG() == 1, "");
+static_assert(GMOCK_PP_NARG(x) == 1, "");
+static_assert(GMOCK_PP_NARG(x, y) == 2, "");
+static_assert(GMOCK_PP_NARG(x, y, z) == 3, "");
+static_assert(GMOCK_PP_NARG(x, y, z, w) == 4, "");
+static_assert(!GMOCK_PP_HAS_COMMA(), "");
+static_assert(GMOCK_PP_HAS_COMMA(b, ), "");
+static_assert(!GMOCK_PP_HAS_COMMA((, )), "");
+static_assert(GMOCK_PP_HAS_COMMA(GMOCK_TEST_REPLACE_comma_WITH_COMMA(comma)),
+              "");
+static_assert(
+    GMOCK_PP_HAS_COMMA(GMOCK_TEST_REPLACE_comma_WITH_COMMA(comma(unrelated))),
+    "");
+static_assert(!GMOCK_PP_IS_EMPTY(, ), "");
+static_assert(!GMOCK_PP_IS_EMPTY(a), "");
+static_assert(!GMOCK_PP_IS_EMPTY(()), "");
+static_assert(GMOCK_PP_IF(1, 1, 2) == 1, "");
+static_assert(GMOCK_PP_IF(0, 1, 2) == 2, "");
+static_assert(GMOCK_PP_NARG0(x) == 1, "");
+static_assert(GMOCK_PP_NARG0(x, y) == 2, "");
+static_assert(GMOCK_PP_HEAD(1) == 1, "");
+static_assert(GMOCK_PP_HEAD(1, 2) == 1, "");
+static_assert(GMOCK_PP_HEAD(1, 2, 3) == 1, "");
+static_assert(GMOCK_PP_TAIL(1, 2) == 2, "");
+static_assert(GMOCK_PP_HEAD(GMOCK_PP_TAIL(1, 2, 3)) == 2, "");
+static_assert(!GMOCK_PP_IS_BEGIN_PARENS(sss), "");
+static_assert(!GMOCK_PP_IS_BEGIN_PARENS(sss()), "");
+static_assert(!GMOCK_PP_IS_BEGIN_PARENS(sss() sss), "");
+static_assert(GMOCK_PP_IS_BEGIN_PARENS((sss)), "");
+static_assert(GMOCK_PP_IS_BEGIN_PARENS((sss)ss), "");
+static_assert(!GMOCK_PP_IS_ENCLOSED_PARENS(sss), "");
+static_assert(!GMOCK_PP_IS_ENCLOSED_PARENS(sss()), "");
+static_assert(!GMOCK_PP_IS_ENCLOSED_PARENS(sss() sss), "");
+static_assert(!GMOCK_PP_IS_ENCLOSED_PARENS((sss)ss), "");
+static_assert(GMOCK_PP_REMOVE_PARENS((1 + 1)) * 2 == 3, "");
+static_assert(GMOCK_PP_INC(4) == 5, "");
+
+template <class... Args>
+struct Test {
+  static constexpr int kArgs = sizeof...(Args);
+};
+#define GMOCK_PP_INTERNAL_TYPE_TEST(_i, _Data, _element) \
+  GMOCK_PP_COMMA_IF(_i) _element
+static_assert(Test<GMOCK_PP_FOR_EACH(GMOCK_PP_INTERNAL_TYPE_TEST, ~,
+                                     (int, float, double, char))>::kArgs == 4,
+              "");
+#define GMOCK_PP_INTERNAL_VAR_TEST_1(_x) 1
+#define GMOCK_PP_INTERNAL_VAR_TEST_2(_x, _y) 2
+#define GMOCK_PP_INTERNAL_VAR_TEST_3(_x, _y, _z) 3
+
+#define GMOCK_PP_INTERNAL_VAR_TEST(...) \
+  GMOCK_PP_VARIADIC_CALL(GMOCK_PP_INTERNAL_VAR_TEST_, __VA_ARGS__)
+static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y) == 2, "");
+static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, "");
+static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, "");
+
+// TODO(iserna): The following asserts fail in --config=lexan.
+#define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
+static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), "");
+static_assert(GMOCK_PP_IS_EMPTY(), "");
+static_assert(GMOCK_PP_IS_ENCLOSED_PARENS((sss)), "");
+static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_TAIL(1)), "");
+static_assert(GMOCK_PP_NARG0() == 0, "");
+
+}  // namespace gmockpp
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googlemock/test/gmock-spec-builders_test.cc b/3rd-party/googletest/googlemock/test/gmock-spec-builders_test.cc
new file mode 100644
index 0000000..aaf88d7
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock-spec-builders_test.cc
@@ -0,0 +1,2600 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the spec builder syntax.
+
+#include "gmock/gmock-spec-builders.h"
+
+#include <memory>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace {
+
+using ::testing::internal::FormatFileLocation;
+using ::testing::internal::kAllow;
+using ::testing::internal::kErrorVerbosity;
+using ::testing::internal::kFail;
+using ::testing::internal::kInfoVerbosity;
+using ::testing::internal::kWarn;
+using ::testing::internal::kWarningVerbosity;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using ::testing::internal::CaptureStdout;
+using ::testing::internal::GetCapturedStdout;
+#endif
+
+class Incomplete;
+
+class MockIncomplete {
+ public:
+  // This line verifies that a mock method can take a by-reference
+  // argument of an incomplete type.
+  MOCK_METHOD1(ByRefFunc, void(const Incomplete& x));
+};
+
+// Tells Google Mock how to print a value of type Incomplete.
+void PrintTo(const Incomplete& x, ::std::ostream* os);
+
+TEST(MockMethodTest, CanInstantiateWithIncompleteArgType) {
+  // Even though this mock class contains a mock method that takes
+  // by-reference an argument whose type is incomplete, we can still
+  // use the mock, as long as Google Mock knows how to print the
+  // argument.
+  MockIncomplete incomplete;
+  EXPECT_CALL(incomplete, ByRefFunc(_)).Times(AnyNumber());
+}
+
+// The definition of the printer for the argument type doesn't have to
+// be visible where the mock is used.
+void PrintTo(const Incomplete& /* x */, ::std::ostream* os) {
+  *os << "incomplete";
+}
+
+class Result {};
+
+// A type that's not default constructible.
+class NonDefaultConstructible {
+ public:
+  explicit NonDefaultConstructible(int /* dummy */) {}
+};
+
+class MockA {
+ public:
+  MockA() = default;
+
+  MOCK_METHOD1(DoA, void(int n));
+  MOCK_METHOD1(ReturnResult, Result(int n));
+  MOCK_METHOD0(ReturnNonDefaultConstructible, NonDefaultConstructible());
+  MOCK_METHOD2(Binary, bool(int x, int y));
+  MOCK_METHOD2(ReturnInt, int(int x, int y));
+
+ private:
+  MockA(const MockA&) = delete;
+  MockA& operator=(const MockA&) = delete;
+};
+
+class MockB {
+ public:
+  MockB() = default;
+
+  MOCK_CONST_METHOD0(DoB, int());  // NOLINT
+  MOCK_METHOD1(DoB, int(int n));   // NOLINT
+
+ private:
+  MockB(const MockB&) = delete;
+  MockB& operator=(const MockB&) = delete;
+};
+
+class ReferenceHoldingMock {
+ public:
+  ReferenceHoldingMock() = default;
+
+  MOCK_METHOD1(AcceptReference, void(std::shared_ptr<MockA>*));
+
+ private:
+  ReferenceHoldingMock(const ReferenceHoldingMock&) = delete;
+  ReferenceHoldingMock& operator=(const ReferenceHoldingMock&) = delete;
+};
+
+// Tests that EXPECT_CALL and ON_CALL compile in a presence of macro
+// redefining a mock method name. This could happen, for example, when
+// the tested code #includes Win32 API headers which define many APIs
+// as macros, e.g. #define TextOut TextOutW.
+
+#define Method MethodW
+
+class CC {
+ public:
+  virtual ~CC() = default;
+  virtual int Method() = 0;
+};
+class MockCC : public CC {
+ public:
+  MockCC() = default;
+
+  MOCK_METHOD0(Method, int());
+
+ private:
+  MockCC(const MockCC&) = delete;
+  MockCC& operator=(const MockCC&) = delete;
+};
+
+// Tests that a method with expanded name compiles.
+TEST(OnCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  ON_CALL(cc, Method());
+}
+
+// Tests that the method with expanded name not only compiles but runs
+// and returns a correct value, too.
+TEST(OnCallSyntaxTest, WorksWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  ON_CALL(cc, Method()).WillByDefault(Return(42));
+  EXPECT_EQ(42, cc.Method());
+}
+
+// Tests that a method with expanded name compiles.
+TEST(ExpectCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  EXPECT_CALL(cc, Method());
+  cc.Method();
+}
+
+// Tests that it works, too.
+TEST(ExpectCallSyntaxTest, WorksWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  EXPECT_CALL(cc, Method()).WillOnce(Return(42));
+  EXPECT_EQ(42, cc.Method());
+}
+
+#undef Method  // Done with macro redefinition tests.
+
+// Tests that ON_CALL evaluates its arguments exactly once as promised
+// by Google Mock.
+TEST(OnCallSyntaxTest, EvaluatesFirstArgumentOnce) {
+  MockA a;
+  MockA* pa = &a;
+
+  ON_CALL(*pa++, DoA(_));
+  EXPECT_EQ(&a + 1, pa);
+}
+
+TEST(OnCallSyntaxTest, EvaluatesSecondArgumentOnce) {
+  MockA a;
+  int n = 0;
+
+  ON_CALL(a, DoA(n++));
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the syntax of ON_CALL() is enforced at run time.
+
+TEST(OnCallSyntaxTest, WithIsOptional) {
+  MockA a;
+
+  ON_CALL(a, DoA(5)).WillByDefault(Return());
+  ON_CALL(a, DoA(_)).With(_).WillByDefault(Return());
+}
+
+TEST(OnCallSyntaxTest, WithCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        ON_CALL(a, ReturnResult(_))
+            .With(_)
+            .With(_)
+            .WillByDefault(Return(Result()));
+      },
+      ".With() cannot appear more than once in an ON_CALL()");
+}
+
+TEST(OnCallSyntaxTest, WillByDefaultIsMandatory) {
+  MockA a;
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        ON_CALL(a, DoA(5));
+        a.DoA(5);
+      },
+      "");
+}
+
+TEST(OnCallSyntaxTest, WillByDefaultCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        ON_CALL(a, DoA(5)).WillByDefault(Return()).WillByDefault(Return());
+      },
+      ".WillByDefault() must appear exactly once in an ON_CALL()");
+}
+
+// Tests that EXPECT_CALL evaluates its arguments exactly once as
+// promised by Google Mock.
+TEST(ExpectCallSyntaxTest, EvaluatesFirstArgumentOnce) {
+  MockA a;
+  MockA* pa = &a;
+
+  EXPECT_CALL(*pa++, DoA(_));
+  a.DoA(0);
+  EXPECT_EQ(&a + 1, pa);
+}
+
+TEST(ExpectCallSyntaxTest, EvaluatesSecondArgumentOnce) {
+  MockA a;
+  int n = 0;
+
+  EXPECT_CALL(a, DoA(n++));
+  a.DoA(0);
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the syntax of EXPECT_CALL() is enforced at run time.
+
+TEST(ExpectCallSyntaxTest, WithIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(5)).Times(0);
+  EXPECT_CALL(a, DoA(6)).With(_).Times(0);
+}
+
+TEST(ExpectCallSyntaxTest, WithCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(6)).With(_).With(_);
+      },
+      ".With() cannot appear more than once in an EXPECT_CALL()");
+
+  a.DoA(6);
+}
+
+TEST(ExpectCallSyntaxTest, WithMustBeFirstClause) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).Times(1).With(_);
+      },
+      ".With() must be the first clause in an EXPECT_CALL()");
+
+  a.DoA(1);
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(2)).WillOnce(Return()).With(_);
+      },
+      ".With() must be the first clause in an EXPECT_CALL()");
+
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, TimesCanBeInferred) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1)).WillOnce(Return());
+
+  EXPECT_CALL(a, DoA(2)).WillOnce(Return()).WillRepeatedly(Return());
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, TimesCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).Times(1).Times(2);
+      },
+      ".Times() cannot appear more than once in an EXPECT_CALL()");
+
+  a.DoA(1);
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, TimesMustBeBeforeInSequence) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).InSequence(s).Times(1);
+      },
+      ".Times() may only appear *before* ");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceIsOptional) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(2)).InSequence(s);
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceCanAppearMultipleTimes) {
+  MockA a;
+  Sequence s1, s2;
+
+  EXPECT_CALL(a, DoA(1)).InSequence(s1, s2).InSequence(s1);
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeAfter) {
+  MockA a;
+  Sequence s;
+
+  Expectation e = EXPECT_CALL(a, DoA(1)).Times(AnyNumber());
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(2)).After(e).InSequence(s);
+      },
+      ".InSequence() cannot appear after ");
+
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeWillOnce) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).WillOnce(Return()).InSequence(s);
+      },
+      ".InSequence() cannot appear after ");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, AfterMustBeBeforeWillOnce) {
+  MockA a;
+
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  EXPECT_NONFATAL_FAILURE(
+      { EXPECT_CALL(a, DoA(2)).WillOnce(Return()).After(e); },
+      ".After() cannot appear after ");
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, WillIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(2)).WillOnce(Return());
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, WillCanAppearMultipleTimes) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1))
+      .Times(AnyNumber())
+      .WillOnce(Return())
+      .WillOnce(Return())
+      .WillOnce(Return());
+}
+
+TEST(ExpectCallSyntaxTest, WillMustBeBeforeWillRepeatedly) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).WillRepeatedly(Return()).WillOnce(Return());
+      },
+      ".WillOnce() cannot appear after ");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, WillRepeatedlyIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1)).WillOnce(Return());
+  EXPECT_CALL(a, DoA(2)).WillOnce(Return()).WillRepeatedly(Return());
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, WillRepeatedlyCannotAppearMultipleTimes) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).WillRepeatedly(Return()).WillRepeatedly(
+            Return());
+      },
+      ".WillRepeatedly() cannot appear more than once in an "
+      "EXPECT_CALL()");
+}
+
+TEST(ExpectCallSyntaxTest, WillRepeatedlyMustBeBeforeRetiresOnSaturation) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).RetiresOnSaturation().WillRepeatedly(Return());
+      },
+      ".WillRepeatedly() cannot appear after ");
+}
+
+TEST(ExpectCallSyntaxTest, RetiresOnSaturationIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(1)).RetiresOnSaturation();
+
+  a.DoA(1);
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, RetiresOnSaturationCannotAppearMultipleTimes) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_CALL(a, DoA(1)).RetiresOnSaturation().RetiresOnSaturation();
+      },
+      ".RetiresOnSaturation() cannot appear more than once");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, DefaultCardinalityIsOnce) {
+  {
+    MockA a;
+    EXPECT_CALL(a, DoA(1));
+    a.DoA(1);
+  }
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        MockA a;
+        EXPECT_CALL(a, DoA(1));
+      },
+      "to be called once");
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        MockA a;
+        EXPECT_CALL(a, DoA(1));
+        a.DoA(1);
+        a.DoA(1);
+      },
+      "to be called once");
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that Google Mock doesn't print a warning when the number of
+// WillOnce() is adequate.
+TEST(ExpectCallSyntaxTest, DoesNotWarnOnAdequateActionCount) {
+  CaptureStdout();
+  {
+    MockB b;
+
+    // It's always fine to omit WillOnce() entirely.
+    EXPECT_CALL(b, DoB()).Times(0);
+    EXPECT_CALL(b, DoB(1)).Times(AtMost(1));
+    EXPECT_CALL(b, DoB(2)).Times(1).WillRepeatedly(Return(1));
+
+    // It's fine for the number of WillOnce()s to equal the upper bound.
+    EXPECT_CALL(b, DoB(3))
+        .Times(Between(1, 2))
+        .WillOnce(Return(1))
+        .WillOnce(Return(2));
+
+    // It's fine for the number of WillOnce()s to be smaller than the
+    // upper bound when there is a WillRepeatedly().
+    EXPECT_CALL(b, DoB(4)).Times(AtMost(3)).WillOnce(Return(1)).WillRepeatedly(
+        Return(2));
+
+    // Satisfies the above expectations.
+    b.DoB(2);
+    b.DoB(3);
+  }
+  EXPECT_STREQ("", GetCapturedStdout().c_str());
+}
+
+// Tests that Google Mock warns on having too many actions in an
+// expectation compared to its cardinality.
+TEST(ExpectCallSyntaxTest, WarnsOnTooManyActions) {
+  CaptureStdout();
+  {
+    MockB b;
+
+    // Warns when the number of WillOnce()s is larger than the upper bound.
+    EXPECT_CALL(b, DoB()).Times(0).WillOnce(Return(1));  // #1
+    EXPECT_CALL(b, DoB()).Times(AtMost(1)).WillOnce(Return(1)).WillOnce(
+        Return(2));  // #2
+    EXPECT_CALL(b, DoB(1))
+        .Times(1)
+        .WillOnce(Return(1))
+        .WillOnce(Return(2))
+        .RetiresOnSaturation();  // #3
+
+    // Warns when the number of WillOnce()s equals the upper bound and
+    // there is a WillRepeatedly().
+    EXPECT_CALL(b, DoB()).Times(0).WillRepeatedly(Return(1));  // #4
+    EXPECT_CALL(b, DoB(2)).Times(1).WillOnce(Return(1)).WillRepeatedly(
+        Return(2));  // #5
+
+    // Satisfies the above expectations.
+    b.DoB(1);
+    b.DoB(2);
+  }
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring,
+                      "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
+                      "Expected to be never called, but has 1 WillOnce().",
+                      output);  // #1
+  EXPECT_PRED_FORMAT2(IsSubstring,
+                      "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
+                      "Expected to be called at most once, "
+                      "but has 2 WillOnce()s.",
+                      output);  // #2
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB(1))...\n"
+      "Expected to be called once, but has 2 WillOnce()s.",
+      output);  // #3
+  EXPECT_PRED_FORMAT2(IsSubstring,
+                      "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
+                      "Expected to be never called, but has 0 WillOnce()s "
+                      "and a WillRepeatedly().",
+                      output);  // #4
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB(2))...\n"
+      "Expected to be called once, but has 1 WillOnce() "
+      "and a WillRepeatedly().",
+      output);  // #5
+}
+
+// Tests that Google Mock warns on having too few actions in an
+// expectation compared to its cardinality.
+TEST(ExpectCallSyntaxTest, WarnsOnTooFewActions) {
+  MockB b;
+
+  EXPECT_CALL(b, DoB()).Times(Between(2, 3)).WillOnce(Return(1));
+
+  CaptureStdout();
+  b.DoB();
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring,
+                      "Too few actions specified in EXPECT_CALL(b, DoB())...\n"
+                      "Expected to be called between 2 and 3 times, "
+                      "but has only 1 WillOnce().",
+                      output);
+  b.DoB();
+}
+
+TEST(ExpectCallSyntaxTest, WarningIsErrorWithFlag) {
+  int original_behavior = GMOCK_FLAG_GET(default_mock_behavior);
+
+  GMOCK_FLAG_SET(default_mock_behavior, kAllow);
+  CaptureStdout();
+  {
+    MockA a;
+    a.DoA(0);
+  }
+  std::string output = GetCapturedStdout();
+  EXPECT_TRUE(output.empty()) << output;
+
+  GMOCK_FLAG_SET(default_mock_behavior, kWarn);
+  CaptureStdout();
+  {
+    MockA a;
+    a.DoA(0);
+  }
+  std::string warning_output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", warning_output);
+  EXPECT_PRED_FORMAT2(IsSubstring, "Uninteresting mock function call",
+                      warning_output);
+
+  GMOCK_FLAG_SET(default_mock_behavior, kFail);
+  EXPECT_NONFATAL_FAILURE(
+      {
+        MockA a;
+        a.DoA(0);
+      },
+      "Uninteresting mock function call");
+
+  // Out of bounds values are converted to kWarn
+  GMOCK_FLAG_SET(default_mock_behavior, -1);
+  CaptureStdout();
+  {
+    MockA a;
+    a.DoA(0);
+  }
+  warning_output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", warning_output);
+  EXPECT_PRED_FORMAT2(IsSubstring, "Uninteresting mock function call",
+                      warning_output);
+  GMOCK_FLAG_SET(default_mock_behavior, 3);
+  CaptureStdout();
+  {
+    MockA a;
+    a.DoA(0);
+  }
+  warning_output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", warning_output);
+  EXPECT_PRED_FORMAT2(IsSubstring, "Uninteresting mock function call",
+                      warning_output);
+
+  GMOCK_FLAG_SET(default_mock_behavior, original_behavior);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests the semantics of ON_CALL().
+
+// Tests that the built-in default action is taken when no ON_CALL()
+// is specified.
+TEST(OnCallTest, TakesBuiltInDefaultActionWhenNoOnCall) {
+  MockB b;
+  EXPECT_CALL(b, DoB());
+
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that the built-in default action is taken when no ON_CALL()
+// matches the invocation.
+TEST(OnCallTest, TakesBuiltInDefaultActionWhenNoOnCallMatches) {
+  MockB b;
+  ON_CALL(b, DoB(1)).WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(_));
+
+  EXPECT_EQ(0, b.DoB(2));
+}
+
+// Tests that the last matching ON_CALL() action is taken.
+TEST(OnCallTest, PicksLastMatchingOnCall) {
+  MockB b;
+  ON_CALL(b, DoB(_)).WillByDefault(Return(3));
+  ON_CALL(b, DoB(2)).WillByDefault(Return(2));
+  ON_CALL(b, DoB(1)).WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(_));
+
+  EXPECT_EQ(2, b.DoB(2));
+}
+
+// Tests the semantics of EXPECT_CALL().
+
+// Tests that any call is allowed when no EXPECT_CALL() is specified.
+TEST(ExpectCallTest, AllowsAnyCallWhenNoSpec) {
+  MockB b;
+  EXPECT_CALL(b, DoB());
+  // There is no expectation on DoB(int).
+
+  b.DoB();
+
+  // DoB(int) can be called any number of times.
+  b.DoB(1);
+  b.DoB(2);
+}
+
+// Tests that the last matching EXPECT_CALL() fires.
+TEST(ExpectCallTest, PicksLastMatchingExpectCall) {
+  MockB b;
+  EXPECT_CALL(b, DoB(_)).WillRepeatedly(Return(2));
+  EXPECT_CALL(b, DoB(1)).WillRepeatedly(Return(1));
+
+  EXPECT_EQ(1, b.DoB(1));
+}
+
+// Tests lower-bound violation.
+TEST(ExpectCallTest, CatchesTooFewCalls) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        MockB b;
+        EXPECT_CALL(b, DoB(5)).Description("DoB Method").Times(AtLeast(2));
+
+        b.DoB(5);
+      },
+      "Actual function \"DoB Method\" call count "
+      "doesn't match EXPECT_CALL(b, DoB(5))...\n"
+      "         Expected: to be called at least twice\n"
+      "           Actual: called once - unsatisfied and active");
+}
+
+// Tests that the cardinality can be inferred when no Times(...) is
+// specified.
+TEST(ExpectCallTest, InfersCardinalityWhenThereIsNoWillRepeatedly) {
+  {
+    MockB b;
+    EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillOnce(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+  }
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        MockB b;
+        EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillOnce(Return(2));
+
+        EXPECT_EQ(1, b.DoB());
+      },
+      "to be called twice");
+
+  {  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillOnce(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+    EXPECT_NONFATAL_FAILURE(b.DoB(), "to be called twice");
+  }
+}
+
+TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
+  {
+    MockB b;
+    EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillRepeatedly(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+  }
+
+  {  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillRepeatedly(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+  }
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        MockB b;
+        EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillRepeatedly(Return(2));
+      },
+      "to be called at least once");
+}
+
+#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
+    GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
+// It should be possible to return a non-moveable type from a mock action in
+// C++17 and above, where it's guaranteed that such a type can be initialized
+// from a prvalue returned from a function.
+TEST(ExpectCallTest, NonMoveableType) {
+  // Define a non-moveable result type.
+  struct NonMoveableStruct {
+    explicit NonMoveableStruct(int x_in) : x(x_in) {}
+    NonMoveableStruct(NonMoveableStruct&&) = delete;
+
+    int x;
+  };
+
+  static_assert(!std::is_move_constructible_v<NonMoveableStruct>);
+  static_assert(!std::is_copy_constructible_v<NonMoveableStruct>);
+
+  static_assert(!std::is_move_assignable_v<NonMoveableStruct>);
+  static_assert(!std::is_copy_assignable_v<NonMoveableStruct>);
+
+  // We should be able to use a callable that returns that result as both a
+  // OnceAction and an Action, whether the callable ignores arguments or not.
+  const auto return_17 = [] { return NonMoveableStruct(17); };
+
+  static_cast<void>(OnceAction<NonMoveableStruct()>{return_17});
+  static_cast<void>(Action<NonMoveableStruct()>{return_17});
+
+  static_cast<void>(OnceAction<NonMoveableStruct(int)>{return_17});
+  static_cast<void>(Action<NonMoveableStruct(int)>{return_17});
+
+  // It should be possible to return the result end to end through an
+  // EXPECT_CALL statement, with both WillOnce and WillRepeatedly.
+  MockFunction<NonMoveableStruct()> mock;
+  EXPECT_CALL(mock, Call)   //
+      .WillOnce(return_17)  //
+      .WillRepeatedly(return_17);
+
+  EXPECT_EQ(17, mock.AsStdFunction()().x);
+  EXPECT_EQ(17, mock.AsStdFunction()().x);
+  EXPECT_EQ(17, mock.AsStdFunction()().x);
+}
+
+#endif  // C++17 and above
+
+// Tests that the n-th action is taken for the n-th matching
+// invocation.
+TEST(ExpectCallTest, NthMatchTakesNthAction) {
+  MockB b;
+  EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillOnce(Return(2)).WillOnce(
+      Return(3));
+
+  EXPECT_EQ(1, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+  EXPECT_EQ(3, b.DoB());
+}
+
+// Tests that the WillRepeatedly() action is taken when the WillOnce(...)
+// list is exhausted.
+TEST(ExpectCallTest, TakesRepeatedActionWhenWillListIsExhausted) {
+  MockB b;
+  EXPECT_CALL(b, DoB()).WillOnce(Return(1)).WillRepeatedly(Return(2));
+
+  EXPECT_EQ(1, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that the default action is taken when the WillOnce(...) list is
+// exhausted and there is no WillRepeatedly().
+TEST(ExpectCallTest, TakesDefaultActionWhenWillListIsExhausted) {
+  MockB b;
+  EXPECT_CALL(b, DoB(_)).Times(1);
+  EXPECT_CALL(b, DoB())
+      .Times(AnyNumber())
+      .WillOnce(Return(1))
+      .WillOnce(Return(2));
+
+  CaptureStdout();
+  EXPECT_EQ(0, b.DoB(1));  // Shouldn't generate a warning as the
+                           // expectation has no action clause at all.
+  EXPECT_EQ(1, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+  const std::string output1 = GetCapturedStdout();
+  EXPECT_STREQ("", output1.c_str());
+
+  CaptureStdout();
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB());
+  const std::string output2 = GetCapturedStdout();
+  EXPECT_THAT(output2.c_str(),
+              HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n"
+                        "Called 3 times, but only 2 WillOnce()s are specified"
+                        " - returning default value."));
+  EXPECT_THAT(output2.c_str(),
+              HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n"
+                        "Called 4 times, but only 2 WillOnce()s are specified"
+                        " - returning default value."));
+}
+
+TEST(FunctionMockerMessageTest, ReportsExpectCallLocationForExhaustedActions) {
+  MockB b;
+  std::string expect_call_location = FormatFileLocation(__FILE__, __LINE__ + 1);
+  EXPECT_CALL(b, DoB()).Times(AnyNumber()).WillOnce(Return(1));
+
+  EXPECT_EQ(1, b.DoB());
+
+  CaptureStdout();
+  EXPECT_EQ(0, b.DoB());
+  const std::string output = GetCapturedStdout();
+  // The warning message should contain the call location.
+  EXPECT_PRED_FORMAT2(IsSubstring, expect_call_location, output);
+}
+
+TEST(FunctionMockerMessageTest,
+     ReportsDefaultActionLocationOfUninterestingCallsForNaggyMock) {
+  std::string on_call_location;
+  CaptureStdout();
+  {
+    NaggyMock<MockB> b;
+    on_call_location = FormatFileLocation(__FILE__, __LINE__ + 1);
+    ON_CALL(b, DoB(_)).WillByDefault(Return(0));
+    b.DoB(0);
+  }
+  EXPECT_PRED_FORMAT2(IsSubstring, on_call_location, GetCapturedStdout());
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that an uninteresting call performs the default action.
+TEST(UninterestingCallTest, DoesDefaultAction) {
+  // When there is an ON_CALL() statement, the action specified by it
+  // should be taken.
+  MockA a;
+  ON_CALL(a, Binary(_, _)).WillByDefault(Return(true));
+  EXPECT_TRUE(a.Binary(1, 2));
+
+  // When there is no ON_CALL(), the default value for the return type
+  // should be returned.
+  MockB b;
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that an unexpected call performs the default action.
+TEST(UnexpectedCallTest, DoesDefaultAction) {
+  // When there is an ON_CALL() statement, the action specified by it
+  // should be taken.
+  MockA a;
+  ON_CALL(a, Binary(_, _)).WillByDefault(Return(true));
+  EXPECT_CALL(a, Binary(0, 0));
+  a.Binary(0, 0);
+  bool result = false;
+  EXPECT_NONFATAL_FAILURE(result = a.Binary(1, 2),
+                          "Unexpected mock function call");
+  EXPECT_TRUE(result);
+
+  // When there is no ON_CALL(), the default value for the return type
+  // should be returned.
+  MockB b;
+  EXPECT_CALL(b, DoB(0)).Times(0);
+  int n = -1;
+  EXPECT_NONFATAL_FAILURE(n = b.DoB(1), "Unexpected mock function call");
+  EXPECT_EQ(0, n);
+}
+
+// Tests that when an unexpected void function generates the right
+// failure message.
+TEST(UnexpectedCallTest, GeneratesFailureForVoidFunction) {
+  // First, tests the message when there is only one EXPECT_CALL().
+  MockA a1;
+  EXPECT_CALL(a1, DoA(1));
+  a1.DoA(1);
+  // Ideally we should match the failure message against a regex, but
+  // EXPECT_NONFATAL_FAILURE doesn't support that, so we test for
+  // multiple sub-strings instead.
+  EXPECT_NONFATAL_FAILURE(
+      a1.DoA(9),
+      "Unexpected mock function call - returning directly.\n"
+      "    Function call: DoA(9)\n"
+      "Google Mock tried the following 1 expectation, but it didn't match:");
+  EXPECT_NONFATAL_FAILURE(
+      a1.DoA(9),
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 9\n"
+      "         Expected: to be called once\n"
+      "           Actual: called once - saturated and active");
+
+  // Next, tests the message when there are more than one EXPECT_CALL().
+  MockA a2;
+  EXPECT_CALL(a2, DoA(1));
+  EXPECT_CALL(a2, DoA(3));
+  a2.DoA(1);
+  EXPECT_NONFATAL_FAILURE(
+      a2.DoA(2),
+      "Unexpected mock function call - returning directly.\n"
+      "    Function call: DoA(2)\n"
+      "Google Mock tried the following 2 expectations, but none matched:");
+  EXPECT_NONFATAL_FAILURE(
+      a2.DoA(2),
+      "tried expectation #0: EXPECT_CALL(a2, DoA(1))...\n"
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 2\n"
+      "         Expected: to be called once\n"
+      "           Actual: called once - saturated and active");
+  EXPECT_NONFATAL_FAILURE(
+      a2.DoA(2),
+      "tried expectation #1: EXPECT_CALL(a2, DoA(3))...\n"
+      "  Expected arg #0: is equal to 3\n"
+      "           Actual: 2\n"
+      "         Expected: to be called once\n"
+      "           Actual: never called - unsatisfied and active");
+  a2.DoA(3);
+}
+
+// Tests that an unexpected non-void function generates the right
+// failure message.
+TEST(UnexpectedCallTest, GeneartesFailureForNonVoidFunction) {
+  MockB b1;
+  EXPECT_CALL(b1, DoB(1));
+  b1.DoB(1);
+  EXPECT_NONFATAL_FAILURE(
+      b1.DoB(2),
+      "Unexpected mock function call - returning default value.\n"
+      "    Function call: DoB(2)\n"
+      "          Returns: 0\n"
+      "Google Mock tried the following 1 expectation, but it didn't match:");
+  EXPECT_NONFATAL_FAILURE(
+      b1.DoB(2),
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 2\n"
+      "         Expected: to be called once\n"
+      "           Actual: called once - saturated and active");
+}
+
+// Tests that Google Mock explains that an retired expectation doesn't
+// match the call.
+TEST(UnexpectedCallTest, RetiredExpectation) {
+  MockB b;
+  EXPECT_CALL(b, DoB(1)).RetiresOnSaturation();
+
+  b.DoB(1);
+  EXPECT_NONFATAL_FAILURE(b.DoB(1),
+                          "         Expected: the expectation is active\n"
+                          "           Actual: it is retired");
+}
+
+// Tests that Google Mock explains that an expectation that doesn't
+// match the arguments doesn't match the call.
+TEST(UnexpectedCallTest, UnmatchedArguments) {
+  MockB b;
+  EXPECT_CALL(b, DoB(1));
+
+  EXPECT_NONFATAL_FAILURE(b.DoB(2),
+                          "  Expected arg #0: is equal to 1\n"
+                          "           Actual: 2\n");
+  b.DoB(1);
+}
+
+// Tests that Google Mock explains that an expectation with
+// unsatisfied pre-requisites doesn't match the call.
+TEST(UnexpectedCallTest, UnsatisfiedPrerequisites) {
+  Sequence s1, s2;
+  MockB b;
+  EXPECT_CALL(b, DoB(1)).InSequence(s1);
+  EXPECT_CALL(b, DoB(2)).Times(AnyNumber()).InSequence(s1);
+  EXPECT_CALL(b, DoB(3)).InSequence(s2);
+  EXPECT_CALL(b, DoB(4)).InSequence(s1, s2);
+
+  ::testing::TestPartResultArray failures;
+  {
+    ::testing::ScopedFakeTestPartResultReporter reporter(&failures);
+    b.DoB(4);
+    // Now 'failures' contains the Google Test failures generated by
+    // the above statement.
+  }
+
+  // There should be one non-fatal failure.
+  ASSERT_EQ(1, failures.size());
+  const ::testing::TestPartResult& r = failures.GetTestPartResult(0);
+  EXPECT_EQ(::testing::TestPartResult::kNonFatalFailure, r.type());
+
+  // Verifies that the failure message contains the two unsatisfied
+  // pre-requisites but not the satisfied one.
+#ifdef GTEST_USES_POSIX_RE
+  EXPECT_THAT(r.message(),
+              ContainsRegex(
+                  // POSIX RE doesn't understand the (?s) prefix, but has no
+                  // trouble with (.|\n).
+                  "the following immediate pre-requisites are not satisfied:\n"
+                  "(.|\n)*: pre-requisite #0\n"
+                  "(.|\n)*: pre-requisite #1"));
+#else
+  // We can only use Google Test's own simple regex.
+  EXPECT_THAT(r.message(),
+              ContainsRegex(
+                  "the following immediate pre-requisites are not satisfied:"));
+  EXPECT_THAT(r.message(), ContainsRegex(": pre-requisite #0"));
+  EXPECT_THAT(r.message(), ContainsRegex(": pre-requisite #1"));
+#endif  // GTEST_USES_POSIX_RE
+
+  b.DoB(1);
+  b.DoB(3);
+  b.DoB(4);
+}
+
+TEST(UndefinedReturnValueTest,
+     ReturnValueIsMandatoryWhenNotDefaultConstructible) {
+  MockA a;
+  // FIXME: We should really verify the output message,
+  // but we cannot yet due to that EXPECT_DEATH only captures stderr
+  // while Google Mock logs to stdout.
+#if GTEST_HAS_EXCEPTIONS
+  EXPECT_ANY_THROW(a.ReturnNonDefaultConstructible());
+#else
+  EXPECT_DEATH_IF_SUPPORTED(a.ReturnNonDefaultConstructible(), "");
+#endif
+}
+
+// Tests that an excessive call (one whose arguments match the
+// matchers but is called too many times) performs the default action.
+TEST(ExcessiveCallTest, DoesDefaultAction) {
+  // When there is an ON_CALL() statement, the action specified by it
+  // should be taken.
+  MockA a;
+  ON_CALL(a, Binary(_, _)).WillByDefault(Return(true));
+  EXPECT_CALL(a, Binary(0, 0));
+  a.Binary(0, 0);
+  bool result = false;
+  EXPECT_NONFATAL_FAILURE(result = a.Binary(0, 0),
+                          "Mock function called more times than expected");
+  EXPECT_TRUE(result);
+
+  // When there is no ON_CALL(), the default value for the return type
+  // should be returned.
+  MockB b;
+  EXPECT_CALL(b, DoB(0)).Description("DoB Method").Times(0);
+  int n = -1;
+  EXPECT_NONFATAL_FAILURE(
+      n = b.DoB(0),
+      "Mock function \"DoB Method\" called more times than expected");
+  EXPECT_EQ(0, n);
+}
+
+// Tests that when a void function is called too many times,
+// the failure message contains the argument values.
+TEST(ExcessiveCallTest, GeneratesFailureForVoidFunction) {
+  MockA a;
+  EXPECT_CALL(a, DoA(_)).Description("DoA Method").Times(0);
+  EXPECT_NONFATAL_FAILURE(
+      a.DoA(9),
+      "Mock function \"DoA Method\" called more times than expected - "
+      "returning directly.\n"
+      "    Function call: DoA(9)\n"
+      "         Expected: to be never called\n"
+      "           Actual: called once - over-saturated and active");
+}
+
+// Tests that when a non-void function is called too many times, the
+// failure message contains the argument values and the return value.
+TEST(ExcessiveCallTest, GeneratesFailureForNonVoidFunction) {
+  MockB b;
+  EXPECT_CALL(b, DoB(_));
+  b.DoB(1);
+  EXPECT_NONFATAL_FAILURE(
+      b.DoB(2),
+      "Mock function called more times than expected - "
+      "returning default value.\n"
+      "    Function call: DoB(2)\n"
+      "          Returns: 0\n"
+      "         Expected: to be called once\n"
+      "           Actual: called twice - over-saturated and active");
+}
+
+// Tests using sequences.
+
+TEST(InSequenceTest, AllExpectationInScopeAreInSequence) {
+  MockA a;
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(a, DoA(2));
+  }
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        a.DoA(2);
+      },
+      "Unexpected mock function call");
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(InSequenceTest, NestedInSequence) {
+  MockA a;
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(a, DoA(1));
+    {
+      InSequence dummy2;
+
+      EXPECT_CALL(a, DoA(2));
+      EXPECT_CALL(a, DoA(3));
+    }
+  }
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        a.DoA(1);
+        a.DoA(3);
+      },
+      "Unexpected mock function call");
+
+  a.DoA(2);
+  a.DoA(3);
+}
+
+TEST(InSequenceTest, ExpectationsOutOfScopeAreNotAffected) {
+  MockA a;
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(a, DoA(2));
+  }
+  EXPECT_CALL(a, DoA(3));
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        a.DoA(2);
+      },
+      "Unexpected mock function call");
+
+  a.DoA(3);
+  a.DoA(1);
+  a.DoA(2);
+}
+
+// Tests that any order is allowed when no sequence is used.
+TEST(SequenceTest, AnyOrderIsOkByDefault) {
+  {
+    MockA a;
+    MockB b;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(b, DoB()).Times(AnyNumber());
+
+    a.DoA(1);
+    b.DoB();
+  }
+
+  {  // NOLINT
+    MockA a;
+    MockB b;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(b, DoB()).Times(AnyNumber());
+
+    b.DoB();
+    a.DoA(1);
+  }
+}
+
+// Tests that the calls must be in strict order when a complete order
+// is specified.
+TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo1) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_)).WillByDefault(Return(Result()));
+
+  Sequence s;
+  EXPECT_CALL(a, ReturnResult(1)).InSequence(s);
+  EXPECT_CALL(a, ReturnResult(2)).InSequence(s);
+  EXPECT_CALL(a, ReturnResult(3)).InSequence(s);
+
+  a.ReturnResult(1);
+
+  // May only be called after a.ReturnResult(2).
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
+
+  a.ReturnResult(2);
+  a.ReturnResult(3);
+}
+
+// Tests that the calls must be in strict order when a complete order
+// is specified.
+TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo2) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_)).WillByDefault(Return(Result()));
+
+  Sequence s;
+  EXPECT_CALL(a, ReturnResult(1)).InSequence(s);
+  EXPECT_CALL(a, ReturnResult(2)).InSequence(s);
+
+  // May only be called after a.ReturnResult(1).
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(2), "Unexpected mock function call");
+
+  a.ReturnResult(1);
+  a.ReturnResult(2);
+}
+
+// Tests specifying a DAG using multiple sequences.
+class PartialOrderTest : public testing::Test {
+ protected:
+  PartialOrderTest() {
+    ON_CALL(a_, ReturnResult(_)).WillByDefault(Return(Result()));
+
+    // Specifies this partial ordering:
+    //
+    // a.ReturnResult(1) ==>
+    //                       a.ReturnResult(2) * n  ==>  a.ReturnResult(3)
+    // b.DoB() * 2       ==>
+    Sequence x, y;
+    EXPECT_CALL(a_, ReturnResult(1)).InSequence(x);
+    EXPECT_CALL(b_, DoB()).Times(2).InSequence(y);
+    EXPECT_CALL(a_, ReturnResult(2)).Times(AnyNumber()).InSequence(x, y);
+    EXPECT_CALL(a_, ReturnResult(3)).InSequence(x);
+  }
+
+  MockA a_;
+  MockB b_;
+};
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag1) {
+  a_.ReturnResult(1);
+  b_.DoB();
+
+  // May only be called after the second DoB().
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
+
+  b_.DoB();
+  a_.ReturnResult(3);
+}
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag2) {
+  // May only be called after ReturnResult(1).
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
+
+  a_.ReturnResult(1);
+  b_.DoB();
+  b_.DoB();
+  a_.ReturnResult(3);
+}
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag3) {
+  // May only be called last.
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(3), "Unexpected mock function call");
+
+  a_.ReturnResult(1);
+  b_.DoB();
+  b_.DoB();
+  a_.ReturnResult(3);
+}
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag4) {
+  a_.ReturnResult(1);
+  b_.DoB();
+  b_.DoB();
+  a_.ReturnResult(3);
+
+  // May only be called before ReturnResult(3).
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
+}
+
+TEST(SequenceTest, Retirement) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_CALL(a, DoA(1)).InSequence(s);
+  EXPECT_CALL(a, DoA(_)).InSequence(s).RetiresOnSaturation();
+  EXPECT_CALL(a, DoA(1)).InSequence(s);
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(1);
+}
+
+// Tests Expectation.
+
+TEST(ExpectationTest, ConstrutorsWork) {
+  MockA a;
+  Expectation e1;  // Default ctor.
+
+  // Ctor from various forms of EXPECT_CALL.
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3)).With(_);
+  {
+    Sequence s;
+    Expectation e4 = EXPECT_CALL(a, DoA(4)).Times(1);
+    Expectation e5 = EXPECT_CALL(a, DoA(5)).InSequence(s);
+  }
+  Expectation e6 = EXPECT_CALL(a, DoA(6)).After(e2);
+  Expectation e7 = EXPECT_CALL(a, DoA(7)).WillOnce(Return());
+  Expectation e8 = EXPECT_CALL(a, DoA(8)).WillRepeatedly(Return());
+  Expectation e9 = EXPECT_CALL(a, DoA(9)).RetiresOnSaturation();
+
+  Expectation e10 = e2;  // Copy ctor.
+
+  EXPECT_THAT(e1, Ne(e2));
+  EXPECT_THAT(e2, Eq(e10));
+
+  a.DoA(2);
+  a.DoA(3);
+  a.DoA(4);
+  a.DoA(5);
+  a.DoA(6);
+  a.DoA(7);
+  a.DoA(8);
+  a.DoA(9);
+}
+
+TEST(ExpectationTest, AssignmentWorks) {
+  MockA a;
+  Expectation e1;
+  Expectation e2 = EXPECT_CALL(a, DoA(1));
+
+  EXPECT_THAT(e1, Ne(e2));
+
+  e1 = e2;
+  EXPECT_THAT(e1, Eq(e2));
+
+  a.DoA(1);
+}
+
+// Tests ExpectationSet.
+
+TEST(ExpectationSetTest, MemberTypesAreCorrect) {
+  ::testing::StaticAssertTypeEq<Expectation, ExpectationSet::value_type>();
+}
+
+TEST(ExpectationSetTest, ConstructorsWork) {
+  MockA a;
+
+  Expectation e1;
+  const Expectation e2;
+  ExpectationSet es1;                           // Default ctor.
+  ExpectationSet es2 = EXPECT_CALL(a, DoA(1));  // Ctor from EXPECT_CALL.
+  ExpectationSet es3 = e1;                      // Ctor from Expectation.
+  ExpectationSet es4(e1);    // Ctor from Expectation; alternative syntax.
+  ExpectationSet es5 = e2;   // Ctor from const Expectation.
+  ExpectationSet es6(e2);    // Ctor from const Expectation; alternative syntax.
+  ExpectationSet es7 = es2;  // Copy ctor.
+
+  EXPECT_EQ(0, es1.size());
+  EXPECT_EQ(1, es2.size());
+  EXPECT_EQ(1, es3.size());
+  EXPECT_EQ(1, es4.size());
+  EXPECT_EQ(1, es5.size());
+  EXPECT_EQ(1, es6.size());
+  EXPECT_EQ(1, es7.size());
+
+  EXPECT_THAT(es3, Ne(es2));
+  EXPECT_THAT(es4, Eq(es3));
+  EXPECT_THAT(es5, Eq(es4));
+  EXPECT_THAT(es6, Eq(es5));
+  EXPECT_THAT(es7, Eq(es2));
+  a.DoA(1);
+}
+
+TEST(ExpectationSetTest, AssignmentWorks) {
+  ExpectationSet es1;
+  ExpectationSet es2 = Expectation();
+
+  es1 = es2;
+  EXPECT_EQ(1, es1.size());
+  EXPECT_THAT(*(es1.begin()), Eq(Expectation()));
+  EXPECT_THAT(es1, Eq(es2));
+}
+
+TEST(ExpectationSetTest, InsertionWorks) {
+  ExpectationSet es1;
+  Expectation e1;
+  es1 += e1;
+  EXPECT_EQ(1, es1.size());
+  EXPECT_THAT(*(es1.begin()), Eq(e1));
+
+  MockA a;
+  Expectation e2 = EXPECT_CALL(a, DoA(1));
+  es1 += e2;
+  EXPECT_EQ(2, es1.size());
+
+  ExpectationSet::const_iterator it1 = es1.begin();
+  ExpectationSet::const_iterator it2 = it1;
+  ++it2;
+  EXPECT_TRUE(*it1 == e1 || *it2 == e1);  // e1 must be in the set.
+  EXPECT_TRUE(*it1 == e2 || *it2 == e2);  // e2 must be in the set too.
+  a.DoA(1);
+}
+
+TEST(ExpectationSetTest, SizeWorks) {
+  ExpectationSet es;
+  EXPECT_EQ(0, es.size());
+
+  es += Expectation();
+  EXPECT_EQ(1, es.size());
+
+  MockA a;
+  es += EXPECT_CALL(a, DoA(1));
+  EXPECT_EQ(2, es.size());
+
+  a.DoA(1);
+}
+
+TEST(ExpectationSetTest, IsEnumerable) {
+  ExpectationSet es;
+  EXPECT_TRUE(es.begin() == es.end());
+
+  es += Expectation();
+  ExpectationSet::const_iterator it = es.begin();
+  EXPECT_TRUE(it != es.end());
+  EXPECT_THAT(*it, Eq(Expectation()));
+  ++it;
+  EXPECT_TRUE(it == es.end());
+}
+
+// Tests the .After() clause.
+
+TEST(AfterTest, SucceedsWhenPartialOrderIsSatisfied) {
+  MockA a;
+  ExpectationSet es;
+  es += EXPECT_CALL(a, DoA(1));
+  es += EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, DoA(3)).After(es);
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(3);
+}
+
+TEST(AfterTest, SucceedsWhenTotalOrderIsSatisfied) {
+  MockA a;
+  MockB b;
+  // The following also verifies that const Expectation objects work
+  // too.  Do not remove the const modifiers.
+  const Expectation e1 = EXPECT_CALL(a, DoA(1));
+  const Expectation e2 = EXPECT_CALL(b, DoB()).Times(2).After(e1);
+  EXPECT_CALL(a, DoA(2)).After(e2);
+
+  a.DoA(1);
+  b.DoB();
+  b.DoB();
+  a.DoA(2);
+}
+
+// Calls must be in strict order when specified so using .After().
+TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo1) {
+  MockA a;
+  MockB b;
+
+  // Define ordering:
+  //   a.DoA(1) ==> b.DoB() ==> a.DoA(2)
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(b, DoB()).After(e1);
+  EXPECT_CALL(a, DoA(2)).After(e2);
+
+  a.DoA(1);
+
+  // May only be called after DoB().
+  EXPECT_NONFATAL_FAILURE(a.DoA(2), "Unexpected mock function call");
+
+  b.DoB();
+  a.DoA(2);
+}
+
+// Calls must be in strict order when specified so using .After().
+TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo2) {
+  MockA a;
+  MockB b;
+
+  // Define ordering:
+  //   a.DoA(1) ==> b.DoB() * 2 ==> a.DoA(2)
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(b, DoB()).Times(2).After(e1);
+  EXPECT_CALL(a, DoA(2)).After(e2);
+
+  a.DoA(1);
+  b.DoB();
+
+  // May only be called after the second DoB().
+  EXPECT_NONFATAL_FAILURE(a.DoA(2), "Unexpected mock function call");
+
+  b.DoB();
+  a.DoA(2);
+}
+
+// Calls must satisfy the partial order when specified so.
+TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_)).WillByDefault(Return(Result()));
+
+  // Define ordering:
+  //   a.DoA(1) ==>
+  //   a.DoA(2) ==> a.ReturnResult(3)
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  const ExpectationSet es = EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, ReturnResult(3)).After(e, es);
+
+  // May only be called last.
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
+
+  a.DoA(2);
+  a.DoA(1);
+  a.ReturnResult(3);
+}
+
+// Calls must satisfy the partial order when specified so.
+TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo2) {
+  MockA a;
+
+  // Define ordering:
+  //   a.DoA(1) ==>
+  //   a.DoA(2) ==> a.DoA(3)
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  const ExpectationSet es = EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, DoA(3)).After(e, es);
+
+  a.DoA(2);
+
+  // May only be called last.
+  EXPECT_NONFATAL_FAILURE(a.DoA(3), "Unexpected mock function call");
+
+  a.DoA(1);
+  a.DoA(3);
+}
+
+// .After() can be combined with .InSequence().
+TEST(AfterTest, CanBeUsedWithInSequence) {
+  MockA a;
+  Sequence s;
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(2)).InSequence(s);
+  EXPECT_CALL(a, DoA(3)).InSequence(s).After(e);
+
+  a.DoA(1);
+
+  // May only be after DoA(2).
+  EXPECT_NONFATAL_FAILURE(a.DoA(3), "Unexpected mock function call");
+
+  a.DoA(2);
+  a.DoA(3);
+}
+
+// .After() can be called multiple times.
+TEST(AfterTest, CanBeCalledManyTimes) {
+  MockA a;
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3));
+  EXPECT_CALL(a, DoA(4)).After(e1).After(e2).After(e3);
+
+  a.DoA(3);
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(4);
+}
+
+// .After() accepts up to 5 arguments.
+TEST(AfterTest, AcceptsUpToFiveArguments) {
+  MockA a;
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3));
+  ExpectationSet es1 = EXPECT_CALL(a, DoA(4));
+  ExpectationSet es2 = EXPECT_CALL(a, DoA(5));
+  EXPECT_CALL(a, DoA(6)).After(e1, e2, e3, es1, es2);
+
+  a.DoA(5);
+  a.DoA(2);
+  a.DoA(4);
+  a.DoA(1);
+  a.DoA(3);
+  a.DoA(6);
+}
+
+// .After() allows input to contain duplicated Expectations.
+TEST(AfterTest, AcceptsDuplicatedInput) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_)).WillByDefault(Return(Result()));
+
+  // Define ordering:
+  //   DoA(1) ==>
+  //   DoA(2) ==> ReturnResult(3)
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  ExpectationSet es;
+  es += e1;
+  es += e2;
+  EXPECT_CALL(a, ReturnResult(3)).After(e1, e2, es, e1);
+
+  a.DoA(1);
+
+  // May only be after DoA(2).
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
+
+  a.DoA(2);
+  a.ReturnResult(3);
+}
+
+// An Expectation added to an ExpectationSet after it has been used in
+// an .After() has no effect.
+TEST(AfterTest, ChangesToExpectationSetHaveNoEffectAfterwards) {
+  MockA a;
+  ExpectationSet es1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, DoA(3)).After(es1);
+  es1 += e2;
+
+  a.DoA(1);
+  a.DoA(3);
+  a.DoA(2);
+}
+
+// Tests that Google Mock correctly handles calls to mock functions
+// after a mock object owning one of their pre-requisites has died.
+
+// Tests that calls that satisfy the original spec are successful.
+TEST(DeletingMockEarlyTest, Success1) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_)).WillOnce(Return(1));
+    EXPECT_CALL(*a, Binary(_, _))
+        .Times(AnyNumber())
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(*b2, DoB(_)).Times(AnyNumber()).WillRepeatedly(Return(2));
+  }
+
+  EXPECT_EQ(1, b1->DoB(1));
+  delete b1;
+  // a's pre-requisite has died.
+  EXPECT_TRUE(a->Binary(0, 1));
+  delete b2;
+  // a's successor has died.
+  EXPECT_TRUE(a->Binary(1, 2));
+  delete a;
+}
+
+// Tests that calls that satisfy the original spec are successful.
+TEST(DeletingMockEarlyTest, Success2) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_)).WillOnce(Return(1));
+    EXPECT_CALL(*a, Binary(_, _)).Times(AnyNumber());
+    EXPECT_CALL(*b2, DoB(_)).Times(AnyNumber()).WillRepeatedly(Return(2));
+  }
+
+  delete a;  // a is trivially satisfied.
+  EXPECT_EQ(1, b1->DoB(1));
+  EXPECT_EQ(2, b2->DoB(2));
+  delete b1;
+  delete b2;
+}
+
+// Tests that it's OK to delete a mock object itself in its action.
+
+// Suppresses warning on unreferenced formal parameter in MSVC with
+// -W4.
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+
+ACTION_P(Delete, ptr) { delete ptr; }
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
+
+TEST(DeletingMockEarlyTest, CanDeleteSelfInActionReturningVoid) {
+  MockA* const a = new MockA;
+  EXPECT_CALL(*a, DoA(_)).WillOnce(Delete(a));
+  a->DoA(42);  // This will cause a to be deleted.
+}
+
+TEST(DeletingMockEarlyTest, CanDeleteSelfInActionReturningValue) {
+  MockA* const a = new MockA;
+  EXPECT_CALL(*a, ReturnResult(_)).WillOnce(DoAll(Delete(a), Return(Result())));
+  a->ReturnResult(42);  // This will cause a to be deleted.
+}
+
+// Tests that calls that violate the original spec yield failures.
+TEST(DeletingMockEarlyTest, Failure1) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_)).WillOnce(Return(1));
+    EXPECT_CALL(*a, Binary(_, _)).Times(AnyNumber());
+    EXPECT_CALL(*b2, DoB(_)).Times(AnyNumber()).WillRepeatedly(Return(2));
+  }
+
+  delete a;  // a is trivially satisfied.
+  EXPECT_NONFATAL_FAILURE({ b2->DoB(2); }, "Unexpected mock function call");
+  EXPECT_EQ(1, b1->DoB(1));
+  delete b1;
+  delete b2;
+}
+
+// Tests that calls that violate the original spec yield failures.
+TEST(DeletingMockEarlyTest, Failure2) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_));
+    EXPECT_CALL(*a, Binary(_, _)).Times(AnyNumber());
+    EXPECT_CALL(*b2, DoB(_)).Times(AnyNumber());
+  }
+
+  EXPECT_NONFATAL_FAILURE(delete b1, "Actual: never called");
+  EXPECT_NONFATAL_FAILURE(a->Binary(0, 1), "Unexpected mock function call");
+  EXPECT_NONFATAL_FAILURE(b2->DoB(1), "Unexpected mock function call");
+  delete a;
+  delete b2;
+}
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  // Returns true if and only if call_count calls will satisfy this
+  // cardinality.
+  bool IsSatisfiedByCallCount(int call_count) const override {
+    return call_count % 2 == 0;
+  }
+
+  // Returns true if and only if call_count calls will saturate this
+  // cardinality.
+  bool IsSaturatedByCallCount(int /* call_count */) const override {
+    return false;
+  }
+
+  // Describes self to an ostream.
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() { return Cardinality(new EvenNumberCardinality); }
+
+TEST(ExpectationBaseTest,
+     AllPrerequisitesAreSatisfiedWorksForNonMonotonicCardinality) {
+  MockA* a = new MockA;
+  Sequence s;
+
+  EXPECT_CALL(*a, DoA(1)).Times(EvenNumber()).InSequence(s);
+  EXPECT_CALL(*a, DoA(2)).Times(AnyNumber()).InSequence(s);
+  EXPECT_CALL(*a, DoA(3)).Times(AnyNumber());
+
+  a->DoA(3);
+  a->DoA(1);
+  EXPECT_NONFATAL_FAILURE(a->DoA(2), "Unexpected mock function call");
+  EXPECT_NONFATAL_FAILURE(delete a, "to be called even number of times");
+}
+
+// The following tests verify the message generated when a mock
+// function is called.
+
+struct Printable {};
+
+inline void operator<<(::std::ostream& os, const Printable&) {
+  os << "Printable";
+}
+
+struct Unprintable {
+  Unprintable() : value(0) {}
+  int value;
+};
+
+class MockC {
+ public:
+  MockC() = default;
+
+  MOCK_METHOD6(VoidMethod, void(bool cond, int n, std::string s, void* p,
+                                const Printable& x, Unprintable y));
+  MOCK_METHOD0(NonVoidMethod, int());  // NOLINT
+
+ private:
+  MockC(const MockC&) = delete;
+  MockC& operator=(const MockC&) = delete;
+};
+
+class VerboseFlagPreservingFixture : public testing::Test {
+ protected:
+  VerboseFlagPreservingFixture()
+      : saved_verbose_flag_(GMOCK_FLAG_GET(verbose)) {}
+
+  ~VerboseFlagPreservingFixture() override {
+    GMOCK_FLAG_SET(verbose, saved_verbose_flag_);
+  }
+
+ private:
+  const std::string saved_verbose_flag_;
+
+  VerboseFlagPreservingFixture(const VerboseFlagPreservingFixture&) = delete;
+  VerboseFlagPreservingFixture& operator=(const VerboseFlagPreservingFixture&) =
+      delete;
+};
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that an uninteresting mock function call on a naggy mock
+// generates a warning without the stack trace when
+// --gmock_verbose=warning is specified.
+TEST(FunctionCallMessageTest,
+     UninterestingCallOnNaggyMockGeneratesNoStackTraceWhenVerboseWarning) {
+  GMOCK_FLAG_SET(verbose, kWarningVerbosity);
+  NaggyMock<MockC> c;
+  CaptureStdout();
+  c.VoidMethod(false, 5, "Hi", nullptr, Printable(), Unprintable());
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output);
+  EXPECT_PRED_FORMAT2(IsNotSubstring, "Stack trace:", output);
+}
+
+// Tests that an uninteresting mock function call on a naggy mock
+// generates a warning containing the stack trace when
+// --gmock_verbose=info is specified.
+TEST(FunctionCallMessageTest,
+     UninterestingCallOnNaggyMockGeneratesFyiWithStackTraceWhenVerboseInfo) {
+  GMOCK_FLAG_SET(verbose, kInfoVerbosity);
+  NaggyMock<MockC> c;
+  CaptureStdout();
+  c.VoidMethod(false, 5, "Hi", nullptr, Printable(), Unprintable());
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output);
+  EXPECT_PRED_FORMAT2(IsSubstring, "Stack trace:", output);
+
+#ifndef NDEBUG
+
+  // We check the stack trace content in dbg-mode only, as opt-mode
+  // may inline the call we are interested in seeing.
+
+  // Verifies that a void mock function's name appears in the stack
+  // trace.
+  EXPECT_PRED_FORMAT2(IsSubstring, "VoidMethod(", output);
+
+  // Verifies that a non-void mock function's name appears in the
+  // stack trace.
+  CaptureStdout();
+  c.NonVoidMethod();
+  const std::string output2 = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "NonVoidMethod(", output2);
+
+#endif  // NDEBUG
+}
+
+// Tests that an uninteresting mock function call on a naggy mock
+// causes the function arguments and return value to be printed.
+TEST(FunctionCallMessageTest,
+     UninterestingCallOnNaggyMockPrintsArgumentsAndReturnValue) {
+  // A non-void mock function.
+  NaggyMock<MockB> b;
+  CaptureStdout();
+  b.DoB();
+  const std::string output1 = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Uninteresting mock function call - returning default value.\n"
+      "    Function call: DoB()\n"
+      "          Returns: 0\n",
+      output1.c_str());
+  // Makes sure the return value is printed.
+
+  // A void mock function.
+  NaggyMock<MockC> c;
+  CaptureStdout();
+  c.VoidMethod(false, 5, "Hi", nullptr, Printable(), Unprintable());
+  const std::string output2 = GetCapturedStdout();
+  EXPECT_THAT(
+      output2.c_str(),
+      ContainsRegex("Uninteresting mock function call - returning directly\\.\n"
+                    "    Function call: VoidMethod"
+                    "\\(false, 5, \"Hi\", NULL, @.+ "
+                    "Printable, 4-byte object <00-00 00-00>\\)"));
+  // A void function has no return value to print.
+}
+
+// Tests how the --gmock_verbose flag affects Google Mock's output.
+
+class GMockVerboseFlagTest : public VerboseFlagPreservingFixture {
+ public:
+  // Verifies that the given Google Mock output is correct.  (When
+  // should_print is true, the output should match the given regex and
+  // contain the given function name in the stack trace.  When it's
+  // false, the output should be empty.)
+  void VerifyOutput(const std::string& output, bool should_print,
+                    const std::string& expected_substring,
+                    const std::string& function_name) {
+    if (should_print) {
+      EXPECT_THAT(output.c_str(), HasSubstr(expected_substring));
+#ifndef NDEBUG
+      // We check the stack trace content in dbg-mode only, as opt-mode
+      // may inline the call we are interested in seeing.
+      EXPECT_THAT(output.c_str(), HasSubstr(function_name));
+#else
+      // Suppresses 'unused function parameter' warnings.
+      static_cast<void>(function_name);
+#endif  // NDEBUG
+    } else {
+      EXPECT_STREQ("", output.c_str());
+    }
+  }
+
+  // Tests how the flag affects expected calls.
+  void TestExpectedCall(bool should_print) {
+    MockA a;
+    EXPECT_CALL(a, DoA(5));
+    EXPECT_CALL(a, Binary(_, 1)).WillOnce(Return(true));
+
+    // A void-returning function.
+    CaptureStdout();
+    a.DoA(5);
+    VerifyOutput(GetCapturedStdout(), should_print,
+                 "Mock function call matches EXPECT_CALL(a, DoA(5))...\n"
+                 "    Function call: DoA(5)\n"
+                 "Stack trace:\n",
+                 "DoA");
+
+    // A non-void-returning function.
+    CaptureStdout();
+    a.Binary(2, 1);
+    VerifyOutput(GetCapturedStdout(), should_print,
+                 "Mock function call matches EXPECT_CALL(a, Binary(_, 1))...\n"
+                 "    Function call: Binary(2, 1)\n"
+                 "          Returns: true\n"
+                 "Stack trace:\n",
+                 "Binary");
+  }
+
+  // Tests how the flag affects uninteresting calls on a naggy mock.
+  void TestUninterestingCallOnNaggyMock(bool should_print) {
+    NaggyMock<MockA> a;
+    const std::string note =
+        "NOTE: You can safely ignore the above warning unless this "
+        "call should not happen.  Do not suppress it by blindly adding "
+        "an EXPECT_CALL() if you don't mean to enforce the call.  "
+        "See "
+        "https://github.com/google/googletest/blob/main/docs/"
+        "gmock_cook_book.md#"
+        "knowing-when-to-expect-useoncall for details.";
+
+    // A void-returning function.
+    CaptureStdout();
+    a.DoA(5);
+    VerifyOutput(GetCapturedStdout(), should_print,
+                 "\nGMOCK WARNING:\n"
+                 "Uninteresting mock function call - returning directly.\n"
+                 "    Function call: DoA(5)\n" +
+                     note,
+                 "DoA");
+
+    // A non-void-returning function.
+    CaptureStdout();
+    a.Binary(2, 1);
+    VerifyOutput(GetCapturedStdout(), should_print,
+                 "\nGMOCK WARNING:\n"
+                 "Uninteresting mock function call - returning default value.\n"
+                 "    Function call: Binary(2, 1)\n"
+                 "          Returns: false\n" +
+                     note,
+                 "Binary");
+  }
+};
+
+// Tests that --gmock_verbose=info causes both expected and
+// uninteresting calls to be reported.
+TEST_F(GMockVerboseFlagTest, Info) {
+  GMOCK_FLAG_SET(verbose, kInfoVerbosity);
+  TestExpectedCall(true);
+  TestUninterestingCallOnNaggyMock(true);
+}
+
+// Tests that --gmock_verbose=warning causes uninteresting calls to be
+// reported.
+TEST_F(GMockVerboseFlagTest, Warning) {
+  GMOCK_FLAG_SET(verbose, kWarningVerbosity);
+  TestExpectedCall(false);
+  TestUninterestingCallOnNaggyMock(true);
+}
+
+// Tests that --gmock_verbose=warning causes neither expected nor
+// uninteresting calls to be reported.
+TEST_F(GMockVerboseFlagTest, Error) {
+  GMOCK_FLAG_SET(verbose, kErrorVerbosity);
+  TestExpectedCall(false);
+  TestUninterestingCallOnNaggyMock(false);
+}
+
+// Tests that --gmock_verbose=SOME_INVALID_VALUE has the same effect
+// as --gmock_verbose=warning.
+TEST_F(GMockVerboseFlagTest, InvalidFlagIsTreatedAsWarning) {
+  GMOCK_FLAG_SET(verbose, "invalid");  // Treated as "warning".
+  TestExpectedCall(false);
+  TestUninterestingCallOnNaggyMock(true);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// A helper class that generates a failure when printed.  We use it to
+// ensure that Google Mock doesn't print a value (even to an internal
+// buffer) when it is not supposed to do so.
+class PrintMeNot {};
+
+void PrintTo(PrintMeNot /* dummy */, ::std::ostream* /* os */) {
+  ADD_FAILURE() << "Google Mock is printing a value that shouldn't be "
+                << "printed even to an internal buffer.";
+}
+
+class LogTestHelper {
+ public:
+  LogTestHelper() = default;
+
+  MOCK_METHOD1(Foo, PrintMeNot(PrintMeNot));
+
+ private:
+  LogTestHelper(const LogTestHelper&) = delete;
+  LogTestHelper& operator=(const LogTestHelper&) = delete;
+};
+
+class GMockLogTest : public VerboseFlagPreservingFixture {
+ protected:
+  LogTestHelper helper_;
+};
+
+TEST_F(GMockLogTest, DoesNotPrintGoodCallInternallyIfVerbosityIsWarning) {
+  GMOCK_FLAG_SET(verbose, kWarningVerbosity);
+  EXPECT_CALL(helper_, Foo(_)).WillOnce(Return(PrintMeNot()));
+  helper_.Foo(PrintMeNot());  // This is an expected call.
+}
+
+TEST_F(GMockLogTest, DoesNotPrintGoodCallInternallyIfVerbosityIsError) {
+  GMOCK_FLAG_SET(verbose, kErrorVerbosity);
+  EXPECT_CALL(helper_, Foo(_)).WillOnce(Return(PrintMeNot()));
+  helper_.Foo(PrintMeNot());  // This is an expected call.
+}
+
+TEST_F(GMockLogTest, DoesNotPrintWarningInternallyIfVerbosityIsError) {
+  GMOCK_FLAG_SET(verbose, kErrorVerbosity);
+  ON_CALL(helper_, Foo(_)).WillByDefault(Return(PrintMeNot()));
+  helper_.Foo(PrintMeNot());  // This should generate a warning.
+}
+
+// Tests Mock::AllowLeak().
+
+TEST(AllowLeakTest, AllowsLeakingUnusedMockObject) {
+  MockA* a = new MockA;
+  Mock::AllowLeak(a);
+}
+
+TEST(AllowLeakTest, CanBeCalledBeforeOnCall) {
+  MockA* a = new MockA;
+  Mock::AllowLeak(a);
+  ON_CALL(*a, DoA(_)).WillByDefault(Return());
+  a->DoA(0);
+}
+
+TEST(AllowLeakTest, CanBeCalledAfterOnCall) {
+  MockA* a = new MockA;
+  ON_CALL(*a, DoA(_)).WillByDefault(Return());
+  Mock::AllowLeak(a);
+}
+
+TEST(AllowLeakTest, CanBeCalledBeforeExpectCall) {
+  MockA* a = new MockA;
+  Mock::AllowLeak(a);
+  EXPECT_CALL(*a, DoA(_));
+  a->DoA(0);
+}
+
+TEST(AllowLeakTest, CanBeCalledAfterExpectCall) {
+  MockA* a = new MockA;
+  EXPECT_CALL(*a, DoA(_)).Times(AnyNumber());
+  Mock::AllowLeak(a);
+}
+
+TEST(AllowLeakTest, WorksWhenBothOnCallAndExpectCallArePresent) {
+  MockA* a = new MockA;
+  ON_CALL(*a, DoA(_)).WillByDefault(Return());
+  EXPECT_CALL(*a, DoA(_)).Times(AnyNumber());
+  Mock::AllowLeak(a);
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when none of its methods has expectations.
+TEST(VerifyAndClearExpectationsTest, NoMethodHasExpectations) {
+  MockB b;
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when some, but not all, of its methods have expectations *and* the
+// verification succeeds.
+TEST(VerifyAndClearExpectationsTest, SomeMethodsHaveExpectationsAndSucceed) {
+  MockB b;
+  EXPECT_CALL(b, DoB()).WillOnce(Return(1));
+  b.DoB();
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when some, but not all, of its methods have expectations *and* the
+// verification fails.
+TEST(VerifyAndClearExpectationsTest, SomeMethodsHaveExpectationsAndFail) {
+  MockB b;
+  EXPECT_CALL(b, DoB()).WillOnce(Return(1));
+  bool result = true;
+  EXPECT_NONFATAL_FAILURE(result = Mock::VerifyAndClearExpectations(&b),
+                          "Actual: never called");
+  ASSERT_FALSE(result);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when all of its methods have expectations.
+TEST(VerifyAndClearExpectationsTest, AllMethodsHaveExpectations) {
+  MockB b;
+  EXPECT_CALL(b, DoB()).WillOnce(Return(1));
+  EXPECT_CALL(b, DoB(_)).WillOnce(Return(2));
+  b.DoB();
+  b.DoB(1);
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when a method has more than one expectation.
+TEST(VerifyAndClearExpectationsTest, AMethodHasManyExpectations) {
+  MockB b;
+  EXPECT_CALL(b, DoB(0)).WillOnce(Return(1));
+  EXPECT_CALL(b, DoB(_)).WillOnce(Return(2));
+  b.DoB(1);
+  bool result = true;
+  EXPECT_NONFATAL_FAILURE(result = Mock::VerifyAndClearExpectations(&b),
+                          "Actual: never called");
+  ASSERT_FALSE(result);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can call VerifyAndClearExpectations() on the same
+// mock object multiple times.
+TEST(VerifyAndClearExpectationsTest, CanCallManyTimes) {
+  MockB b;
+  EXPECT_CALL(b, DoB());
+  b.DoB();
+  Mock::VerifyAndClearExpectations(&b);
+
+  EXPECT_CALL(b, DoB(_)).WillOnce(Return(1));
+  b.DoB(1);
+  Mock::VerifyAndClearExpectations(&b);
+  Mock::VerifyAndClearExpectations(&b);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can clear a mock object's default actions when none
+// of its methods has default actions.
+TEST(VerifyAndClearTest, NoMethodHasDefaultActions) {
+  MockB b;
+  // If this crashes or generates a failure, the test will catch it.
+  Mock::VerifyAndClear(&b);
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that we can clear a mock object's default actions when some,
+// but not all of its methods have default actions.
+TEST(VerifyAndClearTest, SomeMethodsHaveDefaultActions) {
+  MockB b;
+  ON_CALL(b, DoB()).WillByDefault(Return(1));
+
+  Mock::VerifyAndClear(&b);
+
+  // Verifies that the default action of int DoB() was removed.
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that we can clear a mock object's default actions when all of
+// its methods have default actions.
+TEST(VerifyAndClearTest, AllMethodsHaveDefaultActions) {
+  MockB b;
+  ON_CALL(b, DoB()).WillByDefault(Return(1));
+  ON_CALL(b, DoB(_)).WillByDefault(Return(2));
+
+  Mock::VerifyAndClear(&b);
+
+  // Verifies that the default action of int DoB() was removed.
+  EXPECT_EQ(0, b.DoB());
+
+  // Verifies that the default action of int DoB(int) was removed.
+  EXPECT_EQ(0, b.DoB(0));
+}
+
+// Tests that we can clear a mock object's default actions when a
+// method has more than one ON_CALL() set on it.
+TEST(VerifyAndClearTest, AMethodHasManyDefaultActions) {
+  MockB b;
+  ON_CALL(b, DoB(0)).WillByDefault(Return(1));
+  ON_CALL(b, DoB(_)).WillByDefault(Return(2));
+
+  Mock::VerifyAndClear(&b);
+
+  // Verifies that the default actions (there are two) of int DoB(int)
+  // were removed.
+  EXPECT_EQ(0, b.DoB(0));
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can call VerifyAndClear() on a mock object multiple
+// times.
+TEST(VerifyAndClearTest, CanCallManyTimes) {
+  MockB b;
+  ON_CALL(b, DoB()).WillByDefault(Return(1));
+  Mock::VerifyAndClear(&b);
+  Mock::VerifyAndClear(&b);
+
+  ON_CALL(b, DoB(_)).WillByDefault(Return(1));
+  Mock::VerifyAndClear(&b);
+
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that VerifyAndClear() works when the verification succeeds.
+TEST(VerifyAndClearTest, Success) {
+  MockB b;
+  ON_CALL(b, DoB()).WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(1)).WillOnce(Return(2));
+
+  b.DoB();
+  b.DoB(1);
+  ASSERT_TRUE(Mock::VerifyAndClear(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that VerifyAndClear() works when the verification fails.
+TEST(VerifyAndClearTest, Failure) {
+  MockB b;
+  ON_CALL(b, DoB(_)).WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB()).WillOnce(Return(2));
+
+  b.DoB(1);
+  bool result = true;
+  EXPECT_NONFATAL_FAILURE(result = Mock::VerifyAndClear(&b),
+                          "Actual: never called");
+  ASSERT_FALSE(result);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that VerifyAndClear() works when the default actions and
+// expectations are set on a const mock object.
+TEST(VerifyAndClearTest, Const) {
+  MockB b;
+  ON_CALL(Const(b), DoB()).WillByDefault(Return(1));
+
+  EXPECT_CALL(Const(b), DoB()).WillOnce(DoDefault()).WillOnce(Return(2));
+
+  b.DoB();
+  b.DoB();
+  ASSERT_TRUE(Mock::VerifyAndClear(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can set default actions and expectations on a mock
+// object after VerifyAndClear() has been called on it.
+TEST(VerifyAndClearTest, CanSetDefaultActionsAndExpectationsAfterwards) {
+  MockB b;
+  ON_CALL(b, DoB()).WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(_)).WillOnce(Return(2));
+  b.DoB(1);
+
+  Mock::VerifyAndClear(&b);
+
+  EXPECT_CALL(b, DoB()).WillOnce(Return(3));
+  ON_CALL(b, DoB(_)).WillByDefault(Return(4));
+
+  EXPECT_EQ(3, b.DoB());
+  EXPECT_EQ(4, b.DoB(1));
+}
+
+// Tests that calling VerifyAndClear() on one mock object does not
+// affect other mock objects (either of the same type or not).
+TEST(VerifyAndClearTest, DoesNotAffectOtherMockObjects) {
+  MockA a;
+  MockB b1;
+  MockB b2;
+
+  ON_CALL(a, Binary(_, _)).WillByDefault(Return(true));
+  EXPECT_CALL(a, Binary(_, _)).WillOnce(DoDefault()).WillOnce(Return(false));
+
+  ON_CALL(b1, DoB()).WillByDefault(Return(1));
+  EXPECT_CALL(b1, DoB(_)).WillOnce(Return(2));
+
+  ON_CALL(b2, DoB()).WillByDefault(Return(3));
+  EXPECT_CALL(b2, DoB(_));
+
+  b2.DoB(0);
+  Mock::VerifyAndClear(&b2);
+
+  // Verifies that the default actions and expectations of a and b1
+  // are still in effect.
+  EXPECT_TRUE(a.Binary(0, 0));
+  EXPECT_FALSE(a.Binary(0, 0));
+
+  EXPECT_EQ(1, b1.DoB());
+  EXPECT_EQ(2, b1.DoB(0));
+}
+
+TEST(VerifyAndClearTest,
+     DestroyingChainedMocksDoesNotDeadlockThroughExpectations) {
+  std::shared_ptr<MockA> a(new MockA);
+  ReferenceHoldingMock test_mock;
+
+  // EXPECT_CALL stores a reference to a inside test_mock.
+  EXPECT_CALL(test_mock, AcceptReference(_))
+      .WillRepeatedly(SetArgPointee<0>(a));
+
+  // Throw away the reference to the mock that we have in a. After this, the
+  // only reference to it is stored by test_mock.
+  a.reset();
+
+  // When test_mock goes out of scope, it destroys the last remaining reference
+  // to the mock object originally pointed to by a. This will cause the MockA
+  // destructor to be called from inside the ReferenceHoldingMock destructor.
+  // The state of all mocks is protected by a single global lock, but there
+  // should be no deadlock.
+}
+
+TEST(VerifyAndClearTest,
+     DestroyingChainedMocksDoesNotDeadlockThroughDefaultAction) {
+  std::shared_ptr<MockA> a(new MockA);
+  ReferenceHoldingMock test_mock;
+
+  // ON_CALL stores a reference to a inside test_mock.
+  ON_CALL(test_mock, AcceptReference(_)).WillByDefault(SetArgPointee<0>(a));
+
+  // Throw away the reference to the mock that we have in a. After this, the
+  // only reference to it is stored by test_mock.
+  a.reset();
+
+  // When test_mock goes out of scope, it destroys the last remaining reference
+  // to the mock object originally pointed to by a. This will cause the MockA
+  // destructor to be called from inside the ReferenceHoldingMock destructor.
+  // The state of all mocks is protected by a single global lock, but there
+  // should be no deadlock.
+}
+
+// Tests that a mock function's action can call a mock function
+// (either the same function or a different one) either as an explicit
+// action or as a default action without causing a dead lock.  It
+// verifies that the action is not performed inside the critical
+// section.
+TEST(SynchronizationTest, CanCallMockMethodInAction) {
+  MockA a;
+  MockC c;
+  ON_CALL(a, DoA(_)).WillByDefault(
+      IgnoreResult(InvokeWithoutArgs(&c, &MockC::NonVoidMethod)));
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(1))
+      .WillOnce(Invoke(&a, &MockA::DoA))
+      .RetiresOnSaturation();
+  EXPECT_CALL(c, NonVoidMethod());
+
+  a.DoA(1);
+  // This will match the second EXPECT_CALL() and trigger another a.DoA(1),
+  // which will in turn match the first EXPECT_CALL() and trigger a call to
+  // c.NonVoidMethod() that was specified by the ON_CALL() since the first
+  // EXPECT_CALL() did not specify an action.
+}
+
+TEST(ParameterlessExpectationsTest, CanSetExpectationsWithoutMatchers) {
+  MockA a;
+  int do_a_arg0 = 0;
+  ON_CALL(a, DoA).WillByDefault(SaveArg<0>(&do_a_arg0));
+  int do_a_47_arg0 = 0;
+  ON_CALL(a, DoA(47)).WillByDefault(SaveArg<0>(&do_a_47_arg0));
+
+  a.DoA(17);
+  EXPECT_THAT(do_a_arg0, 17);
+  EXPECT_THAT(do_a_47_arg0, 0);
+  a.DoA(47);
+  EXPECT_THAT(do_a_arg0, 17);
+  EXPECT_THAT(do_a_47_arg0, 47);
+
+  ON_CALL(a, Binary).WillByDefault(Return(true));
+  ON_CALL(a, Binary(_, 14)).WillByDefault(Return(false));
+  EXPECT_THAT(a.Binary(14, 17), true);
+  EXPECT_THAT(a.Binary(17, 14), false);
+}
+
+TEST(ParameterlessExpectationsTest, CanSetExpectationsForOverloadedMethods) {
+  MockB b;
+  ON_CALL(b, DoB()).WillByDefault(Return(9));
+  ON_CALL(b, DoB(5)).WillByDefault(Return(11));
+
+  EXPECT_THAT(b.DoB(), 9);
+  EXPECT_THAT(b.DoB(1), 0);  // default value
+  EXPECT_THAT(b.DoB(5), 11);
+}
+
+struct MockWithConstMethods {
+ public:
+  MOCK_CONST_METHOD1(Foo, int(int));
+  MOCK_CONST_METHOD2(Bar, int(int, const char*));
+};
+
+TEST(ParameterlessExpectationsTest, CanSetExpectationsForConstMethods) {
+  MockWithConstMethods mock;
+  ON_CALL(mock, Foo).WillByDefault(Return(7));
+  ON_CALL(mock, Bar).WillByDefault(Return(33));
+
+  EXPECT_THAT(mock.Foo(17), 7);
+  EXPECT_THAT(mock.Bar(27, "purple"), 33);
+}
+
+class MockConstOverload {
+ public:
+  MOCK_METHOD1(Overloaded, int(int));
+  MOCK_CONST_METHOD1(Overloaded, int(int));
+};
+
+TEST(ParameterlessExpectationsTest,
+     CanSetExpectationsForConstOverloadedMethods) {
+  MockConstOverload mock;
+  ON_CALL(mock, Overloaded(_)).WillByDefault(Return(7));
+  ON_CALL(mock, Overloaded(5)).WillByDefault(Return(9));
+  ON_CALL(Const(mock), Overloaded(5)).WillByDefault(Return(11));
+  ON_CALL(Const(mock), Overloaded(7)).WillByDefault(Return(13));
+
+  EXPECT_THAT(mock.Overloaded(1), 7);
+  EXPECT_THAT(mock.Overloaded(5), 9);
+  EXPECT_THAT(mock.Overloaded(7), 7);
+
+  const MockConstOverload& const_mock = mock;
+  EXPECT_THAT(const_mock.Overloaded(1), 0);
+  EXPECT_THAT(const_mock.Overloaded(5), 11);
+  EXPECT_THAT(const_mock.Overloaded(7), 13);
+}
+
+}  // namespace
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  testing::InitGoogleMock(&argc, argv);
+  // Ensures that the tests pass no matter what value of
+  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
+  GMOCK_FLAG_SET(catch_leaked_mocks, true);
+  GMOCK_FLAG_SET(verbose, testing::internal::kWarningVerbosity);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googlemock/test/gmock_all_test.cc b/3rd-party/googletest/googlemock/test/gmock_all_test.cc
new file mode 100644
index 0000000..6db0086
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_all_test.cc
@@ -0,0 +1,49 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for Google C++ Mocking Framework (Google Mock)
+//
+// Some users use a build system that Google Mock doesn't support directly,
+// yet they still want to build and run Google Mock's own tests.  This file
+// includes most such tests, making it easier for these users to maintain
+// their build scripts (they just need to build this file, even though the
+// below list of actual *_test.cc files might change).
+#include "test/gmock-actions_test.cc"
+#include "test/gmock-cardinalities_test.cc"
+#include "test/gmock-internal-utils_test.cc"
+#include "test/gmock-matchers-arithmetic_test.cc"
+#include "test/gmock-matchers-comparisons_test.cc"
+#include "test/gmock-matchers-containers_test.cc"
+#include "test/gmock-matchers-misc_test.cc"
+#include "test/gmock-more-actions_test.cc"
+#include "test/gmock-nice-strict_test.cc"
+#include "test/gmock-port_test.cc"
+#include "test/gmock-spec-builders_test.cc"
+#include "test/gmock_test.cc"
diff --git a/3rd-party/googletest/googlemock/test/gmock_ex_test.cc b/3rd-party/googletest/googlemock/test/gmock_ex_test.cc
new file mode 100644
index 0000000..e174122
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_ex_test.cc
@@ -0,0 +1,80 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests Google Mock's functionality that depends on exceptions.
+
+#include <exception>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_EXCEPTIONS
+namespace {
+
+using testing::HasSubstr;
+
+using testing::internal::GoogleTestFailureException;
+
+// A type that cannot be default constructed.
+class NonDefaultConstructible {
+ public:
+  explicit NonDefaultConstructible(int /* dummy */) {}
+};
+
+class MockFoo {
+ public:
+  // A mock method that returns a user-defined type.  Google Mock
+  // doesn't know what the default value for this type is.
+  MOCK_METHOD0(GetNonDefaultConstructible, NonDefaultConstructible());
+};
+
+TEST(DefaultValueTest, ThrowsRuntimeErrorWhenNoDefaultValue) {
+  MockFoo mock;
+  try {
+    // No expectation is set on this method, so Google Mock must
+    // return the default value.  However, since Google Mock knows
+    // nothing about the return type, it doesn't know what to return,
+    // and has to throw (when exceptions are enabled) or abort
+    // (otherwise).
+    mock.GetNonDefaultConstructible();
+    FAIL() << "GetNonDefaultConstructible()'s return type has no default "
+           << "value, so Google Mock should have thrown.";
+  } catch (const GoogleTestFailureException& /* unused */) {
+    FAIL() << "Google Test does not try to catch an exception of type "
+           << "GoogleTestFailureException, which is used for reporting "
+           << "a failure to other testing frameworks.  Google Mock should "
+           << "not throw a GoogleTestFailureException as it will kill the "
+           << "entire test program instead of just the current TEST.";
+  } catch (const std::exception& ex) {
+    EXPECT_THAT(ex.what(), HasSubstr("has no default value"));
+  }
+}
+
+}  // unnamed namespace
+#endif
diff --git a/3rd-party/googletest/googlemock/test/gmock_leak_test.py b/3rd-party/googletest/googlemock/test/gmock_leak_test.py
new file mode 100755
index 0000000..8b02bc4
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_leak_test.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests that leaked mock objects can be caught be Google Mock."""
+
+from googlemock.test import gmock_test_utils
+
+PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_leak_test_')
+TEST_WITH_EXPECT_CALL = [PROGRAM_PATH, '--gtest_filter=*ExpectCall*']
+TEST_WITH_ON_CALL = [PROGRAM_PATH, '--gtest_filter=*OnCall*']
+TEST_MULTIPLE_LEAKS = [PROGRAM_PATH, '--gtest_filter=*MultipleLeaked*']
+
+environ = gmock_test_utils.environ
+SetEnvVar = gmock_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely.  Therefore they are incompatible with
+# the premature-exit-file protocol by design.  Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gmock_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
+
+class GMockLeakTest(gmock_test_utils.TestCase):
+
+  def testCatchesLeakedMockByDefault(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_WITH_EXPECT_CALL, env=environ
+        ).exit_code,
+    )
+    self.assertNotEqual(
+        0, gmock_test_utils.Subprocess(TEST_WITH_ON_CALL, env=environ).exit_code
+    )
+
+  def testDoesNotCatchLeakedMockWhenDisabled(self):
+    self.assertEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_WITH_EXPECT_CALL + ['--gmock_catch_leaked_mocks=0'],
+            env=environ,
+        ).exit_code,
+    )
+    self.assertEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_WITH_ON_CALL + ['--gmock_catch_leaked_mocks=0'], env=environ
+        ).exit_code,
+    )
+
+  def testCatchesLeakedMockWhenEnabled(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_WITH_EXPECT_CALL + ['--gmock_catch_leaked_mocks'], env=environ
+        ).exit_code,
+    )
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_WITH_ON_CALL + ['--gmock_catch_leaked_mocks'], env=environ
+        ).exit_code,
+    )
+
+  def testCatchesLeakedMockWhenEnabledWithExplictFlagValue(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_WITH_EXPECT_CALL + ['--gmock_catch_leaked_mocks=1'],
+            env=environ,
+        ).exit_code,
+    )
+
+  def testCatchesMultipleLeakedMocks(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(
+            TEST_MULTIPLE_LEAKS + ['--gmock_catch_leaked_mocks'], env=environ
+        ).exit_code,
+    )
+
+
+if __name__ == '__main__':
+  gmock_test_utils.Main()
diff --git a/3rd-party/googletest/googlemock/test/gmock_leak_test_.cc b/3rd-party/googletest/googlemock/test/gmock_leak_test_.cc
new file mode 100644
index 0000000..a6bb339
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_leak_test_.cc
@@ -0,0 +1,99 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This program is for verifying that a leaked mock object can be
+// caught by Google Mock's leak detector.
+
+#include "gmock/gmock.h"
+
+namespace {
+
+using ::testing::Return;
+
+class FooInterface {
+ public:
+  virtual ~FooInterface() = default;
+  virtual void DoThis() = 0;
+};
+
+class MockFoo : public FooInterface {
+ public:
+  MockFoo() = default;
+
+  MOCK_METHOD0(DoThis, void());
+
+ private:
+  MockFoo(const MockFoo&) = delete;
+  MockFoo& operator=(const MockFoo&) = delete;
+};
+
+TEST(LeakTest, LeakedMockWithExpectCallCausesFailureWhenLeakCheckingIsEnabled) {
+  MockFoo* foo = new MockFoo;
+
+  EXPECT_CALL(*foo, DoThis());
+  foo->DoThis();
+
+  // In order to test the leak detector, we deliberately leak foo.
+
+  // Makes sure Google Mock's leak detector can change the exit code
+  // to 1 even when the code is already exiting with 0.
+  exit(0);
+}
+
+TEST(LeakTest, LeakedMockWithOnCallCausesFailureWhenLeakCheckingIsEnabled) {
+  MockFoo* foo = new MockFoo;
+
+  ON_CALL(*foo, DoThis()).WillByDefault(Return());
+
+  // In order to test the leak detector, we deliberately leak foo.
+
+  // Makes sure Google Mock's leak detector can change the exit code
+  // to 1 even when the code is already exiting with 0.
+  exit(0);
+}
+
+TEST(LeakTest, CatchesMultipleLeakedMockObjects) {
+  MockFoo* foo1 = new MockFoo;
+  MockFoo* foo2 = new MockFoo;
+
+  ON_CALL(*foo1, DoThis()).WillByDefault(Return());
+  EXPECT_CALL(*foo2, DoThis());
+  foo2->DoThis();
+
+  // In order to test the leak detector, we deliberately leak foo1 and
+  // foo2.
+
+  // Makes sure Google Mock's leak detector can change the exit code
+  // to 1 even when the code is already exiting with 0.
+  exit(0);
+}
+
+}  // namespace
diff --git a/3rd-party/googletest/googlemock/test/gmock_link2_test.cc b/3rd-party/googletest/googlemock/test/gmock_link2_test.cc
new file mode 100644
index 0000000..cd3d690
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_link2_test.cc
@@ -0,0 +1,38 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file is for verifying that various Google Mock constructs do not
+// produce linker errors when instantiated in different translation units.
+// Please see gmock_link_test.h for details.
+
+#define LinkTest LinkTest2
+
+#include "test/gmock_link_test.h"
diff --git a/3rd-party/googletest/googlemock/test/gmock_link_test.cc b/3rd-party/googletest/googlemock/test/gmock_link_test.cc
new file mode 100644
index 0000000..f51e398
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_link_test.cc
@@ -0,0 +1,38 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file is for verifying that various Google Mock constructs do not
+// produce linker errors when instantiated in different translation units.
+// Please see gmock_link_test.h for details.
+
+#define LinkTest LinkTest1
+
+#include "test/gmock_link_test.h"
diff --git a/3rd-party/googletest/googlemock/test/gmock_link_test.h b/3rd-party/googletest/googlemock/test/gmock_link_test.h
new file mode 100644
index 0000000..cb5179b
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_link_test.h
@@ -0,0 +1,693 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests that:
+// a. A header file defining a mock class can be included in multiple
+//    translation units without causing a link error.
+// b. Actions and matchers can be instantiated with identical template
+//    arguments in different translation units without causing link
+//    errors.
+//    The following constructs are currently tested:
+//    Actions:
+//      Return()
+//      Return(value)
+//      ReturnNull
+//      ReturnRef
+//      Assign
+//      SetArgPointee
+//      SetArrayArgument
+//      SetErrnoAndReturn
+//      Invoke(function)
+//      Invoke(object, method)
+//      InvokeWithoutArgs(function)
+//      InvokeWithoutArgs(object, method)
+//      InvokeArgument
+//      WithArg
+//      WithArgs
+//      WithoutArgs
+//      DoAll
+//      DoDefault
+//      IgnoreResult
+//      Throw
+//      ACTION()-generated
+//      ACTION_P()-generated
+//      ACTION_P2()-generated
+//    Matchers:
+//      _
+//      A
+//      An
+//      Eq
+//      Gt, Lt, Ge, Le, Ne
+//      NotNull
+//      Ref
+//      TypedEq
+//      DoubleEq
+//      FloatEq
+//      NanSensitiveDoubleEq
+//      NanSensitiveFloatEq
+//      ContainsRegex
+//      MatchesRegex
+//      EndsWith
+//      HasSubstr
+//      StartsWith
+//      StrCaseEq
+//      StrCaseNe
+//      StrEq
+//      StrNe
+//      ElementsAre
+//      ElementsAreArray
+//      ContainerEq
+//      Field
+//      Property
+//      ResultOf(function)
+//      ResultOf(callback)
+//      Pointee
+//      Truly(predicate)
+//      AddressSatisfies
+//      AllOf
+//      AnyOf
+//      Not
+//      MatcherCast<T>
+//
+//  Please note: this test does not verify the functioning of these
+//  constructs, only that the programs using them will link successfully.
+//
+// Implementation note:
+// This test requires identical definitions of Interface and Mock to be
+// included in different translation units.  We achieve this by writing
+// them in this header and #including it in gmock_link_test.cc and
+// gmock_link2_test.cc.  Because the symbols generated by the compiler for
+// those constructs must be identical in both translation units,
+// definitions of Interface and Mock tests MUST be kept in the SAME
+// NON-ANONYMOUS namespace in this file.  The test fixture class LinkTest
+// is defined as LinkTest1 in gmock_link_test.cc and as LinkTest2 in
+// gmock_link2_test.cc to avoid producing linker errors.
+
+#ifndef GOOGLEMOCK_TEST_GMOCK_LINK_TEST_H_
+#define GOOGLEMOCK_TEST_GMOCK_LINK_TEST_H_
+
+#include "gmock/gmock.h"
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+#include <errno.h>
+#endif
+
+#include <iostream>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+using testing::_;
+using testing::A;
+using testing::Action;
+using testing::AllOf;
+using testing::AnyOf;
+using testing::Assign;
+using testing::ContainerEq;
+using testing::DoAll;
+using testing::DoDefault;
+using testing::DoubleEq;
+using testing::ElementsAre;
+using testing::ElementsAreArray;
+using testing::EndsWith;
+using testing::Eq;
+using testing::Field;
+using testing::FloatEq;
+using testing::Ge;
+using testing::Gt;
+using testing::HasSubstr;
+using testing::IgnoreResult;
+using testing::Invoke;
+using testing::InvokeArgument;
+using testing::InvokeWithoutArgs;
+using testing::IsNull;
+using testing::IsSubsetOf;
+using testing::IsSupersetOf;
+using testing::Le;
+using testing::Lt;
+using testing::Matcher;
+using testing::MatcherCast;
+using testing::NanSensitiveDoubleEq;
+using testing::NanSensitiveFloatEq;
+using testing::Ne;
+using testing::Not;
+using testing::NotNull;
+using testing::Pointee;
+using testing::Property;
+using testing::Ref;
+using testing::ResultOf;
+using testing::Return;
+using testing::ReturnNull;
+using testing::ReturnRef;
+using testing::SetArgPointee;
+using testing::SetArrayArgument;
+using testing::StartsWith;
+using testing::StrCaseEq;
+using testing::StrCaseNe;
+using testing::StrEq;
+using testing::StrNe;
+using testing::Truly;
+using testing::TypedEq;
+using testing::WithArg;
+using testing::WithArgs;
+using testing::WithoutArgs;
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+using testing::SetErrnoAndReturn;
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+using testing::Rethrow;
+using testing::Throw;
+#endif
+
+using testing::ContainsRegex;
+using testing::MatchesRegex;
+
+class Interface {
+ public:
+  virtual ~Interface() = default;
+  virtual void VoidFromString(char* str) = 0;
+  virtual char* StringFromString(char* str) = 0;
+  virtual int IntFromString(char* str) = 0;
+  virtual int& IntRefFromString(char* str) = 0;
+  virtual void VoidFromFunc(void (*func)(char* str)) = 0;
+  virtual void VoidFromIntRef(int& n) = 0;  // NOLINT
+  virtual void VoidFromFloat(float n) = 0;
+  virtual void VoidFromDouble(double n) = 0;
+  virtual void VoidFromVector(const std::vector<int>& v) = 0;
+};
+
+class Mock : public Interface {
+ public:
+  Mock() = default;
+
+  MOCK_METHOD1(VoidFromString, void(char* str));
+  MOCK_METHOD1(StringFromString, char*(char* str));
+  MOCK_METHOD1(IntFromString, int(char* str));
+  MOCK_METHOD1(IntRefFromString, int&(char* str));
+  MOCK_METHOD1(VoidFromFunc, void(void (*func)(char* str)));
+  MOCK_METHOD1(VoidFromIntRef, void(int& n));  // NOLINT
+  MOCK_METHOD1(VoidFromFloat, void(float n));
+  MOCK_METHOD1(VoidFromDouble, void(double n));
+  MOCK_METHOD1(VoidFromVector, void(const std::vector<int>& v));
+
+ private:
+  Mock(const Mock&) = delete;
+  Mock& operator=(const Mock&) = delete;
+};
+
+class InvokeHelper {
+ public:
+  static void StaticVoidFromVoid() {}
+  void VoidFromVoid() {}
+  static void StaticVoidFromString(char* /* str */) {}
+  void VoidFromString(char* /* str */) {}
+  static int StaticIntFromString(char* /* str */) { return 1; }
+  static bool StaticBoolFromString(const char* /* str */) { return true; }
+};
+
+class FieldHelper {
+ public:
+  explicit FieldHelper(int a_field) : field_(a_field) {}
+  int field() const { return field_; }
+  int field_;  // NOLINT -- need external access to field_ to test
+               //           the Field matcher.
+};
+
+// Tests the linkage of the ReturnVoid action.
+TEST(LinkTest, TestReturnVoid) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Return());
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the Return action.
+TEST(LinkTest, TestReturn) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, StringFromString(_)).WillOnce(Return(&ch));
+  mock.StringFromString(nullptr);
+}
+
+// Tests the linkage of the ReturnNull action.
+TEST(LinkTest, TestReturnNull) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Return());
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the ReturnRef action.
+TEST(LinkTest, TestReturnRef) {
+  Mock mock;
+  int n = 42;
+
+  EXPECT_CALL(mock, IntRefFromString(_)).WillOnce(ReturnRef(n));
+  mock.IntRefFromString(nullptr);
+}
+
+// Tests the linkage of the Assign action.
+TEST(LinkTest, TestAssign) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Assign(&ch, 'y'));
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the SetArgPointee action.
+TEST(LinkTest, TestSetArgPointee) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(SetArgPointee<0>('y'));
+  mock.VoidFromString(&ch);
+}
+
+// Tests the linkage of the SetArrayArgument action.
+TEST(LinkTest, TestSetArrayArgument) {
+  Mock mock;
+  char ch = 'x';
+  char ch2 = 'y';
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(SetArrayArgument<0>(&ch2, &ch2 + 1));
+  mock.VoidFromString(&ch);
+}
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+
+// Tests the linkage of the SetErrnoAndReturn action.
+TEST(LinkTest, TestSetErrnoAndReturn) {
+  Mock mock;
+
+  int saved_errno = errno;
+  EXPECT_CALL(mock, IntFromString(_)).WillOnce(SetErrnoAndReturn(1, -1));
+  mock.IntFromString(nullptr);
+  errno = saved_errno;
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests the linkage of the Invoke(function) and Invoke(object, method) actions.
+TEST(LinkTest, TestInvoke) {
+  Mock mock;
+  InvokeHelper test_invoke_helper;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(Invoke(&InvokeHelper::StaticVoidFromString))
+      .WillOnce(Invoke(&test_invoke_helper, &InvokeHelper::VoidFromString));
+  mock.VoidFromString(nullptr);
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the InvokeWithoutArgs action.
+TEST(LinkTest, TestInvokeWithoutArgs) {
+  Mock mock;
+  InvokeHelper test_invoke_helper;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(InvokeWithoutArgs(&InvokeHelper::StaticVoidFromVoid))
+      .WillOnce(
+          InvokeWithoutArgs(&test_invoke_helper, &InvokeHelper::VoidFromVoid));
+  mock.VoidFromString(nullptr);
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the InvokeArgument action.
+TEST(LinkTest, TestInvokeArgument) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromFunc(_)).WillOnce(InvokeArgument<0>(&ch));
+  mock.VoidFromFunc(InvokeHelper::StaticVoidFromString);
+}
+
+// Tests the linkage of the WithArg action.
+TEST(LinkTest, TestWithArg) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(WithArg<0>(Invoke(&InvokeHelper::StaticVoidFromString)));
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the WithArgs action.
+TEST(LinkTest, TestWithArgs) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(WithArgs<0>(Invoke(&InvokeHelper::StaticVoidFromString)));
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the WithoutArgs action.
+TEST(LinkTest, TestWithoutArgs) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(WithoutArgs(Return()));
+  mock.VoidFromString(nullptr);
+}
+
+// Tests the linkage of the DoAll action.
+TEST(LinkTest, TestDoAll) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(DoAll(SetArgPointee<0>('y'), Return()));
+  mock.VoidFromString(&ch);
+}
+
+// Tests the linkage of the DoDefault action.
+TEST(LinkTest, TestDoDefault) {
+  Mock mock;
+  char ch = 'x';
+
+  ON_CALL(mock, VoidFromString(_)).WillByDefault(Return());
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(DoDefault());
+  mock.VoidFromString(&ch);
+}
+
+// Tests the linkage of the IgnoreResult action.
+TEST(LinkTest, TestIgnoreResult) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(IgnoreResult(Return(42)));
+  mock.VoidFromString(nullptr);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+// Tests the linkage of the Throw action.
+TEST(LinkTest, TestThrow) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Throw(42));
+  EXPECT_THROW(mock.VoidFromString(nullptr), int);
+}
+// Tests the linkage of the Rethrow action.
+TEST(LinkTest, TestRethrow) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(Rethrow(std::make_exception_ptr(42)));
+  EXPECT_THROW(mock.VoidFromString(nullptr), int);
+}
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+
+// Tests the linkage of actions created using ACTION macro.
+namespace {
+ACTION(Return1) { return 1; }
+}  // namespace
+
+TEST(LinkTest, TestActionMacro) {
+  Mock mock;
+
+  EXPECT_CALL(mock, IntFromString(_)).WillOnce(Return1());
+  mock.IntFromString(nullptr);
+}
+
+// Tests the linkage of actions created using ACTION_P macro.
+namespace {
+ACTION_P(ReturnArgument, ret_value) { return ret_value; }
+}  // namespace
+
+TEST(LinkTest, TestActionPMacro) {
+  Mock mock;
+
+  EXPECT_CALL(mock, IntFromString(_)).WillOnce(ReturnArgument(42));
+  mock.IntFromString(nullptr);
+}
+
+// Tests the linkage of actions created using ACTION_P2 macro.
+namespace {
+ACTION_P2(ReturnEqualsEitherOf, first, second) {
+  return arg0 == first || arg0 == second;
+}
+}  // namespace
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
+
+TEST(LinkTest, TestActionP2Macro) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, IntFromString(_))
+      .WillOnce(ReturnEqualsEitherOf("one", "two"));
+  mock.IntFromString(&ch);
+}
+
+// Tests the linkage of the "_" matcher.
+TEST(LinkTest, TestMatcherAnything) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(_)).WillByDefault(Return());
+}
+
+// Tests the linkage of the A matcher.
+TEST(LinkTest, TestMatcherA) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(A<char*>())).WillByDefault(Return());
+}
+
+// Tests the linkage of the Eq and the "bare value" matcher.
+TEST(LinkTest, TestMatchersEq) {
+  Mock mock;
+  const char* p = "x";
+
+  ON_CALL(mock, VoidFromString(Eq(p))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(const_cast<char*>("y"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the Lt, Gt, Le, Ge, and Ne matchers.
+TEST(LinkTest, TestMatchersRelations) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromFloat(Lt(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Gt(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Le(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Ge(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Ne(1.0f))).WillByDefault(Return());
+}
+
+// Tests the linkage of the NotNull matcher.
+TEST(LinkTest, TestMatcherNotNull) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(NotNull())).WillByDefault(Return());
+}
+
+// Tests the linkage of the IsNull matcher.
+TEST(LinkTest, TestMatcherIsNull) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(IsNull())).WillByDefault(Return());
+}
+
+// Tests the linkage of the Ref matcher.
+TEST(LinkTest, TestMatcherRef) {
+  Mock mock;
+  int a = 0;
+
+  ON_CALL(mock, VoidFromIntRef(Ref(a))).WillByDefault(Return());
+}
+
+// Tests the linkage of the TypedEq matcher.
+TEST(LinkTest, TestMatcherTypedEq) {
+  Mock mock;
+  long a = 0;
+
+  ON_CALL(mock, VoidFromIntRef(TypedEq<int&>(a))).WillByDefault(Return());
+}
+
+// Tests the linkage of the FloatEq, DoubleEq, NanSensitiveFloatEq and
+// NanSensitiveDoubleEq matchers.
+TEST(LinkTest, TestMatchersFloatingPoint) {
+  Mock mock;
+  float a = 0;
+
+  ON_CALL(mock, VoidFromFloat(FloatEq(a))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromDouble(DoubleEq(a))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(NanSensitiveFloatEq(a))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromDouble(NanSensitiveDoubleEq(a)))
+      .WillByDefault(Return());
+}
+
+// Tests the linkage of the ContainsRegex matcher.
+TEST(LinkTest, TestMatcherContainsRegex) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(ContainsRegex(".*"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the MatchesRegex matcher.
+TEST(LinkTest, TestMatcherMatchesRegex) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(MatchesRegex(".*"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the StartsWith, EndsWith, and HasSubstr matchers.
+TEST(LinkTest, TestMatchersSubstrings) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(StartsWith("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(EndsWith("c"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(HasSubstr("b"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the StrEq, StrNe, StrCaseEq, and StrCaseNe matchers.
+TEST(LinkTest, TestMatchersStringEquality) {
+  Mock mock;
+  ON_CALL(mock, VoidFromString(StrEq("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(StrNe("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(StrCaseEq("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(StrCaseNe("a"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the ElementsAre matcher.
+TEST(LinkTest, TestMatcherElementsAre) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromVector(ElementsAre('a', _))).WillByDefault(Return());
+}
+
+// Tests the linkage of the ElementsAreArray matcher.
+TEST(LinkTest, TestMatcherElementsAreArray) {
+  Mock mock;
+  char arr[] = {'a', 'b'};
+
+  ON_CALL(mock, VoidFromVector(ElementsAreArray(arr))).WillByDefault(Return());
+}
+
+// Tests the linkage of the IsSubsetOf matcher.
+TEST(LinkTest, TestMatcherIsSubsetOf) {
+  Mock mock;
+  char arr[] = {'a', 'b'};
+
+  ON_CALL(mock, VoidFromVector(IsSubsetOf(arr))).WillByDefault(Return());
+}
+
+// Tests the linkage of the IsSupersetOf matcher.
+TEST(LinkTest, TestMatcherIsSupersetOf) {
+  Mock mock;
+  char arr[] = {'a', 'b'};
+
+  ON_CALL(mock, VoidFromVector(IsSupersetOf(arr))).WillByDefault(Return());
+}
+
+// Tests the linkage of the ContainerEq matcher.
+TEST(LinkTest, TestMatcherContainerEq) {
+  Mock mock;
+  std::vector<int> v;
+
+  ON_CALL(mock, VoidFromVector(ContainerEq(v))).WillByDefault(Return());
+}
+
+// Tests the linkage of the Field matcher.
+TEST(LinkTest, TestMatcherField) {
+  FieldHelper helper(0);
+
+  Matcher<const FieldHelper&> m = Field(&FieldHelper::field_, Eq(0));
+  EXPECT_TRUE(m.Matches(helper));
+
+  Matcher<const FieldHelper*> m2 = Field(&FieldHelper::field_, Eq(0));
+  EXPECT_TRUE(m2.Matches(&helper));
+}
+
+// Tests the linkage of the Property matcher.
+TEST(LinkTest, TestMatcherProperty) {
+  FieldHelper helper(0);
+
+  Matcher<const FieldHelper&> m = Property(&FieldHelper::field, Eq(0));
+  EXPECT_TRUE(m.Matches(helper));
+
+  Matcher<const FieldHelper*> m2 = Property(&FieldHelper::field, Eq(0));
+  EXPECT_TRUE(m2.Matches(&helper));
+}
+
+// Tests the linkage of the ResultOf matcher.
+TEST(LinkTest, TestMatcherResultOf) {
+  Matcher<char*> m = ResultOf(&InvokeHelper::StaticIntFromString, Eq(1));
+  EXPECT_TRUE(m.Matches(nullptr));
+}
+
+// Tests the linkage of the ResultOf matcher.
+TEST(LinkTest, TestMatcherPointee) {
+  int n = 1;
+
+  Matcher<int*> m = Pointee(Eq(1));
+  EXPECT_TRUE(m.Matches(&n));
+}
+
+// Tests the linkage of the Truly matcher.
+TEST(LinkTest, TestMatcherTruly) {
+  Matcher<const char*> m = Truly(&InvokeHelper::StaticBoolFromString);
+  EXPECT_TRUE(m.Matches(nullptr));
+}
+
+// Tests the linkage of the AllOf matcher.
+TEST(LinkTest, TestMatcherAllOf) {
+  Matcher<int> m = AllOf(_, Eq(1));
+  EXPECT_TRUE(m.Matches(1));
+}
+
+// Tests the linkage of the AnyOf matcher.
+TEST(LinkTest, TestMatcherAnyOf) {
+  Matcher<int> m = AnyOf(_, Eq(1));
+  EXPECT_TRUE(m.Matches(1));
+}
+
+// Tests the linkage of the Not matcher.
+TEST(LinkTest, TestMatcherNot) {
+  Matcher<int> m = Not(_);
+  EXPECT_FALSE(m.Matches(1));
+}
+
+// Tests the linkage of the MatcherCast<T>() function.
+TEST(LinkTest, TestMatcherCast) {
+  Matcher<const char*> m = MatcherCast<const char*>(_);
+  EXPECT_TRUE(m.Matches(nullptr));
+}
+
+#endif  // GOOGLEMOCK_TEST_GMOCK_LINK_TEST_H_
diff --git a/3rd-party/googletest/googlemock/test/gmock_output_test.py b/3rd-party/googletest/googlemock/test/gmock_output_test.py
new file mode 100755
index 0000000..7c24d68
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_output_test.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+r"""Tests the text output of Google C++ Mocking Framework.
+
+To update the golden file:
+gmock_output_test.py --build_dir=BUILD/DIR --gengolden
+where BUILD/DIR contains the built gmock_output_test_ file.
+gmock_output_test.py --gengolden
+gmock_output_test.py
+
+"""
+
+from io import open  # pylint: disable=redefined-builtin, g-importing-member
+import os
+import re
+import sys
+from googlemock.test import gmock_test_utils
+
+
+# The flag for generating the golden file
+GENGOLDEN_FLAG = '--gengolden'
+
+PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_output_test_')
+COMMAND = [PROGRAM_PATH, '--gtest_stack_trace_depth=0', '--gtest_print_time=0']
+GOLDEN_NAME = 'gmock_output_test_golden.txt'
+GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(), GOLDEN_NAME)
+
+
+def ToUnixLineEnding(s):
+  """Changes all Windows/Mac line endings in s to UNIX line endings."""
+
+  return s.replace('\r\n', '\n').replace('\r', '\n')
+
+
+def RemoveReportHeaderAndFooter(output):
+  """Removes Google Test result report's header and footer from the output."""
+
+  output = re.sub(r'.*gtest_main.*\n', '', output)
+  output = re.sub(r'\[.*\d+ tests.*\n', '', output)
+  output = re.sub(r'\[.* test environment .*\n', '', output)
+  output = re.sub(r'\[=+\] \d+ tests .* ran.*', '', output)
+  output = re.sub(r'.* FAILED TESTS\n', '', output)
+  return output
+
+
+def RemoveLocations(output):
+  """Removes all file location info from a Google Test program's output.
+
+  Args:
+       output:  the output of a Google Test program.
+
+  Returns:
+       output with all file location info (in the form of
+       'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
+       'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
+       'FILE:#: '.
+  """
+
+  return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\:', 'FILE:#:', output)
+
+
+def NormalizeErrorMarker(output):
+  """Normalizes the error marker, which is different on Windows vs on Linux."""
+
+  return re.sub(r' error: ', ' Failure\n', output)
+
+
+def RemoveMemoryAddresses(output):
+  """Removes memory addresses from the test output."""
+
+  return re.sub(r'@\w+', '@0x#', output)
+
+
+def RemoveTestNamesOfLeakedMocks(output):
+  """Removes the test names of leaked mock objects from the test output."""
+
+  return re.sub(r'\(used in test .+\) ', '', output)
+
+
+def GetLeakyTests(output):
+  """Returns a list of test names that leak mock objects."""
+
+  # findall() returns a list of all matches of the regex in output.
+  # For example, if '(used in test FooTest.Bar)' is in output, the
+  # list will contain 'FooTest.Bar'.
+  return re.findall(r'\(used in test (.+)\)', output)
+
+
+def GetNormalizedOutputAndLeakyTests(output):
+  """Normalizes the output of gmock_output_test_.
+
+  Args:
+    output: The test output.
+
+  Returns:
+    A tuple (the normalized test output, the list of test names that have
+    leaked mocks).
+  """
+
+  output = ToUnixLineEnding(output)
+  output = RemoveReportHeaderAndFooter(output)
+  output = NormalizeErrorMarker(output)
+  output = RemoveLocations(output)
+  output = RemoveMemoryAddresses(output)
+  return (RemoveTestNamesOfLeakedMocks(output), GetLeakyTests(output))
+
+
+def GetShellCommandOutput(cmd):
+  """Runs a command in a sub-process, and returns its STDOUT in a string."""
+
+  return gmock_test_utils.Subprocess(cmd, capture_stderr=False).output
+
+
+def GetNormalizedCommandOutputAndLeakyTests(cmd):
+  """Runs a command and returns its normalized output and a list of leaky tests.
+
+  Args:
+    cmd:  the shell command.
+  """
+
+  # Disables exception pop-ups on Windows.
+  os.environ['GTEST_CATCH_EXCEPTIONS'] = '1'
+  return GetNormalizedOutputAndLeakyTests(GetShellCommandOutput(cmd))
+
+
+class GMockOutputTest(gmock_test_utils.TestCase):
+
+  def testOutput(self):
+    (output, leaky_tests) = GetNormalizedCommandOutputAndLeakyTests(COMMAND)
+    golden_file = open(GOLDEN_PATH, 'rb')
+    golden = golden_file.read().decode('utf-8')
+    golden_file.close()
+    # On Windows the repository might have been checked out with \r\n line
+    # endings, so normalize it here.
+    golden = ToUnixLineEnding(golden)
+
+    # The normalized output should match the golden file.
+    self.assertEqual(golden, output)
+
+    # The raw output should contain 2 leaked mock object errors for
+    # test GMockOutputTest.CatchesLeakedMocks.
+    self.assertEqual(
+        [
+            'GMockOutputTest.CatchesLeakedMocks',
+            'GMockOutputTest.CatchesLeakedMocks',
+        ],
+        leaky_tests,
+    )
+
+
+if __name__ == '__main__':
+  if sys.argv[1:] == [GENGOLDEN_FLAG]:
+    (output, _) = GetNormalizedCommandOutputAndLeakyTests(COMMAND)
+    golden_file = open(GOLDEN_PATH, 'wb')
+    golden_file.write(output)
+    golden_file.close()
+    # Suppress the error "googletest was imported but a call to its main()
+    # was never detected."
+    os._exit(0)
+  else:
+    gmock_test_utils.Main()
diff --git a/3rd-party/googletest/googlemock/test/gmock_output_test_.cc b/3rd-party/googletest/googlemock/test/gmock_output_test_.cc
new file mode 100644
index 0000000..03d8421
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_output_test_.cc
@@ -0,0 +1,286 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests Google Mock's output in various scenarios.  This ensures that
+// Google Mock's messages are readable and useful.
+
+#include <stdio.h>
+
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// Silence C4100 (unreferenced formal parameter)
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+
+using testing::_;
+using testing::AnyNumber;
+using testing::Ge;
+using testing::InSequence;
+using testing::NaggyMock;
+using testing::Ref;
+using testing::Return;
+using testing::Sequence;
+using testing::Value;
+
+class MockFoo {
+ public:
+  MockFoo() = default;
+
+  MOCK_METHOD3(Bar, char(const std::string& s, int i, double x));
+  MOCK_METHOD2(Bar2, bool(int x, int y));
+  MOCK_METHOD2(Bar3, void(int x, int y));
+
+ private:
+  MockFoo(const MockFoo&) = delete;
+  MockFoo& operator=(const MockFoo&) = delete;
+};
+
+class GMockOutputTest : public testing::Test {
+ protected:
+  NaggyMock<MockFoo> foo_;
+};
+
+TEST_F(GMockOutputTest, ExpectedCall) {
+  GMOCK_FLAG_SET(verbose, "info");
+
+  EXPECT_CALL(foo_, Bar2(0, _));
+  foo_.Bar2(0, 0);  // Expected call
+
+  GMOCK_FLAG_SET(verbose, "warning");
+}
+
+TEST_F(GMockOutputTest, ExpectedCallToVoidFunction) {
+  GMOCK_FLAG_SET(verbose, "info");
+
+  EXPECT_CALL(foo_, Bar3(0, _));
+  foo_.Bar3(0, 0);  // Expected call
+
+  GMOCK_FLAG_SET(verbose, "warning");
+}
+
+TEST_F(GMockOutputTest, ExplicitActionsRunOut) {
+  EXPECT_CALL(foo_, Bar2(_, _)).Times(2).WillOnce(Return(false));
+  foo_.Bar2(2, 2);
+  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
+}
+
+TEST_F(GMockOutputTest, UnexpectedCall) {
+  EXPECT_CALL(foo_, Bar2(0, _));
+
+  foo_.Bar2(1, 0);  // Unexpected call
+  foo_.Bar2(0, 0);  // Expected call
+}
+
+TEST_F(GMockOutputTest, UnexpectedCallToVoidFunction) {
+  EXPECT_CALL(foo_, Bar3(0, _));
+
+  foo_.Bar3(1, 0);  // Unexpected call
+  foo_.Bar3(0, 0);  // Expected call
+}
+
+TEST_F(GMockOutputTest, ExcessiveCall) {
+  EXPECT_CALL(foo_, Bar2(0, _));
+
+  foo_.Bar2(0, 0);  // Expected call
+  foo_.Bar2(0, 1);  // Excessive call
+}
+
+TEST_F(GMockOutputTest, ExcessiveCallToVoidFunction) {
+  EXPECT_CALL(foo_, Bar3(0, _));
+
+  foo_.Bar3(0, 0);  // Expected call
+  foo_.Bar3(0, 1);  // Excessive call
+}
+
+TEST_F(GMockOutputTest, UninterestingCall) {
+  foo_.Bar2(0, 1);  // Uninteresting call
+}
+
+TEST_F(GMockOutputTest, UninterestingCallToVoidFunction) {
+  foo_.Bar3(0, 1);  // Uninteresting call
+}
+
+TEST_F(GMockOutputTest, RetiredExpectation) {
+  EXPECT_CALL(foo_, Bar2(_, _)).RetiresOnSaturation();
+  EXPECT_CALL(foo_, Bar2(0, 0));
+
+  foo_.Bar2(1, 1);
+  foo_.Bar2(1, 1);  // Matches a retired expectation
+  foo_.Bar2(0, 0);
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedPrerequisite) {
+  {
+    InSequence s;
+    EXPECT_CALL(foo_, Bar(_, 0, _));
+    EXPECT_CALL(foo_, Bar2(0, 0));
+    EXPECT_CALL(foo_, Bar2(1, _));
+  }
+
+  foo_.Bar2(1, 0);  // Has one immediate unsatisfied pre-requisite
+  foo_.Bar("Hi", 0, 0);
+  foo_.Bar2(0, 0);
+  foo_.Bar2(1, 0);
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedPrerequisites) {
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo_, Bar(_, 0, _)).InSequence(s1);
+  EXPECT_CALL(foo_, Bar2(0, 0)).InSequence(s2);
+  EXPECT_CALL(foo_, Bar2(1, _)).InSequence(s1, s2);
+
+  foo_.Bar2(1, 0);  // Has two immediate unsatisfied pre-requisites
+  foo_.Bar("Hi", 0, 0);
+  foo_.Bar2(0, 0);
+  foo_.Bar2(1, 0);
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedWith) {
+  EXPECT_CALL(foo_, Bar2(_, _)).With(Ge());
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedExpectation) {
+  EXPECT_CALL(foo_, Bar(_, _, _));
+  EXPECT_CALL(foo_, Bar2(0, _)).Times(2);
+
+  foo_.Bar2(0, 1);
+}
+
+TEST_F(GMockOutputTest, MismatchArguments) {
+  const std::string s = "Hi";
+  EXPECT_CALL(foo_, Bar(Ref(s), _, Ge(0)));
+
+  foo_.Bar("Ho", 0, -0.1);  // Mismatch arguments
+  foo_.Bar(s, 0, 0);
+}
+
+TEST_F(GMockOutputTest, MismatchWith) {
+  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1))).With(Ge());
+
+  foo_.Bar2(2, 3);  // Mismatch With()
+  foo_.Bar2(2, 1);
+}
+
+TEST_F(GMockOutputTest, MismatchArgumentsAndWith) {
+  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1))).With(Ge());
+
+  foo_.Bar2(1, 3);  // Mismatch arguments and mismatch With()
+  foo_.Bar2(2, 1);
+}
+
+TEST_F(GMockOutputTest, UnexpectedCallWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _)).WillByDefault(Return(true));   // Default action #1
+  ON_CALL(foo_, Bar2(1, _)).WillByDefault(Return(false));  // Default action #2
+
+  EXPECT_CALL(foo_, Bar2(2, 2));
+  foo_.Bar2(1, 0);  // Unexpected call, takes default action #2.
+  foo_.Bar2(0, 0);  // Unexpected call, takes default action #1.
+  foo_.Bar2(2, 2);  // Expected call.
+}
+
+TEST_F(GMockOutputTest, ExcessiveCallWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _)).WillByDefault(Return(true));   // Default action #1
+  ON_CALL(foo_, Bar2(1, _)).WillByDefault(Return(false));  // Default action #2
+
+  EXPECT_CALL(foo_, Bar2(2, 2));
+  EXPECT_CALL(foo_, Bar2(1, 1));
+
+  foo_.Bar2(2, 2);  // Expected call.
+  foo_.Bar2(2, 2);  // Excessive call, takes default action #1.
+  foo_.Bar2(1, 1);  // Expected call.
+  foo_.Bar2(1, 1);  // Excessive call, takes default action #2.
+}
+
+TEST_F(GMockOutputTest, UninterestingCallWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _)).WillByDefault(Return(true));   // Default action #1
+  ON_CALL(foo_, Bar2(1, _)).WillByDefault(Return(false));  // Default action #2
+
+  foo_.Bar2(2, 2);  // Uninteresting call, takes default action #1.
+  foo_.Bar2(1, 1);  // Uninteresting call, takes default action #2.
+}
+
+TEST_F(GMockOutputTest, ExplicitActionsRunOutWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _)).WillByDefault(Return(true));  // Default action #1
+
+  EXPECT_CALL(foo_, Bar2(_, _)).Times(2).WillOnce(Return(false));
+  foo_.Bar2(2, 2);
+  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
+}
+
+TEST_F(GMockOutputTest, CatchesLeakedMocks) {
+  MockFoo* foo1 = new MockFoo;
+  MockFoo* foo2 = new MockFoo;
+
+  // Invokes ON_CALL on foo1.
+  ON_CALL(*foo1, Bar(_, _, _)).WillByDefault(Return('a'));
+
+  // Invokes EXPECT_CALL on foo2.
+  EXPECT_CALL(*foo2, Bar2(_, _));
+  EXPECT_CALL(*foo2, Bar2(1, _));
+  EXPECT_CALL(*foo2, Bar3(_, _)).Times(AnyNumber());
+  foo2->Bar2(2, 1);
+  foo2->Bar2(1, 1);
+
+  // Both foo1 and foo2 are deliberately leaked.
+}
+
+MATCHER_P2(IsPair, first, second, "") {
+  return Value(arg.first, first) && Value(arg.second, second);
+}
+
+TEST_F(GMockOutputTest, PrintsMatcher) {
+  const testing::Matcher<int> m1 = Ge(48);
+  EXPECT_THAT((std::pair<int, bool>(42, true)), IsPair(m1, true));
+}
+
+void TestCatchesLeakedMocksInAdHocTests() {
+  MockFoo* foo = new MockFoo;
+
+  // Invokes EXPECT_CALL on foo.
+  EXPECT_CALL(*foo, Bar2(_, _));
+  foo->Bar2(2, 1);
+
+  // foo is deliberately leaked.
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleMock(&argc, argv);
+  // Ensures that the tests pass no matter what value of
+  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
+  GMOCK_FLAG_SET(catch_leaked_mocks, true);
+  GMOCK_FLAG_SET(verbose, "warning");
+
+  TestCatchesLeakedMocksInAdHocTests();
+  return RUN_ALL_TESTS();
+}
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
diff --git a/3rd-party/googletest/googlemock/test/gmock_output_test_golden.txt b/3rd-party/googletest/googlemock/test/gmock_output_test_golden.txt
new file mode 100644
index 0000000..ca88af0
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_output_test_golden.txt
@@ -0,0 +1,335 @@
+[ RUN      ] GMockOutputTest.ExpectedCall
+
+FILE:#: EXPECT_CALL(foo_, Bar2(0, _)) invoked
+Stack trace:
+
+FILE:#: Mock function call matches EXPECT_CALL(foo_, Bar2(0, _))...
+    Function call: Bar2(0, 0)
+          Returns: false
+Stack trace:
+[       OK ] GMockOutputTest.ExpectedCall
+[ RUN      ] GMockOutputTest.ExpectedCallToVoidFunction
+
+FILE:#: EXPECT_CALL(foo_, Bar3(0, _)) invoked
+Stack trace:
+
+FILE:#: Mock function call matches EXPECT_CALL(foo_, Bar3(0, _))...
+    Function call: Bar3(0, 0)
+Stack trace:
+[       OK ] GMockOutputTest.ExpectedCallToVoidFunction
+[ RUN      ] GMockOutputTest.ExplicitActionsRunOut
+
+GMOCK WARNING:
+FILE:#: Too few actions specified in EXPECT_CALL(foo_, Bar2(_, _))...
+Expected to be called twice, but has only 1 WillOnce().
+GMOCK WARNING:
+FILE:#: Actions ran out in EXPECT_CALL(foo_, Bar2(_, _))...
+Called 2 times, but only 1 WillOnce() is specified - returning default value.
+Stack trace:
+[       OK ] GMockOutputTest.ExplicitActionsRunOut
+[ RUN      ] GMockOutputTest.UnexpectedCall
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(0, _))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnexpectedCall
+[ RUN      ] GMockOutputTest.UnexpectedCallToVoidFunction
+unknown file: Failure
+
+Unexpected mock function call - returning directly.
+    Function call: Bar3(1, 0)
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar3(0, _))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnexpectedCallToVoidFunction
+[ RUN      ] GMockOutputTest.ExcessiveCall
+FILE:#: Failure
+Mock function called more times than expected - returning default value.
+    Function call: Bar2(0, 1)
+          Returns: false
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+
+[  FAILED  ] GMockOutputTest.ExcessiveCall
+[ RUN      ] GMockOutputTest.ExcessiveCallToVoidFunction
+FILE:#: Failure
+Mock function called more times than expected - returning directly.
+    Function call: Bar3(0, 1)
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+
+[  FAILED  ] GMockOutputTest.ExcessiveCallToVoidFunction
+[ RUN      ] GMockOutputTest.UninterestingCall
+
+GMOCK WARNING:
+Uninteresting mock function call - returning default value.
+    Function call: Bar2(0, 1)
+          Returns: false
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+[       OK ] GMockOutputTest.UninterestingCall
+[ RUN      ] GMockOutputTest.UninterestingCallToVoidFunction
+
+GMOCK WARNING:
+Uninteresting mock function call - returning directly.
+    Function call: Bar3(0, 1)
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+[       OK ] GMockOutputTest.UninterestingCallToVoidFunction
+[ RUN      ] GMockOutputTest.RetiredExpectation
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 1)
+          Returns: false
+Google Mock tried the following 2 expectations, but none matched:
+
+FILE:#: tried expectation #0: EXPECT_CALL(foo_, Bar2(_, _))...
+         Expected: the expectation is active
+           Actual: it is retired
+         Expected: to be called once
+           Actual: called once - saturated and retired
+FILE:#: tried expectation #1: EXPECT_CALL(foo_, Bar2(0, 0))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+  Expected arg #1: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.RetiredExpectation
+[ RUN      ] GMockOutputTest.UnsatisfiedPrerequisite
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 2 expectations, but none matched:
+
+FILE:#: tried expectation #0: EXPECT_CALL(foo_, Bar2(0, 0))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+FILE:#: tried expectation #1: EXPECT_CALL(foo_, Bar2(1, _))...
+         Expected: all pre-requisites are satisfied
+           Actual: the following immediate pre-requisites are not satisfied:
+FILE:#: pre-requisite #0
+                   (end of pre-requisites)
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisite
+[ RUN      ] GMockOutputTest.UnsatisfiedPrerequisites
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 2 expectations, but none matched:
+
+FILE:#: tried expectation #0: EXPECT_CALL(foo_, Bar2(0, 0))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+FILE:#: tried expectation #1: EXPECT_CALL(foo_, Bar2(1, _))...
+         Expected: all pre-requisites are satisfied
+           Actual: the following immediate pre-requisites are not satisfied:
+FILE:#: pre-requisite #0
+FILE:#: pre-requisite #1
+                   (end of pre-requisites)
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisites
+[ RUN      ] GMockOutputTest.UnsatisfiedWith
+FILE:#: Failure
+Actual function call count doesn't match EXPECT_CALL(foo_, Bar2(_, _))...
+    Expected args: are a pair where the first >= the second
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnsatisfiedWith
+[ RUN      ] GMockOutputTest.UnsatisfiedExpectation
+FILE:#: Failure
+Actual function call count doesn't match EXPECT_CALL(foo_, Bar2(0, _))...
+         Expected: to be called twice
+           Actual: called once - unsatisfied and active
+
+FILE:#: Failure
+Actual function call count doesn't match EXPECT_CALL(foo_, Bar(_, _, _))...
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnsatisfiedExpectation
+[ RUN      ] GMockOutputTest.MismatchArguments
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar(@0x# "Ho", 0, -0.1)
+          Returns: '\0'
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar(Ref(s), _, Ge(0)))...
+  Expected arg #0: references the variable @0x# "Hi"
+           Actual: "Ho", which is located @0x#
+  Expected arg #2: is >= 0
+           Actual: -0.1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.MismatchArguments
+[ RUN      ] GMockOutputTest.MismatchWith
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(2, 3)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))...
+    Expected args: are a pair where the first >= the second
+           Actual: don't match
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.MismatchWith
+[ RUN      ] GMockOutputTest.MismatchArgumentsAndWith
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 3)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))...
+  Expected arg #0: is >= 2
+           Actual: 1
+    Expected args: are a pair where the first >= the second
+           Actual: don't match
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.MismatchArgumentsAndWith
+[ RUN      ] GMockOutputTest.UnexpectedCallWithDefaultAction
+unknown file: Failure
+
+Unexpected mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(2, 2))...
+  Expected arg #0: is equal to 2
+           Actual: 1
+  Expected arg #1: is equal to 2
+           Actual: 0
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+unknown file: Failure
+
+Unexpected mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(0, 0)
+          Returns: true
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(2, 2))...
+  Expected arg #0: is equal to 2
+           Actual: 0
+  Expected arg #1: is equal to 2
+           Actual: 0
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+
+[  FAILED  ] GMockOutputTest.UnexpectedCallWithDefaultAction
+[ RUN      ] GMockOutputTest.ExcessiveCallWithDefaultAction
+FILE:#: Failure
+Mock function called more times than expected - taking default action specified at:
+FILE:#:
+    Function call: Bar2(2, 2)
+          Returns: true
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+
+FILE:#: Failure
+Mock function called more times than expected - taking default action specified at:
+FILE:#:
+    Function call: Bar2(1, 1)
+          Returns: false
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+
+[  FAILED  ] GMockOutputTest.ExcessiveCallWithDefaultAction
+[ RUN      ] GMockOutputTest.UninterestingCallWithDefaultAction
+
+GMOCK WARNING:
+Uninteresting mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(2, 2)
+          Returns: true
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+
+GMOCK WARNING:
+Uninteresting mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(1, 1)
+          Returns: false
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+[       OK ] GMockOutputTest.UninterestingCallWithDefaultAction
+[ RUN      ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
+
+GMOCK WARNING:
+FILE:#: Too few actions specified in EXPECT_CALL(foo_, Bar2(_, _))...
+Expected to be called twice, but has only 1 WillOnce().
+GMOCK WARNING:
+FILE:#: Actions ran out in EXPECT_CALL(foo_, Bar2(_, _))...
+Called 2 times, but only 1 WillOnce() is specified - taking default action specified at:
+FILE:#:
+Stack trace:
+[       OK ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
+[ RUN      ] GMockOutputTest.CatchesLeakedMocks
+[       OK ] GMockOutputTest.CatchesLeakedMocks
+[ RUN      ] GMockOutputTest.PrintsMatcher
+FILE:#: Failure
+Value of: (std::pair<int, bool>(42, true))
+Expected: is pair (first: is >= 48, second: true)
+  Actual: (42, true) (of type std::pair<int,bool>)
+
+[  FAILED  ] GMockOutputTest.PrintsMatcher
+[  FAILED  ] GMockOutputTest.UnexpectedCall
+[  FAILED  ] GMockOutputTest.UnexpectedCallToVoidFunction
+[  FAILED  ] GMockOutputTest.ExcessiveCall
+[  FAILED  ] GMockOutputTest.ExcessiveCallToVoidFunction
+[  FAILED  ] GMockOutputTest.RetiredExpectation
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisite
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisites
+[  FAILED  ] GMockOutputTest.UnsatisfiedWith
+[  FAILED  ] GMockOutputTest.UnsatisfiedExpectation
+[  FAILED  ] GMockOutputTest.MismatchArguments
+[  FAILED  ] GMockOutputTest.MismatchWith
+[  FAILED  ] GMockOutputTest.MismatchArgumentsAndWith
+[  FAILED  ] GMockOutputTest.UnexpectedCallWithDefaultAction
+[  FAILED  ] GMockOutputTest.ExcessiveCallWithDefaultAction
+[  FAILED  ] GMockOutputTest.PrintsMatcher
+
+
+FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
+FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
+FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
+ERROR: 3 leaked mock objects found at program exit. Expectations on a mock object are verified when the object is destructed. Leaking a mock means that its expectations aren't verified, which is usually a test bug. If you really intend to leak a mock, you can suppress this error using testing::Mock::AllowLeak(mock_object), or you may use a fake or stub instead of a mock.
diff --git a/3rd-party/googletest/googlemock/test/gmock_stress_test.cc b/3rd-party/googletest/googlemock/test/gmock_stress_test.cc
new file mode 100644
index 0000000..9e42cd9
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_stress_test.cc
@@ -0,0 +1,227 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests that Google Mock constructs can be used in a large number of
+// threads concurrently.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace {
+
+// From gtest-port.h.
+using ::testing::internal::ThreadWithParam;
+
+// The maximum number of test threads (not including helper threads)
+// to create.
+const int kMaxTestThreads = 50;
+
+// How many times to repeat a task in a test thread.
+const int kRepeat = 50;
+
+class MockFoo {
+ public:
+  MOCK_METHOD1(Bar, int(int n));                                   // NOLINT
+  MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2));  // NOLINT
+};
+
+// Helper for waiting for the given thread to finish and then deleting it.
+template <typename T>
+void JoinAndDelete(ThreadWithParam<T>* t) {
+  t->Join();
+  delete t;
+}
+
+struct Dummy {};
+
+// Tests that different mock objects can be used in their respective
+// threads.  This should generate no Google Test failure.
+void TestConcurrentMockObjects(Dummy /* dummy */) {
+  // Creates a mock and does some typical operations on it.
+  MockFoo foo;
+  ON_CALL(foo, Bar(_)).WillByDefault(Return(1));
+  ON_CALL(foo, Baz(_, _)).WillByDefault(Return('b'));
+  ON_CALL(foo, Baz(_, "you")).WillByDefault(Return('a'));
+
+  EXPECT_CALL(foo, Bar(0)).Times(AtMost(3));
+  EXPECT_CALL(foo, Baz(_, _));
+  EXPECT_CALL(foo, Baz("hi", "you"))
+      .WillOnce(Return('z'))
+      .WillRepeatedly(DoDefault());
+
+  EXPECT_EQ(1, foo.Bar(0));
+  EXPECT_EQ(1, foo.Bar(0));
+  EXPECT_EQ('z', foo.Baz("hi", "you"));
+  EXPECT_EQ('a', foo.Baz("hi", "you"));
+  EXPECT_EQ('b', foo.Baz("hi", "me"));
+}
+
+// Tests invoking methods of the same mock object in multiple threads.
+
+struct Helper1Param {
+  MockFoo* mock_foo;
+  int* count;
+};
+
+void Helper1(Helper1Param param) {
+  for (int i = 0; i < kRepeat; i++) {
+    const char ch = param.mock_foo->Baz("a", "b");
+    if (ch == 'a') {
+      // It was an expected call.
+      (*param.count)++;
+    } else {
+      // It was an excessive call.
+      EXPECT_EQ('\0', ch);
+    }
+
+    // An unexpected call.
+    EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
+
+    // An uninteresting call.
+    EXPECT_EQ(1, param.mock_foo->Bar(5));
+  }
+}
+
+// This should generate 3*kRepeat + 1 failures in total.
+void TestConcurrentCallsOnSameObject(Dummy /* dummy */) {
+  MockFoo foo;
+
+  ON_CALL(foo, Bar(_)).WillByDefault(Return(1));
+  EXPECT_CALL(foo, Baz(_, "b")).Times(kRepeat).WillRepeatedly(Return('a'));
+  EXPECT_CALL(foo, Baz(_, "c"));  // Expected to be unsatisfied.
+
+  // This chunk of code should generate kRepeat failures about
+  // excessive calls, and 2*kRepeat failures about unexpected calls.
+  int count1 = 0;
+  const Helper1Param param = {&foo, &count1};
+  ThreadWithParam<Helper1Param>* const t =
+      new ThreadWithParam<Helper1Param>(Helper1, param, nullptr);
+
+  int count2 = 0;
+  const Helper1Param param2 = {&foo, &count2};
+  Helper1(param2);
+  JoinAndDelete(t);
+
+  EXPECT_EQ(kRepeat, count1 + count2);
+
+  // foo's destructor should generate one failure about unsatisfied
+  // expectation.
+}
+
+// Tests using the same mock object in multiple threads when the
+// expectations are partially ordered.
+
+void Helper2(MockFoo* foo) {
+  for (int i = 0; i < kRepeat; i++) {
+    foo->Bar(2);
+    foo->Bar(3);
+  }
+}
+
+// This should generate no Google Test failures.
+void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) {
+  MockFoo foo;
+  Sequence s1, s2;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(foo, Bar(0));
+    EXPECT_CALL(foo, Bar(1)).InSequence(s1, s2);
+  }
+
+  EXPECT_CALL(foo, Bar(2))
+      .Times(2 * kRepeat)
+      .InSequence(s1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar(3)).Times(2 * kRepeat).InSequence(s2);
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(foo, Bar(2)).InSequence(s1, s2);
+    EXPECT_CALL(foo, Bar(4));
+  }
+
+  foo.Bar(0);
+  foo.Bar(1);
+
+  ThreadWithParam<MockFoo*>* const t =
+      new ThreadWithParam<MockFoo*>(Helper2, &foo, nullptr);
+  Helper2(&foo);
+  JoinAndDelete(t);
+
+  foo.Bar(2);
+  foo.Bar(4);
+}
+
+// Tests using Google Mock constructs in many threads concurrently.
+TEST(StressTest, CanUseGMockWithThreads) {
+  void (*test_routines[])(Dummy dummy) = {
+      &TestConcurrentMockObjects,
+      &TestConcurrentCallsOnSameObject,
+      &TestPartiallyOrderedExpectationsWithThreads,
+  };
+
+  const int kRoutines = sizeof(test_routines) / sizeof(test_routines[0]);
+  const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
+  const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
+  ThreadWithParam<Dummy>* threads[kTestThreads] = {};
+  for (int i = 0; i < kTestThreads; i++) {
+    // Creates a thread to run the test function.
+    threads[i] = new ThreadWithParam<Dummy>(test_routines[i % kRoutines],
+                                            Dummy(), nullptr);
+    GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
+  }
+
+  // At this point, we have many threads running.
+  for (int i = 0; i < kTestThreads; i++) {
+    JoinAndDelete(threads[i]);
+  }
+
+  // Ensures that the correct number of failures have been reported.
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult& result = *info->result();
+  const int kExpectedFailures = (3 * kRepeat + 1) * kCopiesOfEachRoutine;
+  GTEST_CHECK_(kExpectedFailures == result.total_part_count())
+      << "Expected " << kExpectedFailures << " failures, but got "
+      << result.total_part_count();
+}
+
+}  // namespace
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  testing::InitGoogleMock(&argc, argv);
+
+  const int exit_code = RUN_ALL_TESTS();  // Expected to fail.
+  GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
+
+  printf("\nPASS\n");
+  return 0;
+}
diff --git a/3rd-party/googletest/googlemock/test/gmock_test.cc b/3rd-party/googletest/googlemock/test/gmock_test.cc
new file mode 100644
index 0000000..8cfff30
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_test.cc
@@ -0,0 +1,179 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests code in gmock.cc.
+
+#include "gmock/gmock.h"
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "gtest/internal/custom/gtest.h"
+
+#if !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+
+using testing::InitGoogleMock;
+
+// Verifies that calling InitGoogleMock() on argv results in new_argv,
+// and the gmock_verbose flag's value is set to expected_gmock_verbose.
+template <typename Char, int M, int N>
+void TestInitGoogleMock(const Char* (&argv)[M], const Char* (&new_argv)[N],
+                        const ::std::string& expected_gmock_verbose) {
+  const ::std::string old_verbose = GMOCK_FLAG_GET(verbose);
+
+  int argc = M - 1;
+  InitGoogleMock(&argc, const_cast<Char**>(argv));
+  ASSERT_EQ(N - 1, argc) << "The new argv has wrong number of elements.";
+
+  for (int i = 0; i < N; i++) {
+    EXPECT_STREQ(new_argv[i], argv[i]);
+  }
+
+  EXPECT_EQ(expected_gmock_verbose, GMOCK_FLAG_GET(verbose));
+  GMOCK_FLAG_SET(verbose, old_verbose);  // Restores the gmock_verbose flag.
+}
+
+TEST(InitGoogleMockTest, ParsesInvalidCommandLine) {
+  const char* argv[] = {nullptr};
+
+  const char* new_argv[] = {nullptr};
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG_GET(verbose));
+}
+
+TEST(InitGoogleMockTest, ParsesEmptyCommandLine) {
+  const char* argv[] = {"foo.exe", nullptr};
+
+  const char* new_argv[] = {"foo.exe", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG_GET(verbose));
+}
+
+TEST(InitGoogleMockTest, ParsesSingleFlag) {
+  const char* argv[] = {"foo.exe", "--gmock_verbose=info", nullptr};
+
+  const char* new_argv[] = {"foo.exe", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, "info");
+}
+
+TEST(InitGoogleMockTest, ParsesMultipleFlags) {
+  int old_default_behavior = GMOCK_FLAG_GET(default_mock_behavior);
+  const wchar_t* argv[] = {L"foo.exe", L"--gmock_verbose=info",
+                           L"--gmock_default_mock_behavior=2", nullptr};
+
+  const wchar_t* new_argv[] = {L"foo.exe", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, "info");
+  EXPECT_EQ(2, GMOCK_FLAG_GET(default_mock_behavior));
+  EXPECT_NE(2, old_default_behavior);
+  GMOCK_FLAG_SET(default_mock_behavior, old_default_behavior);
+}
+
+TEST(InitGoogleMockTest, ParsesUnrecognizedFlag) {
+  const char* argv[] = {"foo.exe", "--non_gmock_flag=blah", nullptr};
+
+  const char* new_argv[] = {"foo.exe", "--non_gmock_flag=blah", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG_GET(verbose));
+}
+
+TEST(InitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
+  const char* argv[] = {"foo.exe", "--non_gmock_flag=blah",
+                        "--gmock_verbose=error", nullptr};
+
+  const char* new_argv[] = {"foo.exe", "--non_gmock_flag=blah", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, "error");
+}
+
+TEST(WideInitGoogleMockTest, ParsesInvalidCommandLine) {
+  const wchar_t* argv[] = {nullptr};
+
+  const wchar_t* new_argv[] = {nullptr};
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG_GET(verbose));
+}
+
+TEST(WideInitGoogleMockTest, ParsesEmptyCommandLine) {
+  const wchar_t* argv[] = {L"foo.exe", nullptr};
+
+  const wchar_t* new_argv[] = {L"foo.exe", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG_GET(verbose));
+}
+
+TEST(WideInitGoogleMockTest, ParsesSingleFlag) {
+  const wchar_t* argv[] = {L"foo.exe", L"--gmock_verbose=info", nullptr};
+
+  const wchar_t* new_argv[] = {L"foo.exe", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, "info");
+}
+
+TEST(WideInitGoogleMockTest, ParsesMultipleFlags) {
+  int old_default_behavior = GMOCK_FLAG_GET(default_mock_behavior);
+  const wchar_t* argv[] = {L"foo.exe", L"--gmock_verbose=info",
+                           L"--gmock_default_mock_behavior=2", nullptr};
+
+  const wchar_t* new_argv[] = {L"foo.exe", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, "info");
+  EXPECT_EQ(2, GMOCK_FLAG_GET(default_mock_behavior));
+  EXPECT_NE(2, old_default_behavior);
+  GMOCK_FLAG_SET(default_mock_behavior, old_default_behavior);
+}
+
+TEST(WideInitGoogleMockTest, ParsesUnrecognizedFlag) {
+  const wchar_t* argv[] = {L"foo.exe", L"--non_gmock_flag=blah", nullptr};
+
+  const wchar_t* new_argv[] = {L"foo.exe", L"--non_gmock_flag=blah", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG_GET(verbose));
+}
+
+TEST(WideInitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
+  const wchar_t* argv[] = {L"foo.exe", L"--non_gmock_flag=blah",
+                           L"--gmock_verbose=error", nullptr};
+
+  const wchar_t* new_argv[] = {L"foo.exe", L"--non_gmock_flag=blah", nullptr};
+
+  TestInitGoogleMock(argv, new_argv, "error");
+}
+
+#endif  // !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+
+// Makes sure Google Mock flags can be accessed in code.
+TEST(FlagTest, IsAccessibleInCode) {
+  bool dummy =
+      GMOCK_FLAG_GET(catch_leaked_mocks) && GMOCK_FLAG_GET(verbose).empty();
+  (void)dummy;  // Avoids the "unused local variable" warning.
+}
diff --git a/3rd-party/googletest/googlemock/test/gmock_test_utils.py b/3rd-party/googletest/googlemock/test/gmock_test_utils.py
new file mode 100755
index 0000000..edad1f7
--- /dev/null
+++ b/3rd-party/googletest/googlemock/test/gmock_test_utils.py
@@ -0,0 +1,91 @@
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for Google C++ Mocking Framework."""
+
+import os
+
+# pylint: disable=C6204
+from googletest.test import gtest_test_utils
+
+
+def GetSourceDir():
+  """Returns the absolute path of the directory where the .py files are."""
+
+  return gtest_test_utils.GetSourceDir()
+
+
+def GetTestExecutablePath(executable_name):
+  """Returns the absolute path of the test binary given its name.
+
+  The function will print a message and abort the program if the resulting file
+  doesn't exist.
+
+  Args:
+    executable_name: name of the test binary that the test script runs.
+
+  Returns:
+    The absolute path of the test binary.
+  """
+
+  return gtest_test_utils.GetTestExecutablePath(executable_name)
+
+
+def GetExitStatus(exit_code):
+  """Returns the argument to exit(), or -1 if exit() wasn't called.
+
+  Args:
+    exit_code: the result value of os.system(command).
+  """
+
+  if os.name == 'nt':
+    # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns
+    # the argument to exit() directly.
+    return exit_code
+  else:
+    # On Unix, os.WEXITSTATUS() must be used to extract the exit status
+    # from the result of os.system().
+    if os.WIFEXITED(exit_code):
+      return os.WEXITSTATUS(exit_code)
+    else:
+      return -1
+
+
+# Exposes utilities from gtest_test_utils.
+Subprocess = gtest_test_utils.Subprocess
+TestCase = gtest_test_utils.TestCase
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+PREMATURE_EXIT_FILE_ENV_VAR = gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR
+
+
+def Main():
+  """Runs the unit test."""
+
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/CMakeLists.txt b/3rd-party/googletest/googletest/CMakeLists.txt
new file mode 100644
index 0000000..dce6a7c
--- /dev/null
+++ b/3rd-party/googletest/googletest/CMakeLists.txt
@@ -0,0 +1,330 @@
+########################################################################
+# Note: CMake support is community-based. The maintainers do not use CMake
+# internally.
+#
+# CMake build script for Google Test.
+#
+# To run the tests for Google Test itself on Linux, use 'make test' or
+# ctest. You can select which tests to run using 'ctest -R regex'.
+# For more options, run 'ctest --help'.
+
+# When other libraries are using a shared version of runtime libraries,
+# Google Test also has to use one.
+option(
+  gtest_force_shared_crt
+  "Use shared (DLL) run-time lib even when Google Test is built as static lib."
+  OFF)
+
+option(gtest_build_tests "Build all of gtest's own tests." OFF)
+
+option(gtest_build_samples "Build gtest's sample programs." OFF)
+
+option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
+
+option(
+  gtest_hide_internal_symbols
+  "Build gtest with internal symbols hidden in shared libraries."
+  OFF)
+
+# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
+include(cmake/hermetic_build.cmake OPTIONAL)
+
+if (COMMAND pre_project_set_up_hermetic_build)
+  pre_project_set_up_hermetic_build()
+endif()
+
+########################################################################
+#
+# Project-wide settings.
+
+# Name of the project.
+#
+# CMake files in this project can refer to the root source directory
+# as ${gtest_SOURCE_DIR} and to the root binary directory as
+# ${gtest_BINARY_DIR}.
+# Language "C" is required for find_package(Threads).
+
+# Project version.
+
+cmake_minimum_required(VERSION 3.13)
+project(gtest VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
+
+if (COMMAND set_up_hermetic_build)
+  set_up_hermetic_build()
+endif()
+
+# These commands only run if this is the main project.
+if(CMAKE_PROJECT_NAME STREQUAL "gtest" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution")
+
+  # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
+  # make it prominent in the GUI.
+  option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
+
+else()
+
+  mark_as_advanced(
+    gtest_force_shared_crt
+    gtest_build_tests
+    gtest_build_samples
+    gtest_disable_pthreads
+    gtest_hide_internal_symbols)
+
+endif()
+
+
+if (gtest_hide_internal_symbols)
+  set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+  set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
+endif()
+
+# Define helper functions and macros used by Google Test.
+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(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}")
+  set(version_file "${generated_dir}/${cmake_package_name}ConfigVersion.cmake")
+  write_basic_package_version_file(${version_file} VERSION ${GOOGLETEST_VERSION} COMPATIBILITY AnyNewerVersion)
+  install(EXPORT ${targets_export_name}
+    COMPONENT "${PROJECT_NAME}"
+    NAMESPACE ${cmake_package_name}::
+    DESTINATION ${cmake_files_install_dir})
+  set(config_file "${generated_dir}/${cmake_package_name}Config.cmake")
+  configure_package_config_file("${gtest_SOURCE_DIR}/cmake/Config.cmake.in"
+    "${config_file}" INSTALL_DESTINATION ${cmake_files_install_dir})
+  install(FILES ${version_file} ${config_file}
+    COMPONENT "${PROJECT_NAME}"
+    DESTINATION ${cmake_files_install_dir})
+endif()
+
+# Where Google Test's .h files can be found.
+set(gtest_build_include_dirs
+  "${gtest_SOURCE_DIR}/include"
+  "${gtest_SOURCE_DIR}")
+include_directories(${gtest_build_include_dirs})
+
+########################################################################
+#
+# Defines the gtest & gtest_main libraries. User tests should link
+# with one of them.
+
+# Google Test libraries. We build them using more strict warnings than what
+# are used for other targets, to ensure that gtest can be compiled by a user
+# aggressive about warnings.
+cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
+set_target_properties(gtest PROPERTIES VERSION ${GOOGLETEST_VERSION})
+if(GTEST_HAS_ABSL)
+  target_compile_definitions(gtest PUBLIC GTEST_HAS_ABSL=1)
+  target_link_libraries(gtest PUBLIC
+    absl::failure_signal_handler
+    absl::stacktrace
+    absl::symbolize
+    absl::flags_parse
+    absl::flags_reflection
+    absl::flags_usage
+    absl::strings
+    absl::any
+    absl::optional
+    absl::variant
+    re2::re2
+  )
+endif()
+cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
+set_target_properties(gtest_main PROPERTIES VERSION ${GOOGLETEST_VERSION})
+string(REPLACE ";" "$<SEMICOLON>" dirs "${gtest_build_include_dirs}")
+target_include_directories(gtest SYSTEM INTERFACE
+  "$<BUILD_INTERFACE:${dirs}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+target_include_directories(gtest_main SYSTEM INTERFACE
+  "$<BUILD_INTERFACE:${dirs}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+if(CMAKE_SYSTEM_NAME MATCHES "QNX" AND CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 7.1)
+  target_link_libraries(gtest PUBLIC regex)
+endif()
+target_link_libraries(gtest_main PUBLIC gtest)
+
+########################################################################
+#
+# Install rules.
+install_project(gtest gtest_main)
+
+########################################################################
+#
+# Samples on how to link user tests with gtest or gtest_main.
+#
+# They are not built by default. To build them, set the
+# gtest_build_samples option to ON. You can do it by running ccmake
+# or specifying the -Dgtest_build_samples=ON flag when running cmake.
+
+if (gtest_build_samples)
+  cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
+  cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
+  cxx_executable(sample3_unittest samples gtest_main)
+  cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
+  cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
+  cxx_executable(sample6_unittest samples gtest_main)
+  cxx_executable(sample7_unittest samples gtest_main)
+  cxx_executable(sample8_unittest samples gtest_main)
+  cxx_executable(sample9_unittest samples gtest)
+  cxx_executable(sample10_unittest samples gtest)
+endif()
+
+########################################################################
+#
+# Google Test's own tests.
+#
+# You can skip this section if you aren't interested in testing
+# Google Test itself.
+#
+# The tests are not built by default. To build them, set the
+# gtest_build_tests option to ON. You can do it by running ccmake
+# or specifying the -Dgtest_build_tests=ON flag when running cmake.
+
+if (gtest_build_tests)
+  # This must be set in the root directory for the tests to be run by
+  # 'make test' or ctest.
+  enable_testing()
+
+  ############################################################
+  # C++ tests built with standard compiler flags.
+
+  cxx_test(googletest-death-test-test gtest_main)
+  cxx_test(gtest_environment_test gtest)
+  cxx_test(googletest-filepath-test gtest_main)
+  cxx_test(googletest-listener-test gtest_main)
+  cxx_test(gtest_main_unittest gtest_main)
+  cxx_test(googletest-message-test gtest_main)
+  cxx_test(gtest_no_test_unittest gtest)
+  cxx_test(googletest-options-test gtest_main)
+  cxx_test(googletest-param-test-test gtest
+    test/googletest-param-test2-test.cc)
+  cxx_test(googletest-port-test gtest_main)
+  cxx_test(gtest_pred_impl_unittest gtest_main)
+  cxx_test(gtest_premature_exit_test gtest
+    test/gtest_premature_exit_test.cc)
+  cxx_test(googletest-printers-test gtest_main)
+  cxx_test(gtest_prod_test gtest_main
+    test/production.cc)
+  cxx_test(gtest_repeat_test gtest)
+  cxx_test(gtest_sole_header_test gtest_main)
+  cxx_test(gtest_stress_test gtest)
+  cxx_test(googletest-test-part-test gtest_main)
+  cxx_test(gtest_throw_on_failure_ex_test gtest)
+  cxx_test(gtest-typed-test_test gtest_main
+    test/gtest-typed-test2_test.cc)
+  cxx_test(gtest_unittest gtest_main)
+  cxx_test(gtest-unittest-api_test gtest)
+  cxx_test(gtest_skip_in_environment_setup_test gtest_main)
+  cxx_test(gtest_skip_test gtest_main)
+
+  ############################################################
+  # C++ tests built with non-standard compiler flags.
+
+  # MSVC 7.1 does not support STL with exceptions disabled.
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+    cxx_library(gtest_no_exception "${cxx_no_exception}"
+      src/gtest-all.cc)
+    cxx_library(gtest_main_no_exception "${cxx_no_exception}"
+      src/gtest-all.cc src/gtest_main.cc)
+  endif()
+  cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
+    src/gtest-all.cc src/gtest_main.cc)
+
+  cxx_test_with_flags(gtest-death-test_ex_nocatch_test
+    "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
+    gtest test/googletest-death-test_ex_test.cc)
+  cxx_test_with_flags(gtest-death-test_ex_catch_test
+    "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
+    gtest test/googletest-death-test_ex_test.cc)
+
+  cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
+    gtest_main_no_rtti test/gtest_unittest.cc)
+
+  cxx_shared_library(gtest_dll "${cxx_default}"
+    src/gtest-all.cc src/gtest_main.cc)
+
+  cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
+    gtest_dll test/gtest_all_test.cc)
+  set_target_properties(gtest_dll_test_
+                        PROPERTIES
+                        COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+
+  ############################################################
+  # Python tests.
+
+  cxx_executable(googletest-break-on-failure-unittest_ test gtest)
+  py_test(googletest-break-on-failure-unittest)
+
+  py_test(gtest_skip_check_output_test)
+  py_test(gtest_skip_environment_check_output_test)
+
+  # Visual Studio .NET 2003 does not support STL with exceptions disabled.
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310) # 1310 is Visual Studio .NET 2003
+    cxx_executable_with_flags(
+      googletest-catch-exceptions-no-ex-test_
+      "${cxx_no_exception}"
+      gtest_main_no_exception
+      test/googletest-catch-exceptions-test_.cc)
+  endif()
+
+  cxx_executable_with_flags(
+    googletest-catch-exceptions-ex-test_
+    "${cxx_exception}"
+    gtest_main
+    test/googletest-catch-exceptions-test_.cc)
+  py_test(googletest-catch-exceptions-test)
+
+  cxx_executable(googletest-color-test_ test gtest)
+  py_test(googletest-color-test)
+
+  cxx_executable(googletest-env-var-test_ test gtest)
+  py_test(googletest-env-var-test)
+
+  cxx_executable(googletest-filter-unittest_ test gtest)
+  py_test(googletest-filter-unittest)
+
+  cxx_executable(gtest_help_test_ test gtest_main)
+  py_test(gtest_help_test)
+
+  cxx_executable(googletest-list-tests-unittest_ test gtest)
+  py_test(googletest-list-tests-unittest)
+
+  cxx_executable(googletest-output-test_ test gtest)
+  py_test(googletest-output-test --no_stacktrace_support)
+
+  cxx_executable(googletest-shuffle-test_ test gtest)
+  py_test(googletest-shuffle-test)
+
+  # MSVC 7.1 does not support STL with exceptions disabled.
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+    cxx_executable(googletest-throw-on-failure-test_ test gtest_no_exception)
+    set_target_properties(googletest-throw-on-failure-test_
+      PROPERTIES
+      COMPILE_FLAGS "${cxx_no_exception}")
+    py_test(googletest-throw-on-failure-test)
+  endif()
+
+  cxx_executable(googletest-uninitialized-test_ test gtest)
+  py_test(googletest-uninitialized-test)
+
+  cxx_executable(gtest_list_output_unittest_ test gtest)
+  py_test(gtest_list_output_unittest)
+
+  cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
+  cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
+  py_test(gtest_xml_outfiles_test)
+  py_test(googletest-json-outfiles-test)
+
+  cxx_executable(gtest_xml_output_unittest_ test gtest)
+  py_test(gtest_xml_output_unittest --no_stacktrace_support)
+  py_test(googletest-json-output-unittest --no_stacktrace_support)
+endif()
diff --git a/3rd-party/googletest/googletest/README.md b/3rd-party/googletest/googletest/README.md
new file mode 100644
index 0000000..a7d9aa3
--- /dev/null
+++ b/3rd-party/googletest/googletest/README.md
@@ -0,0 +1,231 @@
+### Generic Build Instructions
+
+#### Setup
+
+To build GoogleTest and your tests that use it, you need to tell your build
+system where to find its headers and source files. The exact way to do it
+depends on which build system you use, and is usually straightforward.
+
+### Build with CMake
+
+GoogleTest comes with a CMake build script
+([CMakeLists.txt](https://github.com/google/googletest/blob/main/CMakeLists.txt))
+that can be used on a wide range of platforms ("C" stands for cross-platform.).
+If you don't have CMake installed already, you can download it for free from
+<https://cmake.org/>.
+
+CMake works by generating native makefiles or build projects that can be used in
+the compiler environment of your choice. You can either build GoogleTest as a
+standalone project or it can be incorporated into an existing CMake build for
+another project.
+
+#### Standalone CMake Project
+
+When building GoogleTest as a standalone project, the typical workflow starts
+with
+
+```
+git clone https://github.com/google/googletest.git -b v1.15.0
+cd googletest        # Main directory of the cloned repository.
+mkdir build          # Create a directory to hold the build output.
+cd build
+cmake ..             # Generate native build scripts for GoogleTest.
+```
+
+The above command also includes GoogleMock by default. And so, if you want to
+build only GoogleTest, you should replace the last command with
+
+```
+cmake .. -DBUILD_GMOCK=OFF
+```
+
+If you are on a \*nix system, you should now see a Makefile in the current
+directory. Just type `make` to build GoogleTest. And then you can simply install
+GoogleTest if you are a system administrator.
+
+```
+make
+sudo make install    # Install in /usr/local/ by default
+```
+
+If you use Windows and have Visual Studio installed, a `gtest.sln` file and
+several `.vcproj` files will be created. You can then build them using Visual
+Studio.
+
+On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
+
+#### Incorporating Into An Existing CMake Project
+
+If you want to use GoogleTest in a project which already uses CMake, the easiest
+way is to get installed libraries and headers.
+
+*   Import GoogleTest by using `find_package` (or `pkg_check_modules`). For
+    example, if `find_package(GTest CONFIG REQUIRED)` succeeds, you can use the
+    libraries as `GTest::gtest`, `GTest::gmock`.
+
+And a more robust and flexible approach is to build GoogleTest as part of that
+project directly. This is done by making the GoogleTest source code available to
+the main build and adding it using CMake's `add_subdirectory()` command. This
+has the significant advantage that the same compiler and linker settings are
+used between GoogleTest and the rest of your project, so issues associated with
+using incompatible libraries (eg debug/release), etc. are avoided. This is
+particularly useful on Windows. Making GoogleTest's source code available to the
+main build can be done a few different ways:
+
+*   Download the GoogleTest source code manually and place it at a known
+    location. This is the least flexible approach and can make it more difficult
+    to use with continuous integration systems, etc.
+*   Embed the GoogleTest source code as a direct copy in the main project's
+    source tree. This is often the simplest approach, but is also the hardest to
+    keep up to date. Some organizations may not permit this method.
+*   Add GoogleTest as a git submodule or equivalent. This may not always be
+    possible or appropriate. Git submodules, for example, have their own set of
+    advantages and drawbacks.
+*   Use CMake to download GoogleTest as part of the build's configure step. This
+    approach doesn't have the limitations of the other methods.
+
+The last of the above methods is implemented with a small piece of CMake code
+that downloads and pulls the GoogleTest code into the main build.
+
+Just add to your `CMakeLists.txt`:
+
+```cmake
+include(FetchContent)
+FetchContent_Declare(
+  googletest
+  # Specify the commit you depend on and update it regularly.
+  URL https://github.com/google/googletest/archive/5376968f6948923e2411081fd9372e71a59d8e77.zip
+)
+# For Windows: Prevent overriding the parent project's compiler/linker settings
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+FetchContent_MakeAvailable(googletest)
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable(example example.cpp)
+target_link_libraries(example gtest_main)
+add_test(NAME example_test COMMAND example)
+```
+
+Note that this approach requires CMake 3.14 or later due to its use of the
+`FetchContent_MakeAvailable()` command.
+
+##### Visual Studio Dynamic vs Static Runtimes
+
+By default, new Visual Studio projects link the C runtimes dynamically but
+GoogleTest links them statically. This will generate an error that looks
+something like the following: gtest.lib(gtest-all.obj) : error LNK2038: mismatch
+detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value
+'MDd_DynamicDebug' in main.obj
+
+GoogleTest already has a CMake option for this: `gtest_force_shared_crt`
+
+Enabling this option will make gtest link the runtimes dynamically too, and
+match the project in which it is included.
+
+#### C++ Standard Version
+
+An environment that supports C++14 is required in order to successfully build
+GoogleTest. One way to ensure this is to specify the standard in the top-level
+project, for example by using the `set(CMAKE_CXX_STANDARD 14)` command along
+with `set(CMAKE_CXX_STANDARD_REQUIRED ON)`. If this is not feasible, for example
+in a C project using GoogleTest for validation, then it can be specified by
+adding it to the options for cmake via the`-DCMAKE_CXX_FLAGS` option.
+
+### Tweaking GoogleTest
+
+GoogleTest can be used in diverse environments. The default configuration may
+not work (or may not work well) out of the box in some environments. However,
+you can easily tweak GoogleTest by defining control macros on the compiler
+command line. Generally, these macros are named like `GTEST_XYZ` and you define
+them to either 1 or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below. For a complete list, see file
+[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/main/googletest/include/gtest/internal/gtest-port.h).
+
+### Multi-threaded Tests
+
+GoogleTest is thread-safe where the pthread library is available. After
+`#include <gtest/gtest.h>`, you can check the
+`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
+`#defined` to 1, no if it's undefined.).
+
+If GoogleTest doesn't correctly detect whether pthread is available in your
+environment, you can force it with
+
+```
+-DGTEST_HAS_PTHREAD=1
+```
+
+or
+
+```
+-DGTEST_HAS_PTHREAD=0
+```
+
+When GoogleTest uses pthread, you may need to add flags to your compiler and/or
+linker to select the pthread library, or you'll get link errors. If you use the
+CMake script, this is taken care of for you. If you use your own build script,
+you'll need to read your compiler and linker's manual to figure out what flags
+to add.
+
+### As a Shared Library (DLL)
+
+GoogleTest is compact, so most users can build and link it as a static library
+for the simplicity. You can choose to use GoogleTest as a shared library (known
+as a DLL on Windows) if you prefer.
+
+To compile *gtest* as a shared library, add
+
+```
+-DGTEST_CREATE_SHARED_LIBRARY=1
+```
+
+to the compiler flags. You'll also need to tell the linker to produce a shared
+library instead - consult your linker's manual for how to do it.
+
+To compile your *tests* that use the gtest shared library, add
+
+```
+-DGTEST_LINKED_AS_SHARED_LIBRARY=1
+```
+
+to the compiler flags.
+
+Note: while the above steps aren't technically necessary today when using some
+compilers (e.g. GCC), they may become necessary in the future, if we decide to
+improve the speed of loading the library (see
+<https://gcc.gnu.org/wiki/Visibility> for details). Therefore you are
+recommended to always add the above flags when using GoogleTest as a shared
+library. Otherwise a future release of GoogleTest may break your build script.
+
+### Avoiding Macro Name Clashes
+
+In C++, macros don't obey namespaces. Therefore two libraries that both define a
+macro of the same name will clash if you `#include` both definitions. In case a
+GoogleTest macro clashes with another library, you can force GoogleTest to
+rename its macro to avoid the conflict.
+
+Specifically, if both GoogleTest and some other code define macro FOO, you can
+add
+
+```
+-DGTEST_DONT_DEFINE_FOO=1
+```
+
+to the compiler flags to tell GoogleTest to change the macro's name from `FOO`
+to `GTEST_FOO`. Currently `FOO` can be `ASSERT_EQ`, `ASSERT_FALSE`, `ASSERT_GE`,
+`ASSERT_GT`, `ASSERT_LE`, `ASSERT_LT`, `ASSERT_NE`, `ASSERT_TRUE`,
+`EXPECT_FALSE`, `EXPECT_TRUE`, `FAIL`, `SUCCEED`, `TEST`, or `TEST_F`. For
+example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
+
+```
+GTEST_TEST(SomeTest, DoesThis) { ... }
+```
+
+instead of
+
+```
+TEST(SomeTest, DoesThis) { ... }
+```
+
+in order to define a test.
diff --git a/3rd-party/googletest/googletest/cmake/Config.cmake.in b/3rd-party/googletest/googletest/cmake/Config.cmake.in
new file mode 100644
index 0000000..3f70661
--- /dev/null
+++ b/3rd-party/googletest/googletest/cmake/Config.cmake.in
@@ -0,0 +1,13 @@
+@PACKAGE_INIT@
+include(CMakeFindDependencyMacro)
+if (@GTEST_HAS_PTHREAD@)
+  set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@)
+  find_dependency(Threads)
+endif()
+if (@GTEST_HAS_ABSL@)
+  find_dependency(absl)
+  find_dependency(re2)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
+check_required_components("@project_name@")
diff --git a/3rd-party/googletest/googletest/cmake/gtest.pc.in b/3rd-party/googletest/googletest/cmake/gtest.pc.in
new file mode 100644
index 0000000..b4148fa
--- /dev/null
+++ b/3rd-party/googletest/googletest/cmake/gtest.pc.in
@@ -0,0 +1,9 @@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: gtest
+Description: GoogleTest (without main() function)
+Version: @PROJECT_VERSION@
+URL: https://github.com/google/googletest
+Libs: -L${libdir} -lgtest @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
diff --git a/3rd-party/googletest/googletest/cmake/gtest_main.pc.in b/3rd-party/googletest/googletest/cmake/gtest_main.pc.in
new file mode 100644
index 0000000..38c88c5
--- /dev/null
+++ b/3rd-party/googletest/googletest/cmake/gtest_main.pc.in
@@ -0,0 +1,10 @@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: gtest_main
+Description: GoogleTest (with main() function)
+Version: @PROJECT_VERSION@
+URL: https://github.com/google/googletest
+Requires: gtest = @PROJECT_VERSION@
+Libs: -L${libdir} -lgtest_main @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
diff --git a/3rd-party/googletest/googletest/cmake/internal_utils.cmake b/3rd-party/googletest/googletest/cmake/internal_utils.cmake
new file mode 100644
index 0000000..580ac1c
--- /dev/null
+++ b/3rd-party/googletest/googletest/cmake/internal_utils.cmake
@@ -0,0 +1,334 @@
+# Defines functions and macros useful for building Google Test and
+# Google Mock.
+#
+# Note:
+#
+# - This file will be run twice when building Google Mock (once via
+#   Google Test's CMakeLists.txt, and once via Google Mock's).
+#   Therefore it shouldn't have any side effects other than defining
+#   the functions and macros.
+#
+# - The functions/macros defined in this file may depend on Google
+#   Test and Google Mock's option() definitions, and thus must be
+#   called *after* the options have been defined.
+
+# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
+#
+# This must be a macro(), as inside a function string() can only
+# update variables in the function scope.
+macro(fix_default_compiler_settings_)
+  if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC|Clang")
+    # For MSVC and Clang, CMake sets certain flags to defaults we want to
+    # override.
+    # This replacement code is taken from sample in the CMake Wiki at
+    # https://gitlab.kitware.com/cmake/community/wikis/FAQ#dynamic-replace.
+    foreach (flag_var
+             CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+             CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
+             CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+             CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
+        # When Google Test is built as a shared library, it should also use
+        # shared runtime libraries. Otherwise, it may end up with multiple
+        # copies of runtime library data in different modules, resulting in
+        # hard-to-find crashes. When it is built as a static library, it is
+        # preferable to use CRT as static libraries, as we don't have to rely
+        # on CRT DLLs being available. CMake always defaults to using shared
+        # CRT libraries, so we override that default here.
+        string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
+
+        # When using Ninja with Clang, static builds pass -D_DLL on Windows.
+        # This is incorrect and should not happen, so we fix that here.
+        string(REPLACE "-D_DLL" "" ${flag_var} "${${flag_var}}")
+      endif()
+
+      # We prefer more strict warning checking for building Google Test.
+      # Replaces /W3 with /W4 in defaults.
+      string(REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}")
+
+      # Prevent D9025 warning for targets that have exception handling
+      # turned off (/EHs-c- flag). Where required, exceptions are explicitly
+      # re-enabled using the cxx_exception_flags variable.
+      string(REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")
+    endforeach()
+  endif()
+endmacro()
+
+# Defines the compiler/linker flags used to build Google Test and
+# Google Mock. You can tweak these definitions to suit your need. A
+# variable's value is empty before it's explicitly assigned to.
+macro(config_compiler_and_linker)
+  # Note: pthreads on MinGW is not supported, even if available
+  # instead, we use windows threading primitives.
+  unset(GTEST_HAS_PTHREAD)
+  if (NOT gtest_disable_pthreads AND NOT MINGW)
+    # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
+    find_package(Threads)
+    if (CMAKE_USE_PTHREADS_INIT)
+      set(GTEST_HAS_PTHREAD ON)
+    endif()
+  endif()
+
+  fix_default_compiler_settings_()
+  if (MSVC)
+    # Newlines inside flags variables break CMake's NMake generator.
+    # TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
+    set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J")
+    set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
+    set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
+    set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-GR-")
+    # Suppress "unreachable code" warning,
+    # https://stackoverflow.com/questions/3232669 explains the issue.
+    set(cxx_base_flags "${cxx_base_flags} -wd4702")
+    # Ensure MSVC treats source files as UTF-8 encoded.
+    if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+      set(cxx_base_flags "${cxx_base_flags} -utf-8")
+    endif()
+    if (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
+      set(cxx_base_flags "${cxx_base_flags} /fp:precise -Wno-inconsistent-missing-override -Wno-microsoft-exception-spec -Wno-unused-function -Wno-unused-but-set-variable")
+    endif()
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
+      CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
+    set(cxx_base_flags "-Wall -Wshadow -Wconversion -Wundef")
+    set(cxx_exception_flags "-fexceptions")
+    set(cxx_no_exception_flags "-fno-exceptions")
+    set(cxx_strict_flags "-W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Winline -Wredundant-decls")
+    set(cxx_no_rtti_flags "-fno-rtti")
+    if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+      set(cxx_strict_flags "${cxx_strict_flags} -Wchar-subscripts")
+    endif()
+    if (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
+      set(cxx_base_flags "${cxx_base_flags} -Wno-implicit-float-size-conversion -ffp-model=precise")
+    endif()
+  elseif (CMAKE_COMPILER_IS_GNUCXX)
+    set(cxx_base_flags "-Wall -Wshadow -Wundef")
+    if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0)
+      set(cxx_base_flags "${cxx_base_flags} -Wno-error=dangling-else")
+    endif()
+    set(cxx_exception_flags "-fexceptions")
+    set(cxx_no_exception_flags "-fno-exceptions")
+    # Until version 4.3.2, GCC doesn't define a macro to indicate
+    # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
+    set(cxx_strict_flags
+      "-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
+    set(cxx_exception_flags "-features=except")
+    # Sun Pro doesn't provide macros to indicate whether exceptions and
+    # RTTI are enabled, so we define GTEST_HAS_* explicitly.
+    set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
+      CMAKE_CXX_COMPILER_ID STREQUAL "XL")
+    # CMake 2.8 changes Visual Age's compiler ID to "XL".
+    set(cxx_exception_flags "-qeh")
+    set(cxx_no_exception_flags "-qnoeh")
+    # Until version 9.0, Visual Age doesn't define a macro to indicate
+    # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
+    set(cxx_base_flags "-AA -mt")
+    set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
+    # RTTI can not be disabled in HP aCC compiler.
+    set(cxx_no_rtti_flags "")
+  endif()
+
+  # The pthreads library is available and allowed?
+  if (DEFINED GTEST_HAS_PTHREAD)
+    set(GTEST_HAS_PTHREAD_MACRO "-DGTEST_HAS_PTHREAD=1")
+  else()
+    set(GTEST_HAS_PTHREAD_MACRO "-DGTEST_HAS_PTHREAD=0")
+  endif()
+  set(cxx_base_flags "${cxx_base_flags} ${GTEST_HAS_PTHREAD_MACRO}")
+
+  # For building gtest's own tests and samples.
+  set(cxx_exception "${cxx_base_flags} ${cxx_exception_flags}")
+  set(cxx_no_exception
+    "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
+  set(cxx_default "${cxx_exception}")
+  set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
+
+  # For building the gtest libraries.
+  set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
+endmacro()
+
+# Defines the gtest & gtest_main libraries. User tests should link
+# with one of them.
+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}")
+  # Set the output directory for build artifacts.
+  set_target_properties(${name}
+    PROPERTIES
+    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
+    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
+    PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
+  # Make PDBs match library name.
+  get_target_property(pdb_debug_postfix ${name} DEBUG_POSTFIX)
+  set_target_properties(${name}
+    PROPERTIES
+    PDB_NAME "${name}"
+    PDB_NAME_DEBUG "${name}${pdb_debug_postfix}"
+    COMPILE_PDB_NAME "${name}"
+    COMPILE_PDB_NAME_DEBUG "${name}${pdb_debug_postfix}")
+
+  if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
+    target_compile_definitions(${name} INTERFACE
+      $<INSTALL_INTERFACE:GTEST_LINKED_AS_SHARED_LIBRARY=1>)
+  endif()
+  if (DEFINED GTEST_HAS_PTHREAD)
+    target_link_libraries(${name} PUBLIC Threads::Threads)
+  endif()
+
+  target_compile_features(${name} PUBLIC cxx_std_14)
+endfunction()
+
+########################################################################
+#
+# Helper functions for creating build targets.
+
+function(cxx_shared_library name cxx_flags)
+  cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endfunction()
+
+function(cxx_library name cxx_flags)
+  cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
+endfunction()
+
+# cxx_executable_with_flags(name cxx_flags libs srcs...)
+#
+# Creates a named C++ executable that depends on the given libraries and
+# is built from the given source files with the given compiler flags.
+function(cxx_executable_with_flags name cxx_flags libs)
+  add_executable(${name} ${ARGN})
+  if (MSVC)
+    # BigObj required for tests.
+    set(cxx_flags "${cxx_flags} -bigobj")
+  endif()
+  if (cxx_flags)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_FLAGS "${cxx_flags}")
+  endif()
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+  endif()
+  # To support mixing linking in static and dynamic libraries, link each
+  # library in with an extra call to target_link_libraries.
+  foreach (lib "${libs}")
+    target_link_libraries(${name} ${lib})
+  endforeach()
+endfunction()
+
+# cxx_executable(name dir lib srcs...)
+#
+# Creates a named target that depends on the given libs and is built
+# from the given source files. dir/name.cc is implicitly included in
+# the source file list.
+function(cxx_executable name dir libs)
+  cxx_executable_with_flags(
+    ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
+endfunction()
+
+if(gtest_build_tests)
+  find_package(Python3)
+endif()
+
+# cxx_test_with_flags(name cxx_flags libs srcs...)
+#
+# Creates a named C++ test that depends on the given libs and is built
+# from the given source files with the given compiler flags.
+function(cxx_test_with_flags name cxx_flags libs)
+  cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
+    add_test(NAME ${name} COMMAND "$<TARGET_FILE:${name}>")
+endfunction()
+
+# cxx_test(name libs srcs...)
+#
+# Creates a named test target that depends on the given libs and is
+# built from the given source files. Unlike cxx_test_with_flags,
+# test/name.cc is already implicitly included in the source file list.
+function(cxx_test name libs)
+  cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
+    "test/${name}.cc" ${ARGN})
+endfunction()
+
+# py_test(name)
+#
+# Creates a Python test with the given name whose main module is in
+# test/name.py. It does nothing if Python is not installed.
+function(py_test name)
+  if (NOT Python3_Interpreter_FOUND)
+    return()
+  endif()
+
+  get_cmake_property(is_multi "GENERATOR_IS_MULTI_CONFIG")
+  set(build_dir "${CMAKE_CURRENT_BINARY_DIR}")
+  if (is_multi)
+    set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
+  endif()
+
+  add_test(NAME ${name}
+      COMMAND Python3::Interpreter ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
+          --build_dir=${build_dir} ${ARGN})
+
+  # Make the Python import path consistent between Bazel and CMake.
+  set_tests_properties(${name} PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_SOURCE_DIR})
+endfunction()
+
+# install_project(targets...)
+#
+# Installs the specified targets and configures the associated pkgconfig files.
+function(install_project)
+  if(INSTALL_GTEST)
+    install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
+      COMPONENT "${PROJECT_NAME}"
+      DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+    # Install the project targets.
+    install(TARGETS ${ARGN}
+      EXPORT ${targets_export_name}
+      COMPONENT "${PROJECT_NAME}"
+      RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+      ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+      LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+    if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+      # Install PDBs.
+      foreach(t ${ARGN})
+        get_target_property(t_pdb_name ${t} COMPILE_PDB_NAME)
+        get_target_property(t_pdb_name_debug ${t} COMPILE_PDB_NAME_DEBUG)
+        get_target_property(t_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY)
+        install(FILES
+          "${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<$<CONFIG:Debug>:${t_pdb_name_debug}>$<$<NOT:$<CONFIG:Debug>>:${t_pdb_name}>.pdb"
+          COMPONENT "${PROJECT_NAME}"
+          DESTINATION ${CMAKE_INSTALL_LIBDIR}
+          OPTIONAL)
+      endforeach()
+    endif()
+    # Configure and install pkgconfig files.
+    foreach(t ${ARGN})
+      set(configured_pc "${generated_dir}/${t}.pc")
+      configure_file("${PROJECT_SOURCE_DIR}/cmake/${t}.pc.in"
+        "${configured_pc}" @ONLY)
+      install(FILES "${configured_pc}"
+        COMPONENT "${PROJECT_NAME}"
+        DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+    endforeach()
+  endif()
+endfunction()
diff --git a/3rd-party/googletest/googletest/cmake/libgtest.la.in b/3rd-party/googletest/googletest/cmake/libgtest.la.in
new file mode 100644
index 0000000..840c838
--- /dev/null
+++ b/3rd-party/googletest/googletest/cmake/libgtest.la.in
@@ -0,0 +1,21 @@
+# libgtest.la - a libtool library file
+# Generated by libtool (GNU libtool) 2.4.6
+
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Names of this library.
+library_names='libgtest.so'
+
+# Is this an already installed library?
+installed=yes
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=no
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='@CMAKE_INSTALL_FULL_LIBDIR@'
diff --git a/3rd-party/googletest/googletest/docs/README.md b/3rd-party/googletest/googletest/docs/README.md
new file mode 100644
index 0000000..1bc57b7
--- /dev/null
+++ b/3rd-party/googletest/googletest/docs/README.md
@@ -0,0 +1,4 @@
+# Content Moved
+
+We are working on updates to the GoogleTest documentation, which has moved to
+the top-level [docs](../../docs) directory.
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-assertion-result.h b/3rd-party/googletest/googletest/include/gtest/gtest-assertion-result.h
new file mode 100644
index 0000000..74eb2b1
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-assertion-result.h
@@ -0,0 +1,237 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file implements the AssertionResult type.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_ASSERTION_RESULT_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_ASSERTION_RESULT_H_
+
+#include <memory>
+#include <ostream>
+#include <string>
+#include <type_traits>
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-port.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251                                   \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+
+// C4800 is a level 3 warning in Visual Studio 2015 and earlier.
+// This warning is not emitted in Visual Studio 2017.
+// This warning is off by default starting in Visual Studio 2019 but can be
+// enabled with command-line options.
+#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
+#endif
+
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  //
+  // T must be contextually convertible to bool.
+  //
+  // The second parameter prevents this overload from being considered if
+  // the argument is implicitly convertible to AssertionResult. In that case
+  // we want AssertionResult's copy constructor to be used.
+  template <typename T>
+  explicit AssertionResult(
+      const T& success,
+      typename std::enable_if<
+          !std::is_convertible<T, AssertionResult>::value>::type*
+      /*enabler*/
+      = nullptr)
+      : success_(success) {}
+
+#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+  // Assignment operator.
+  AssertionResult& operator=(AssertionResult other) {
+    swap(other);
+    return *this;
+  }
+
+  // Returns true if and only if the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_ != nullptr ? message_->c_str() : "";
+  }
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T>
+  AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_ == nullptr) message_ = ::std::make_unique<::std::string>();
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Swap the contents of this AssertionResult with other.
+  void swap(AssertionResult& other);
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  std::unique_ptr< ::std::string> message_;
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_ASSERTION_RESULT_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-death-test.h b/3rd-party/googletest/googletest/include/gtest/gtest-death-test.h
new file mode 100644
index 0000000..3c61909
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-death-test.h
@@ -0,0 +1,345 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+namespace testing {
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+GTEST_API_ bool InDeathTestChild();
+
+}  // namespace internal
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//                  << "Failed to die on request " << i;
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// The final parameter to each of these macros is a matcher applied to any data
+// the sub-process wrote to stderr.  For compatibility with existing tests, a
+// bare string is interpreted as a regular expression matcher.
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows or Mac), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+
+// Asserts that a given `statement` causes the program to exit, with an
+// integer exit status that satisfies `predicate`, and emitting error output
+// that matches `matcher`.
+#define ASSERT_EXIT(statement, predicate, matcher) \
+  GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_)
+
+// Like `ASSERT_EXIT`, but continues on to successive tests in the
+// test suite, if any:
+#define EXPECT_EXIT(statement, predicate, matcher) \
+  GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given `statement` causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches `matcher`.
+#define ASSERT_DEATH(statement, matcher) \
+  ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
+
+// Like `ASSERT_DEATH`, but continues on to successive tests in the
+// test suite, if any:
+#define EXPECT_DEATH(statement, matcher) \
+  EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  ExitedWithCode(const ExitedWithCode&) = default;
+  void operator=(const ExitedWithCode& other) = delete;
+  bool operator()(int exit_status) const;
+
+ private:
+  const int exit_code_;
+};
+
+#if !defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_FUCHSIA)
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+
+ private:
+  const int signum_;
+};
+#endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+#ifdef NDEBUG
+
+#define EXPECT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+#define ASSERT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+#else
+
+#define EXPECT_DEBUG_DEATH(statement, regex) EXPECT_DEATH(statement, regex)
+
+#define ASSERT_DEBUG_DEATH(statement, regex) ASSERT_DEATH(statement, regex)
+
+#endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters
+// on systems that support death tests. This allows one to write such a macro on
+// a system that does not support death tests and be sure that it will compile
+// on a death-test supporting system. It is exposed publicly so that systems
+// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST
+// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and
+// ASSERT_DEATH_IF_SUPPORTED.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter if and only if EXPECT_DEATH compiles with it.
+//   regex_or_matcher -  A regex that a macro such as EXPECT_DEATH would use
+//                to test the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+#define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex_or_matcher, terminator)  \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
+  if (::testing::internal::AlwaysTrue()) {                                     \
+    GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
+                        << "Statement '" #statement "' cannot be verified.";   \
+  } else if (::testing::internal::AlwaysFalse()) {                             \
+    ::testing::internal::MakeDeathTestMatcher(regex_or_matcher);               \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);                 \
+    terminator;                                                                \
+  } else                                                                       \
+    ::testing::Message()
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#ifdef GTEST_HAS_DEATH_TEST
+#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+#else
+#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+  GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
+#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+  GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-matchers.h b/3rd-party/googletest/googletest/include/gtest/gtest-matchers.h
new file mode 100644
index 0000000..eae210e
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-matchers.h
@@ -0,0 +1,923 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file implements just enough of the matcher interface to allow
+// EXPECT_DEATH and friends to accept a matcher argument.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <type_traits>
+
+#include "gtest/gtest-printers.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+// MSVC warning C5046 is new as of VS2017 version 15.8.
+#if defined(_MSC_VER) && _MSC_VER >= 1915
+#define GTEST_MAYBE_5046_ 5046
+#else
+#define GTEST_MAYBE_5046_
+#endif
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(
+    4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by
+                              clients of class B */
+    /* Symbol involving type with internal linkage not defined */)
+
+namespace testing {
+
+// To implement a matcher Foo for type T, define:
+//   1. a class FooMatcherMatcher that implements the matcher interface:
+//     using is_gtest_matcher = void;
+//     bool MatchAndExplain(const T&, std::ostream*);
+//       (MatchResultListener* can also be used instead of std::ostream*)
+//     void DescribeTo(std::ostream*);
+//     void DescribeNegationTo(std::ostream*);
+//
+//   2. a factory function that creates a Matcher<T> object from a
+//      FooMatcherMatcher.
+
+class MatchResultListener {
+ public:
+  // Creates a listener object with the given underlying ostream.  The
+  // listener does not own the ostream, and does not dereference it
+  // in the constructor or destructor.
+  explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
+  virtual ~MatchResultListener() = 0;  // Makes this class abstract.
+
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x) {
+    if (stream_ != nullptr) *stream_ << x;
+    return *this;
+  }
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream() { return stream_; }
+
+  // Returns true if and only if the listener is interested in an explanation
+  // of the match result.  A matcher's MatchAndExplain() method can use
+  // this information to avoid generating the explanation when no one
+  // intends to hear it.
+  bool IsInterested() const { return stream_ != nullptr; }
+
+ private:
+  ::std::ostream* const stream_;
+
+  MatchResultListener(const MatchResultListener&) = delete;
+  MatchResultListener& operator=(const MatchResultListener&) = delete;
+};
+
+inline MatchResultListener::~MatchResultListener() = default;
+
+// An instance of a subclass of this knows how to describe itself as a
+// matcher.
+class GTEST_API_ MatcherDescriberInterface {
+ public:
+  virtual ~MatcherDescriberInterface() = default;
+
+  // Describes this matcher to an ostream.  The function should print
+  // a verb phrase that describes the property a value matching this
+  // matcher should have.  The subject of the verb phrase is the value
+  // being matched.  For example, the DescribeTo() method of the Gt(7)
+  // matcher prints "is greater than 7".
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.  For
+  // example, if the description of this matcher is "is greater than
+  // 7", the negated description could be "is not greater than 7".
+  // You are not required to override this when implementing
+  // MatcherInterface, but it is highly advised so that your matcher
+  // can produce good error messages.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not (";
+    DescribeTo(os);
+    *os << ")";
+  }
+};
+
+// The implementation of a matcher.
+template <typename T>
+class MatcherInterface : public MatcherDescriberInterface {
+ public:
+  // Returns true if and only if the matcher matches x; also explains the
+  // match result to 'listener' if necessary (see the next paragraph), in
+  // the form of a non-restrictive relative clause ("which ...",
+  // "whose ...", etc) that describes x.  For example, the
+  // MatchAndExplain() method of the Pointee(...) matcher should
+  // generate an explanation like "which points to ...".
+  //
+  // Implementations of MatchAndExplain() should add an explanation of
+  // the match result *if and only if* they can provide additional
+  // information that's not already present (or not obvious) in the
+  // print-out of x and the matcher's description.  Whether the match
+  // succeeds is not a factor in deciding whether an explanation is
+  // needed, as sometimes the caller needs to print a failure message
+  // when the match succeeds (e.g. when the matcher is used inside
+  // Not()).
+  //
+  // For example, a "has at least 10 elements" matcher should explain
+  // what the actual element count is, regardless of the match result,
+  // as it is useful information to the reader; on the other hand, an
+  // "is empty" matcher probably only needs to explain what the actual
+  // size is when the match fails, as it's redundant to say that the
+  // size is 0 when the value is already known to be empty.
+  //
+  // You should override this method when defining a new matcher.
+  //
+  // It's the responsibility of the caller (Google Test) to guarantee
+  // that 'listener' is not NULL.  This helps to simplify a matcher's
+  // implementation when it doesn't care about the performance, as it
+  // can talk to 'listener' without checking its validity first.
+  // However, in order to implement dummy listeners efficiently,
+  // listener->stream() may be NULL.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Inherits these methods from MatcherDescriberInterface:
+  //   virtual void DescribeTo(::std::ostream* os) const = 0;
+  //   virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+
+namespace internal {
+
+// A match result listener that ignores the explanation.
+class DummyMatchResultListener : public MatchResultListener {
+ public:
+  DummyMatchResultListener() : MatchResultListener(nullptr) {}
+
+ private:
+  DummyMatchResultListener(const DummyMatchResultListener&) = delete;
+  DummyMatchResultListener& operator=(const DummyMatchResultListener&) = delete;
+};
+
+// A match result listener that forwards the explanation to a given
+// ostream.  The difference between this and MatchResultListener is
+// that the former is concrete.
+class StreamMatchResultListener : public MatchResultListener {
+ public:
+  explicit StreamMatchResultListener(::std::ostream* os)
+      : MatchResultListener(os) {}
+
+ private:
+  StreamMatchResultListener(const StreamMatchResultListener&) = delete;
+  StreamMatchResultListener& operator=(const StreamMatchResultListener&) =
+      delete;
+};
+
+struct SharedPayloadBase {
+  std::atomic<int> ref{1};
+  void Ref() { ref.fetch_add(1, std::memory_order_relaxed); }
+  bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; }
+};
+
+template <typename T>
+struct SharedPayload : SharedPayloadBase {
+  explicit SharedPayload(const T& v) : value(v) {}
+  explicit SharedPayload(T&& v) : value(std::move(v)) {}
+
+  static void Destroy(SharedPayloadBase* shared) {
+    delete static_cast<SharedPayload*>(shared);
+  }
+
+  T value;
+};
+
+// An internal class for implementing Matcher<T>, which will derive
+// from it.  We put functionalities common to all Matcher<T>
+// specializations here to avoid code duplication.
+template <typename T>
+class MatcherBase : private MatcherDescriberInterface {
+ public:
+  // Returns true if and only if the matcher matches x; also explains the
+  // match result to 'listener'.
+  bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
+    GTEST_CHECK_(vtable_ != nullptr);
+    return vtable_->match_and_explain(*this, x, listener);
+  }
+
+  // Returns true if and only if this matcher matches x.
+  bool Matches(const T& x) const {
+    DummyMatchResultListener dummy;
+    return MatchAndExplain(x, &dummy);
+  }
+
+  // Describes this matcher to an ostream.
+  void DescribeTo(::std::ostream* os) const final {
+    GTEST_CHECK_(vtable_ != nullptr);
+    vtable_->describe(*this, os, false);
+  }
+
+  // Describes the negation of this matcher to an ostream.
+  void DescribeNegationTo(::std::ostream* os) const final {
+    GTEST_CHECK_(vtable_ != nullptr);
+    vtable_->describe(*this, os, true);
+  }
+
+  // Explains why x matches, or doesn't match, the matcher.
+  void ExplainMatchResultTo(const T& x, ::std::ostream* os) const {
+    StreamMatchResultListener listener(os);
+    MatchAndExplain(x, &listener);
+  }
+
+  // Returns the describer for this matcher object; retains ownership
+  // of the describer, which is only guaranteed to be alive when
+  // this matcher object is alive.
+  const MatcherDescriberInterface* GetDescriber() const {
+    if (vtable_ == nullptr) return nullptr;
+    return vtable_->get_describer(*this);
+  }
+
+ protected:
+  MatcherBase() : vtable_(nullptr), buffer_() {}
+
+  // Constructs a matcher from its implementation.
+  template <typename U>
+  explicit MatcherBase(const MatcherInterface<U>* impl)
+      : vtable_(nullptr), buffer_() {
+    Init(impl);
+  }
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  MatcherBase(M&& m) : vtable_(nullptr), buffer_() {  // NOLINT
+    Init(std::forward<M>(m));
+  }
+
+  MatcherBase(const MatcherBase& other)
+      : vtable_(other.vtable_), buffer_(other.buffer_) {
+    if (IsShared()) buffer_.shared->Ref();
+  }
+
+  MatcherBase& operator=(const MatcherBase& other) {
+    if (this == &other) return *this;
+    Destroy();
+    vtable_ = other.vtable_;
+    buffer_ = other.buffer_;
+    if (IsShared()) buffer_.shared->Ref();
+    return *this;
+  }
+
+  MatcherBase(MatcherBase&& other)
+      : vtable_(other.vtable_), buffer_(other.buffer_) {
+    other.vtable_ = nullptr;
+  }
+
+  MatcherBase& operator=(MatcherBase&& other) {
+    if (this == &other) return *this;
+    Destroy();
+    vtable_ = other.vtable_;
+    buffer_ = other.buffer_;
+    other.vtable_ = nullptr;
+    return *this;
+  }
+
+  ~MatcherBase() override { Destroy(); }
+
+ private:
+  struct VTable {
+    bool (*match_and_explain)(const MatcherBase&, const T&,
+                              MatchResultListener*);
+    void (*describe)(const MatcherBase&, std::ostream*, bool negation);
+    // Returns the captured object if it implements the interface, otherwise
+    // returns the MatcherBase itself.
+    const MatcherDescriberInterface* (*get_describer)(const MatcherBase&);
+    // Called on shared instances when the reference count reaches 0.
+    void (*shared_destroy)(SharedPayloadBase*);
+  };
+
+  bool IsShared() const {
+    return vtable_ != nullptr && vtable_->shared_destroy != nullptr;
+  }
+
+  // If the implementation uses a listener, call that.
+  template <typename P>
+  static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
+                                  MatchResultListener* listener)
+      -> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) {
+    return P::Get(m).MatchAndExplain(value, listener->stream());
+  }
+
+  template <typename P>
+  static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
+                                  MatchResultListener* listener)
+      -> decltype(P::Get(m).MatchAndExplain(value, listener)) {
+    return P::Get(m).MatchAndExplain(value, listener);
+  }
+
+  template <typename P>
+  static void DescribeImpl(const MatcherBase& m, std::ostream* os,
+                           bool negation) {
+    if (negation) {
+      P::Get(m).DescribeNegationTo(os);
+    } else {
+      P::Get(m).DescribeTo(os);
+    }
+  }
+
+  template <typename P>
+  static const MatcherDescriberInterface* GetDescriberImpl(
+      const MatcherBase& m) {
+    // If the impl is a MatcherDescriberInterface, then return it.
+    // Otherwise use MatcherBase itself.
+    // This allows us to implement the GetDescriber() function without support
+    // from the impl, but some users really want to get their impl back when
+    // they call GetDescriber().
+    // We use std::get on a tuple as a workaround of not having `if constexpr`.
+    return std::get<(
+        std::is_convertible<decltype(&P::Get(m)),
+                            const MatcherDescriberInterface*>::value
+            ? 1
+            : 0)>(std::make_tuple(&m, &P::Get(m)));
+  }
+
+  template <typename P>
+  const VTable* GetVTable() {
+    static constexpr VTable kVTable = {&MatchAndExplainImpl<P>,
+                                       &DescribeImpl<P>, &GetDescriberImpl<P>,
+                                       P::shared_destroy};
+    return &kVTable;
+  }
+
+  union Buffer {
+    // Add some types to give Buffer some common alignment/size use cases.
+    void* ptr;
+    double d;
+    int64_t i;
+    // And add one for the out-of-line cases.
+    SharedPayloadBase* shared;
+  };
+
+  void Destroy() {
+    if (IsShared() && buffer_.shared->Unref()) {
+      vtable_->shared_destroy(buffer_.shared);
+    }
+  }
+
+  template <typename M>
+  static constexpr bool IsInlined() {
+    return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) &&
+           std::is_trivially_copy_constructible<M>::value &&
+           std::is_trivially_destructible<M>::value;
+  }
+
+  template <typename M, bool = MatcherBase::IsInlined<M>()>
+  struct ValuePolicy {
+    static const M& Get(const MatcherBase& m) {
+      // When inlined along with Init, need to be explicit to avoid violating
+      // strict aliasing rules.
+      const M* ptr =
+          static_cast<const M*>(static_cast<const void*>(&m.buffer_));
+      return *ptr;
+    }
+    static void Init(MatcherBase& m, M impl) {
+      ::new (static_cast<void*>(&m.buffer_)) M(impl);
+    }
+    static constexpr auto shared_destroy = nullptr;
+  };
+
+  template <typename M>
+  struct ValuePolicy<M, false> {
+    using Shared = SharedPayload<M>;
+    static const M& Get(const MatcherBase& m) {
+      return static_cast<Shared*>(m.buffer_.shared)->value;
+    }
+    template <typename Arg>
+    static void Init(MatcherBase& m, Arg&& arg) {
+      m.buffer_.shared = new Shared(std::forward<Arg>(arg));
+    }
+    static constexpr auto shared_destroy = &Shared::Destroy;
+  };
+
+  template <typename U, bool B>
+  struct ValuePolicy<const MatcherInterface<U>*, B> {
+    using M = const MatcherInterface<U>;
+    using Shared = SharedPayload<std::unique_ptr<M>>;
+    static const M& Get(const MatcherBase& m) {
+      return *static_cast<Shared*>(m.buffer_.shared)->value;
+    }
+    static void Init(MatcherBase& m, M* impl) {
+      m.buffer_.shared = new Shared(std::unique_ptr<M>(impl));
+    }
+
+    static constexpr auto shared_destroy = &Shared::Destroy;
+  };
+
+  template <typename M>
+  void Init(M&& m) {
+    using MM = typename std::decay<M>::type;
+    using Policy = ValuePolicy<MM>;
+    vtable_ = GetVTable<Policy>();
+    Policy::Init(*this, std::forward<M>(m));
+  }
+
+  const VTable* vtable_;
+  Buffer buffer_;
+};
+
+}  // namespace internal
+
+// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
+// object that can check whether a value of type T matches.  The
+// implementation of Matcher<T> is just a std::shared_ptr to const
+// MatcherInterface<T>.  Don't inherit from Matcher!
+template <typename T>
+class Matcher : public internal::MatcherBase<T> {
+ public:
+  // Constructs a null matcher.  Needed for storing Matcher objects in STL
+  // containers.  A default-constructed matcher is not yet initialized.  You
+  // cannot use it until a valid value has been assigned to it.
+  explicit Matcher() {}  // NOLINT
+
+  // Constructs a matcher from its implementation.
+  explicit Matcher(const MatcherInterface<const T&>* impl)
+      : internal::MatcherBase<T>(impl) {}
+
+  template <typename U>
+  explicit Matcher(
+      const MatcherInterface<U>* impl,
+      typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
+          nullptr)
+      : internal::MatcherBase<T>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m) : internal::MatcherBase<T>(std::forward<M>(m)) {}  // NOLINT
+
+  // Implicit constructor here allows people to write
+  // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
+  Matcher(T value);  // NOLINT
+};
+
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
+// matcher is expected.
+template <>
+class GTEST_API_ Matcher<const std::string&>
+    : public internal::MatcherBase<const std::string&> {
+ public:
+  Matcher() = default;
+
+  explicit Matcher(const MatcherInterface<const std::string&>* impl)
+      : internal::MatcherBase<const std::string&>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<const std::string&>(std::forward<M>(m)) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a std::string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+template <>
+class GTEST_API_ Matcher<std::string>
+    : public internal::MatcherBase<std::string> {
+ public:
+  Matcher() = default;
+
+  explicit Matcher(const MatcherInterface<const std::string&>* impl)
+      : internal::MatcherBase<std::string>(impl) {}
+  explicit Matcher(const MatcherInterface<std::string>* impl)
+      : internal::MatcherBase<std::string>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<std::string>(std::forward<M>(m)) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
+// matcher is expected.
+template <>
+class GTEST_API_ Matcher<const internal::StringView&>
+    : public internal::MatcherBase<const internal::StringView&> {
+ public:
+  Matcher() = default;
+
+  explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
+      : internal::MatcherBase<const internal::StringView&>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<const internal::StringView&>(std::forward<M>(m)) {
+  }
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a std::string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+
+  // Allows the user to pass absl::string_views or std::string_views directly.
+  Matcher(internal::StringView s);  // NOLINT
+};
+
+template <>
+class GTEST_API_ Matcher<internal::StringView>
+    : public internal::MatcherBase<internal::StringView> {
+ public:
+  Matcher() = default;
+
+  explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
+      : internal::MatcherBase<internal::StringView>(impl) {}
+  explicit Matcher(const MatcherInterface<internal::StringView>* impl)
+      : internal::MatcherBase<internal::StringView>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<internal::StringView>(std::forward<M>(m)) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a std::string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+
+  // Allows the user to pass absl::string_views or std::string_views directly.
+  Matcher(internal::StringView s);  // NOLINT
+};
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+// Prints a matcher in a human-readable format.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
+  matcher.DescribeTo(&os);
+  return os;
+}
+
+// The PolymorphicMatcher class template makes it easy to implement a
+// polymorphic matcher (i.e. a matcher that can match values of more
+// than one type, e.g. Eq(n) and NotNull()).
+//
+// To define a polymorphic matcher, a user should provide an Impl
+// class that has a DescribeTo() method and a DescribeNegationTo()
+// method, and define a member function (or member function template)
+//
+//   bool MatchAndExplain(const Value& value,
+//                        MatchResultListener* listener) const;
+//
+// See the definition of NotNull() for a complete example.
+template <class Impl>
+class PolymorphicMatcher {
+ public:
+  explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
+
+  // Returns a mutable reference to the underlying matcher
+  // implementation object.
+  Impl& mutable_impl() { return impl_; }
+
+  // Returns an immutable reference to the underlying matcher
+  // implementation object.
+  const Impl& impl() const { return impl_; }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new MonomorphicImpl<const T&>(impl_));
+  }
+
+ private:
+  template <typename T>
+  class MonomorphicImpl : public MatcherInterface<T> {
+   public:
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      impl_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+      return impl_.MatchAndExplain(x, listener);
+    }
+
+   private:
+    const Impl impl_;
+  };
+
+  Impl impl_;
+};
+
+// Creates a matcher from its implementation.
+// DEPRECATED: Especially in the generic code, prefer:
+//   Matcher<T>(new MyMatcherImpl<const T&>(...));
+//
+// MakeMatcher may create a Matcher that accepts its argument by value, which
+// leads to unnecessary copies & lack of support for non-copyable types.
+template <typename T>
+inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
+  return Matcher<T>(impl);
+}
+
+// Creates a polymorphic matcher from its implementation.  This is
+// easier to use than the PolymorphicMatcher<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicMatcher(foo);
+// vs
+//   PolymorphicMatcher<TypeOfFoo>(foo);
+template <class Impl>
+inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
+  return PolymorphicMatcher<Impl>(impl);
+}
+
+namespace internal {
+// Implements a matcher that compares a given value with a
+// pre-supplied value using one of the ==, <=, <, etc, operators.  The
+// two values being compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq(5) can be
+// used to match an int, a short, a double, etc).  Therefore we use
+// a template type conversion operator in the implementation.
+//
+// The following template definition assumes that the Rhs parameter is
+// a "bare" type (i.e. neither 'const T' nor 'T&').
+template <typename D, typename Rhs, typename Op>
+class ComparisonBase {
+ public:
+  explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
+
+  using is_gtest_matcher = void;
+
+  template <typename Lhs>
+  bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
+    return Op()(lhs, Unwrap(rhs_));
+  }
+  void DescribeTo(std::ostream* os) const {
+    *os << D::Desc() << " ";
+    UniversalPrint(Unwrap(rhs_), os);
+  }
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << D::NegatedDesc() << " ";
+    UniversalPrint(Unwrap(rhs_), os);
+  }
+
+ private:
+  template <typename T>
+  static const T& Unwrap(const T& v) {
+    return v;
+  }
+  template <typename T>
+  static const T& Unwrap(std::reference_wrapper<T> v) {
+    return v;
+  }
+
+  Rhs rhs_;
+};
+
+template <typename Rhs>
+class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>> {
+ public:
+  explicit EqMatcher(const Rhs& rhs)
+      : ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>>(rhs) {}
+  static const char* Desc() { return "is equal to"; }
+  static const char* NegatedDesc() { return "isn't equal to"; }
+};
+template <typename Rhs>
+class NeMatcher
+    : public ComparisonBase<NeMatcher<Rhs>, Rhs, std::not_equal_to<>> {
+ public:
+  explicit NeMatcher(const Rhs& rhs)
+      : ComparisonBase<NeMatcher<Rhs>, Rhs, std::not_equal_to<>>(rhs) {}
+  static const char* Desc() { return "isn't equal to"; }
+  static const char* NegatedDesc() { return "is equal to"; }
+};
+template <typename Rhs>
+class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>> {
+ public:
+  explicit LtMatcher(const Rhs& rhs)
+      : ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>>(rhs) {}
+  static const char* Desc() { return "is <"; }
+  static const char* NegatedDesc() { return "isn't <"; }
+};
+template <typename Rhs>
+class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>> {
+ public:
+  explicit GtMatcher(const Rhs& rhs)
+      : ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>>(rhs) {}
+  static const char* Desc() { return "is >"; }
+  static const char* NegatedDesc() { return "isn't >"; }
+};
+template <typename Rhs>
+class LeMatcher
+    : public ComparisonBase<LeMatcher<Rhs>, Rhs, std::less_equal<>> {
+ public:
+  explicit LeMatcher(const Rhs& rhs)
+      : ComparisonBase<LeMatcher<Rhs>, Rhs, std::less_equal<>>(rhs) {}
+  static const char* Desc() { return "is <="; }
+  static const char* NegatedDesc() { return "isn't <="; }
+};
+template <typename Rhs>
+class GeMatcher
+    : public ComparisonBase<GeMatcher<Rhs>, Rhs, std::greater_equal<>> {
+ public:
+  explicit GeMatcher(const Rhs& rhs)
+      : ComparisonBase<GeMatcher<Rhs>, Rhs, std::greater_equal<>>(rhs) {}
+  static const char* Desc() { return "is >="; }
+  static const char* NegatedDesc() { return "isn't >="; }
+};
+
+template <typename T, typename = typename std::enable_if<
+                          std::is_constructible<std::string, T>::value>::type>
+using StringLike = T;
+
+// Implements polymorphic matchers MatchesRegex(regex) and
+// ContainsRegex(regex), which can be used as a Matcher<T> as long as
+// T can be converted to a string.
+class MatchesRegexMatcher {
+ public:
+  MatchesRegexMatcher(const RE* regex, bool full_match)
+      : regex_(regex), full_match_(full_match) {}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  bool MatchAndExplain(const internal::StringView& s,
+                       MatchResultListener* listener) const {
+    return MatchAndExplain(std::string(s), listener);
+  }
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != nullptr && MatchAndExplain(std::string(s), listener);
+  }
+
+  // Matches anything that can convert to std::string.
+  //
+  // This is a template, not just a plain function with const std::string&,
+  // because absl::string_view has some interfering non-explicit constructors.
+  template <class MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const std::string s2(s);
+    return full_match_ ? RE::FullMatch(s2, *regex_)
+                       : RE::PartialMatch(s2, *regex_);
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << (full_match_ ? "matches" : "contains") << " regular expression ";
+    UniversalPrinter<std::string>::Print(regex_->pattern(), os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't " << (full_match_ ? "match" : "contain")
+        << " regular expression ";
+    UniversalPrinter<std::string>::Print(regex_->pattern(), os);
+  }
+
+ private:
+  const std::shared_ptr<const RE> regex_;
+  const bool full_match_;
+};
+}  // namespace internal
+
+// Matches a string that fully matches regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
+}
+template <typename T = std::string>
+PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::StringLike<T>& regex) {
+  return MatchesRegex(new internal::RE(std::string(regex)));
+}
+
+// Matches a string that contains regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
+}
+template <typename T = std::string>
+PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::StringLike<T>& regex) {
+  return ContainsRegex(new internal::RE(std::string(regex)));
+}
+
+// Creates a polymorphic matcher that matches anything equal to x.
+// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
+// wouldn't compile.
+template <typename T>
+inline internal::EqMatcher<T> Eq(T x) {
+  return internal::EqMatcher<T>(x);
+}
+
+// Constructs a Matcher<T> from a 'value' of type T.  The constructed
+// matcher matches any value that's equal to 'value'.
+template <typename T>
+Matcher<T>::Matcher(T value) {
+  *this = Eq(value);
+}
+
+// Creates a monomorphic matcher that matches anything with type Lhs
+// and equal to rhs.  A user may need to use this instead of Eq(...)
+// in order to resolve an overloading ambiguity.
+//
+// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
+// or Matcher<T>(x), but more readable than the latter.
+//
+// We could define similar monomorphic matchers for other comparison
+// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
+// it yet as those are used much less than Eq() in practice.  A user
+// can always write Matcher<T>(Lt(5)) to be explicit about the type,
+// for example.
+template <typename Lhs, typename Rhs>
+inline Matcher<Lhs> TypedEq(const Rhs& rhs) {
+  return Eq(rhs);
+}
+
+// Creates a polymorphic matcher that matches anything >= x.
+template <typename Rhs>
+inline internal::GeMatcher<Rhs> Ge(Rhs x) {
+  return internal::GeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything > x.
+template <typename Rhs>
+inline internal::GtMatcher<Rhs> Gt(Rhs x) {
+  return internal::GtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything <= x.
+template <typename Rhs>
+inline internal::LeMatcher<Rhs> Le(Rhs x) {
+  return internal::LeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything < x.
+template <typename Rhs>
+inline internal::LtMatcher<Rhs> Lt(Rhs x) {
+  return internal::LtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything != x.
+template <typename Rhs>
+inline internal::NeMatcher<Rhs> Ne(Rhs x) {
+  return internal::NeMatcher<Rhs>(x);
+}
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251 5046
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-message.h b/3rd-party/googletest/googletest/include/gtest/gtest-message.h
new file mode 100644
index 0000000..448ac6b
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-message.h
@@ -0,0 +1,251 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_HAS_ABSL
+#include <type_traits>
+
+#include "absl/strings/has_absl_stringify.h"
+#include "absl/strings/str_cat.h"
+#endif  // GTEST_HAS_ABSL
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  Message();
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+  // Streams a non-pointer value to this object. If building a version of
+  // GoogleTest with ABSL, this overload is only enabled if the value does not
+  // have an AbslStringify definition.
+  template <
+      typename T
+#ifdef GTEST_HAS_ABSL
+      ,
+      typename std::enable_if<!absl::HasAbslStringify<T>::value,  // NOLINT
+                              int>::type = 0
+#endif  // GTEST_HAS_ABSL
+      >
+  inline Message& operator<<(const T& val) {
+        // Some libraries overload << for STL containers.  These
+    // overloads are defined in the global namespace instead of ::std.
+    //
+    // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+    // overloads are visible in either the std namespace or the global
+    // namespace, but not other namespaces, including the testing
+    // namespace which Google Test's Message class is in.
+    //
+    // To allow STL containers (and other types that has a << operator
+    // defined in the global namespace) to be used in Google Test
+    // assertions, testing::Message must access the custom << operator
+    // from the global namespace.  With this using declaration,
+    // overloads of << defined in the global namespace and those
+    // visible via Koenig lookup are both exposed in this function.
+    using ::operator<<;
+    *ss_ << val;
+    return *this;
+  }
+
+#ifdef GTEST_HAS_ABSL
+  // Streams a non-pointer value with an AbslStringify definition to this
+  // object.
+  template <typename T,
+            typename std::enable_if<absl::HasAbslStringify<T>::value,  // NOLINT
+                                    int>::type = 0>
+  inline Message& operator<<(const T& val) {
+    // ::operator<< is needed here for a similar reason as with the non-Abseil
+    // version above
+    using ::operator<<;
+    *ss_ << absl::StrCat(val);
+    return *this;
+  }
+#endif  // GTEST_HAS_ABSL
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator<<(T* const& pointer) {  // NOLINT
+    if (pointer == nullptr) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+    return *this;
+  }
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator<<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator<<(bool b) { return *this << (b ? "true" : "false"); }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator<<(const wchar_t* wide_c_str);
+  Message& operator<<(wchar_t* wide_c_str);
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator<<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+  // Gets the text streamed to this object so far as an std::string.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  std::string GetString() const;
+
+ private:
+  // We'll hold the text streamed to this object here.
+  const std::unique_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator<<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+namespace internal {
+
+// Converts a streamable value to an std::string.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-param-test.h b/3rd-party/googletest/googletest/include/gtest/gtest-param-test.h
new file mode 100644
index 0000000..55ee088
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-param-test.h
@@ -0,0 +1,546 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing and Mocking Framework (Google Test)
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_SUITE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test suite
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_SUITE_P(InstantiationName,
+                         FooTest,
+                         Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more than once) the first argument to the
+// INSTANTIATE_TEST_SUITE_P macro 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"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest, 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"
+//
+// 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.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include <iterator>
+#include <utility>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"  // IWYU pragma: export
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test suite is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test suite FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_SUITE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test suite StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_SUITE_P(StringSequence, StringTest, ValuesIn(strings));
+//
+// This instantiates tests from test suite StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_SUITE_P(CharSequence,
+//                          StlStringTest,
+//                          ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_SUITE_P(CharSequence2,
+//                          CharTest,
+//                          ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+    typename std::iterator_traits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename std::iterator_traits<ForwardIterator>::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test suite BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_SUITE_P(NumSequence,
+//                          BarTest,
+//                          Values("one", "two", "three"));
+//
+// This instantiates tests from test suite BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_SUITE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+//
+template <typename... T>
+internal::ValueArray<T...> Values(T... v) {
+  return internal::ValueArray<T...>(std::move(v)...);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test suite FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() { return Values(false, true); }
+
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     std::tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Example:
+//
+// This will instantiate tests in test suite AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<std::tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest,
+//                          Combine(Values("cat", "dog"),
+//                                  Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<std::tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     std::tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_SUITE_P(TwoBoolSequence, FlagDependentTest,
+//                          Combine(Bool(), Bool()));
+//
+template <typename... Generator>
+internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
+  return internal::CartesianProductHolder<Generator...>(g...);
+}
+
+// ConvertGenerator() wraps a parameter generator in order to cast each produced
+// value through a known type before supplying it to the test suite
+//
+// Synopsis:
+// ConvertGenerator<T>(gen)
+//   - returns a generator producing the same elements as generated by gen, but
+//     each element is static_cast to type T before being returned
+//
+// It is useful when using the Combine() function to get the generated
+// parameters in a custom type instead of std::tuple
+//
+// Example:
+//
+// This will instantiate tests in test suite AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// struct ParamType {
+//   using TupleT = std::tuple<const char*, Color>;
+//   std::string animal;
+//   Color color;
+//   ParamType(TupleT t) : animal(std::get<0>(t)), color(std::get<1>(t)) {}
+// };
+// class AnimalTest
+//     : public testing::TestWithParam<ParamType> {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest,
+//                          ConvertGenerator<ParamType::TupleT>(
+//                              Combine(Values("cat", "dog"),
+//                                      Values(BLACK, WHITE))));
+//
+template <typename T>
+internal::ParamConverterGenerator<T> ConvertGenerator(
+    internal::ParamGenerator<T> gen) {
+  return internal::ParamConverterGenerator<T>(gen);
+}
+
+#define TEST_P(test_suite_name, test_name)                                     \
+  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                     \
+      : public test_suite_name,                                                \
+        private ::testing::internal::GTestNonCopyable {                        \
+   public:                                                                     \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {}                    \
+    void TestBody() override;                                                  \
+                                                                               \
+   private:                                                                    \
+    static int AddToRegistry() {                                               \
+      ::testing::UnitTest::GetInstance()                                       \
+          ->parameterized_test_registry()                                      \
+          .GetTestSuitePatternHolder<test_suite_name>(                         \
+              GTEST_STRINGIFY_(test_suite_name),                               \
+              ::testing::internal::CodeLocation(__FILE__, __LINE__))           \
+          ->AddTestPattern(                                                    \
+              GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name),  \
+              new ::testing::internal::TestMetaFactory<GTEST_TEST_CLASS_NAME_( \
+                  test_suite_name, test_name)>(),                              \
+              ::testing::internal::CodeLocation(__FILE__, __LINE__));          \
+      return 0;                                                                \
+    }                                                                          \
+    GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int gtest_registering_dummy_; \
+  };                                                                           \
+  int GTEST_TEST_CLASS_NAME_(test_suite_name,                                  \
+                             test_name)::gtest_registering_dummy_ =            \
+      GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry();     \
+  void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
+
+// The last argument to INSTANTIATE_TEST_SUITE_P allows the user to specify
+// generator and an optional function or functor that generates custom test name
+// suffixes based on the test parameters. Such a function or functor should
+// accept one argument of type testing::TestParamInfo<class ParamType>, and
+// return std::string.
+//
+// testing::PrintToStringParamName is a builtin test suffix generator that
+// returns the value of testing::PrintToString(GetParam()).
+//
+// Note: test names must be non-empty, unique, and may only contain ASCII
+// alphanumeric characters or underscore. Because PrintToString adds quotes
+// to std::string and C strings, it won't work for these types.
+
+#define GTEST_EXPAND_(arg) arg
+#define GTEST_GET_FIRST_(first, ...) first
+#define GTEST_GET_SECOND_(first, second, ...) second
+
+#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...)               \
+  static ::testing::internal::ParamGenerator<test_suite_name::ParamType>     \
+      gtest_##prefix##test_suite_name##_EvalGenerator_() {                   \
+    return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_));       \
+  }                                                                          \
+  static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_(  \
+      const ::testing::TestParamInfo<test_suite_name::ParamType>& info) {    \
+    if (::testing::internal::AlwaysFalse()) {                                \
+      ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_(     \
+          __VA_ARGS__,                                                       \
+          ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
+          DUMMY_PARAM_)));                                                   \
+      auto t = std::make_tuple(__VA_ARGS__);                                 \
+      static_assert(std::tuple_size<decltype(t)>::value <= 2,                \
+                    "Too Many Args!");                                       \
+    }                                                                        \
+    return ((GTEST_EXPAND_(GTEST_GET_SECOND_(                                \
+        __VA_ARGS__,                                                         \
+        ::testing::internal::DefaultParamName<test_suite_name::ParamType>,   \
+        DUMMY_PARAM_))))(info);                                              \
+  }                                                                          \
+  GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int                           \
+      gtest_##prefix##test_suite_name##_dummy_ =                             \
+          ::testing::UnitTest::GetInstance()                                 \
+              ->parameterized_test_registry()                                \
+              .GetTestSuitePatternHolder<test_suite_name>(                   \
+                  GTEST_STRINGIFY_(test_suite_name),                         \
+                  ::testing::internal::CodeLocation(__FILE__, __LINE__))     \
+              ->AddTestSuiteInstantiation(                                   \
+                  GTEST_STRINGIFY_(prefix),                                  \
+                  &gtest_##prefix##test_suite_name##_EvalGenerator_,         \
+                  &gtest_##prefix##test_suite_name##_EvalGenerateName_,      \
+                  __FILE__, __LINE__)
+
+// Allow Marking a Parameterized test class as not needing to be instantiated.
+#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T)                  \
+  namespace gtest_do_not_use_outside_namespace_scope {}                   \
+  static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \
+      GTEST_STRINGIFY_(T))
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define INSTANTIATE_TEST_CASE_P                                            \
+  static_assert(::testing::internal::InstantiateTestCase_P_IsDeprecated(), \
+                "");                                                       \
+  INSTANTIATE_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-printers.h b/3rd-party/googletest/googletest/include/gtest/gtest-printers.h
new file mode 100644
index 0000000..b2822bc
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-printers.h
@@ -0,0 +1,1197 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Test - The Google C++ Testing and Mocking Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+// * Prefer AbslStringify(..) to operator<<(..), per https://abseil.io/tips/215.
+// * Define foo::PrintTo(..) if the type already has AbslStringify(..), but an
+//   alternative presentation in test results is of interest.
+//
+// However if T is an STL-style container then it is printed element-wise
+// unless foo::PrintTo(const T&, ostream*) is defined. Note that
+// operator<<() is ignored for container types.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <functional>
+#include <memory>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+#include <vector>
+
+#ifdef GTEST_HAS_ABSL
+#include "absl/strings/has_absl_stringify.h"
+#include "absl/strings/str_cat.h"
+#endif  // GTEST_HAS_ABSL
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_INTERNAL_HAS_STD_SPAN
+#include <span>  // NOLINT
+#endif           // GTEST_INTERNAL_HAS_STD_SPAN
+
+namespace testing {
+
+// Definitions in the internal* namespaces are subject to change without notice.
+// DO NOT USE THEM IN USER CODE!
+namespace internal {
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+template <typename T>
+struct IsStdSpan {
+  static constexpr bool value = false;
+};
+
+#if GTEST_INTERNAL_HAS_STD_SPAN
+template <typename E>
+struct IsStdSpan<std::span<E>> {
+  static constexpr bool value = true;
+};
+#endif  // GTEST_INTERNAL_HAS_STD_SPAN
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+//
+// NOTE: Since std::span does not have const_iterator until C++23, it would
+// fail IsContainerTest before C++23. However, IsContainerTest only uses
+// the presence of const_iterator to avoid treating iterators as containers
+// because of iterator::iterator. Which means std::span satisfies the *intended*
+// condition of IsContainerTest.
+struct ContainerPrinter {
+  template <typename T,
+            typename = typename std::enable_if<
+                ((sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
+                 !IsRecursiveContainer<T>::value) ||
+                IsStdSpan<T>::value>::type>
+  static void PrintValue(const T& container, std::ostream* os) {
+    const size_t kMaxCount = 32;  // The maximum number of elements to print.
+    *os << '{';
+    size_t count = 0;
+    for (auto&& elem : container) {
+      if (count > 0) {
+        *os << ',';
+        if (count == kMaxCount) {  // Enough has been printed.
+          *os << " ...";
+          break;
+        }
+      }
+      *os << ' ';
+      // We cannot call PrintTo(elem, os) here as PrintTo() doesn't
+      // handle `elem` being a native array.
+      internal::UniversalPrint(elem, os);
+      ++count;
+    }
+
+    if (count > 0) {
+      *os << ' ';
+    }
+    *os << '}';
+  }
+};
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+struct FunctionPointerPrinter {
+  template <typename T, typename = typename std::enable_if<
+                            std::is_function<T>::value>::type>
+  static void PrintValue(T* p, ::std::ostream* os) {
+    if (p == nullptr) {
+      *os << "NULL";
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.
+      *os << reinterpret_cast<const void*>(p);
+    }
+  }
+};
+
+struct PointerPrinter {
+  template <typename T>
+  static void PrintValue(T* p, ::std::ostream* os) {
+    if (p == nullptr) {
+      *os << "NULL";
+    } else {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    }
+  }
+};
+
+namespace internal_stream_operator_without_lexical_name_lookup {
+
+// The presence of an operator<< here will terminate lexical scope lookup
+// straight away (even though it cannot be a match because of its argument
+// types). Thus, the two operator<< calls in StreamPrinter will find only ADL
+// candidates.
+struct LookupBlocker {};
+void operator<<(LookupBlocker, LookupBlocker);
+
+struct StreamPrinter {
+  template <typename T,
+            // Don't accept member pointers here. We'd print them via implicit
+            // conversion to bool, which isn't useful.
+            typename = typename std::enable_if<
+                !std::is_member_pointer<T>::value>::type>
+  // Only accept types for which we can find a streaming operator via
+  // ADL (possibly involving implicit conversions).
+  // (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name
+  // lookup properly when we do it in the template parameter list.)
+  static auto PrintValue(const T& value,
+                         ::std::ostream* os) -> decltype((void)(*os << value)) {
+    // Call streaming operator found by ADL, possibly with implicit conversions
+    // of the arguments.
+    *os << value;
+  }
+};
+
+}  // namespace internal_stream_operator_without_lexical_name_lookup
+
+struct ProtobufPrinter {
+  // We print a protobuf using its ShortDebugString() when the string
+  // doesn't exceed this many characters; otherwise we print it using
+  // DebugString() for better readability.
+  static const size_t kProtobufOneLinerMaxLength = 50;
+
+  template <typename T,
+            typename = typename std::enable_if<
+                internal::HasDebugStringAndShortDebugString<T>::value>::type>
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    std::string pretty_str = value.ShortDebugString();
+    if (pretty_str.length() > kProtobufOneLinerMaxLength) {
+      pretty_str = "\n" + value.DebugString();
+    }
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+struct ConvertibleToIntegerPrinter {
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(internal::BiggestInt value, ::std::ostream* os) {
+    *os << value;
+  }
+};
+
+struct ConvertibleToStringViewPrinter {
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  static void PrintValue(internal::StringView value, ::std::ostream* os) {
+    internal::UniversalPrint(value, os);
+  }
+#endif
+};
+
+#ifdef GTEST_HAS_ABSL
+struct ConvertibleToAbslStringifyPrinter {
+  template <typename T,
+            typename = typename std::enable_if<
+                absl::HasAbslStringify<T>::value>::type>  // NOLINT
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    *os << absl::StrCat(value);
+  }
+};
+#endif  // GTEST_HAS_ABSL
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count, ::std::ostream* os);
+struct RawBytesPrinter {
+  // SFINAE on `sizeof` to make sure we have a complete type.
+  template <typename T, size_t = sizeof(T)>
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(
+        static_cast<const unsigned char*>(
+            // Load bearing cast to void* to support iOS
+            reinterpret_cast<const void*>(std::addressof(value))),
+        sizeof(value), os);
+  }
+};
+
+struct FallbackPrinter {
+  template <typename T>
+  static void PrintValue(const T&, ::std::ostream* os) {
+    *os << "(incomplete type)";
+  }
+};
+
+// Try every printer in order and return the first one that works.
+template <typename T, typename E, typename Printer, typename... Printers>
+struct FindFirstPrinter : FindFirstPrinter<T, E, Printers...> {};
+
+template <typename T, typename Printer, typename... Printers>
+struct FindFirstPrinter<
+    T, decltype(Printer::PrintValue(std::declval<const T&>(), nullptr)),
+    Printer, Printers...> {
+  using type = Printer;
+};
+
+// Select the best printer in the following order:
+//  - Print containers (they have begin/end/etc).
+//  - Print function pointers.
+//  - Print object pointers.
+//  - Print protocol buffers.
+//  - Use the stream operator, if available.
+//  - Print types convertible to BiggestInt.
+//  - Print types convertible to StringView, if available.
+//  - Fallback to printing the raw bytes of the object.
+template <typename T>
+void PrintWithFallback(const T& value, ::std::ostream* os) {
+  using Printer = typename FindFirstPrinter<
+      T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter,
+      ProtobufPrinter,
+#ifdef GTEST_HAS_ABSL
+      ConvertibleToAbslStringifyPrinter,
+#endif  // GTEST_HAS_ABSL
+      internal_stream_operator_without_lexical_name_lookup::StreamPrinter,
+      ConvertibleToIntegerPrinter, ConvertibleToStringViewPrinter,
+      RawBytesPrinter, FallbackPrinter>::type;
+  Printer::PrintValue(value, os);
+}
+
+// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
+// value of type ToPrint that is an operand of a comparison assertion
+// (e.g. ASSERT_EQ).  OtherOperand is the type of the other operand in
+// the comparison, and is used to help determine the best way to
+// format the value.  In particular, when the value is a C string
+// (char pointer) and the other operand is an STL string object, we
+// want to format the C string as a string, since we know it is
+// compared by value with the string object.  If the value is a char
+// pointer but the other operand is not an STL string object, we don't
+// know whether the pointer is supposed to point to a NUL-terminated
+// string, and thus want to print it as a pointer to be safe.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// The default case.
+template <typename ToPrint, typename OtherOperand>
+class FormatForComparison {
+ public:
+  static ::std::string Format(const ToPrint& value) {
+    return ::testing::PrintToString(value);
+  }
+};
+
+// Array.
+template <typename ToPrint, size_t N, typename OtherOperand>
+class FormatForComparison<ToPrint[N], OtherOperand> {
+ public:
+  static ::std::string Format(const ToPrint* value) {
+    return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
+  }
+};
+
+// By default, print C string as pointers to be safe, as we don't know
+// whether they actually point to a NUL-terminated string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType)                \
+  template <typename OtherOperand>                                      \
+  class FormatForComparison<CharType*, OtherOperand> {                  \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(static_cast<const void*>(value)); \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
+#ifdef __cpp_lib_char8_t
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t);
+#endif
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char16_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char16_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char32_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
+
+// If a C string is compared with an STL string object, we know it's meant
+// to point to a NUL-terminated string, and thus can print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+  template <>                                                            \
+  class FormatForComparison<CharType*, OtherStringType> {                \
+   public:                                                               \
+    static ::std::string Format(CharType* value) {                       \
+      return ::testing::PrintToString(value);                            \
+    }                                                                    \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
+#ifdef __cpp_lib_char8_t
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string);
+#endif
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char16_t, ::std::u16string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char16_t, ::std::u16string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char32_t, ::std::u32string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char32_t, ::std::u32string);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
+#endif
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char* or void*, and print it as a C string when it is compared
+// against an std::string object, for example.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+std::string FormatForComparisonFailureMessage(const T1& value,
+                                              const T2& /* other_operand */) {
+  return FormatForComparison<T1, T2>::Format(value);
+}
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  internal::PrintWithFallback(value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
+inline void PrintTo(char16_t c, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<char32_t>(c), os);
+}
+#ifdef __cpp_lib_char8_t
+inline void PrintTo(char8_t c, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<char32_t>(c), os);
+}
+#endif
+
+// gcc/clang __{u,}int128_t
+#if defined(__SIZEOF_INT128__)
+GTEST_API_ void PrintTo(__uint128_t v, ::std::ostream* os);
+GTEST_API_ void PrintTo(__int128_t v, ::std::ostream* os);
+#endif  // __SIZEOF_INT128__
+
+// The default resolution used to print floating-point values uses only
+// 6 digits, which can be confusing if a test compares two values whose
+// difference lies in the 7th digit.  So we'd like to print out numbers
+// in full precision.
+// However if the value is something simple like 1.1, full will print a
+// long string like 1.100000001 due to floating-point numbers not using
+// a base of 10.  This routiune returns an appropriate resolution for a
+// given floating-point number, that is, 6 if it will be accurate, or a
+// max_digits10 value (full precision) if it won't,  for values between
+// 0.0001 and one million.
+// It does this by computing what those digits would be (by multiplying
+// by an appropriate power of 10), then dividing by that power again to
+// see if gets the original value back.
+// A similar algorithm applies for values larger than one million; note
+// that for those values, we must divide to get a six-digit number, and
+// then multiply to possibly get the original value again.
+template <typename FloatType>
+int AppropriateResolution(FloatType val) {
+  int full = std::numeric_limits<FloatType>::max_digits10;
+  if (val < 0) val = -val;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+  if (val < 1000000) {
+    FloatType mulfor6 = 1e10;
+    // Without these static casts, the template instantiation for float would
+    // fail to compile when -Wdouble-promotion is enabled, as the arithmetic and
+    // comparison logic would promote floats to doubles.
+    if (val >= static_cast<FloatType>(100000.0)) {  // 100,000 to 999,999
+      mulfor6 = 1.0;
+    } else if (val >= static_cast<FloatType>(10000.0)) {
+      mulfor6 = 1e1;
+    } else if (val >= static_cast<FloatType>(1000.0)) {
+      mulfor6 = 1e2;
+    } else if (val >= static_cast<FloatType>(100.0)) {
+      mulfor6 = 1e3;
+    } else if (val >= static_cast<FloatType>(10.0)) {
+      mulfor6 = 1e4;
+    } else if (val >= static_cast<FloatType>(1.0)) {
+      mulfor6 = 1e5;
+    } else if (val >= static_cast<FloatType>(0.1)) {
+      mulfor6 = 1e6;
+    } else if (val >= static_cast<FloatType>(0.01)) {
+      mulfor6 = 1e7;
+    } else if (val >= static_cast<FloatType>(0.001)) {
+      mulfor6 = 1e8;
+    } else if (val >= static_cast<FloatType>(0.0001)) {
+      mulfor6 = 1e9;
+    }
+    if (static_cast<FloatType>(static_cast<int32_t>(
+            val * mulfor6 + (static_cast<FloatType>(0.5)))) /
+            mulfor6 ==
+        val)
+      return 6;
+  } else if (val < static_cast<FloatType>(1e10)) {
+    FloatType divfor6 = static_cast<FloatType>(1.0);
+    if (val >= static_cast<FloatType>(1e9)) {  // 1,000,000,000 to 9,999,999,999
+      divfor6 = 10000;
+    } else if (val >=
+               static_cast<FloatType>(1e8)) {  // 100,000,000 to 999,999,999
+      divfor6 = 1000;
+    } else if (val >=
+               static_cast<FloatType>(1e7)) {  // 10,000,000 to 99,999,999
+      divfor6 = 100;
+    } else if (val >= static_cast<FloatType>(1e6)) {  // 1,000,000 to 9,999,999
+      divfor6 = 10;
+    }
+    if (static_cast<FloatType>(static_cast<int32_t>(
+            val / divfor6 + (static_cast<FloatType>(0.5)))) *
+            divfor6 ==
+        val)
+      return 6;
+  }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+  return full;
+}
+
+inline void PrintTo(float f, ::std::ostream* os) {
+  auto old_precision = os->precision();
+  os->precision(AppropriateResolution(f));
+  *os << f;
+  os->precision(old_precision);
+}
+
+inline void PrintTo(double d, ::std::ostream* os) {
+  auto old_precision = os->precision();
+  os->precision(AppropriateResolution(d));
+  *os << d;
+  os->precision(old_precision);
+}
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+#ifdef __cpp_lib_char8_t
+// Overloads for u8 strings.
+GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os);
+inline void PrintTo(char8_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char8_t*>(s), os);
+}
+#endif
+// Overloads for u16 strings.
+GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os);
+inline void PrintTo(char16_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char16_t*>(s), os);
+}
+// Overloads for u32 strings.
+GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os);
+inline void PrintTo(char32_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char32_t*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::std::string.
+GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::std::u8string
+#ifdef __cpp_lib_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);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// Overload for internal::StringView.
+inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
+  PrintTo(::std::string(sp), os);
+}
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
+
+#if GTEST_HAS_RTTI
+inline void PrintTo(const std::type_info& info, std::ostream* os) {
+  *os << internal::GetTypeName(info);
+}
+#endif  // GTEST_HAS_RTTI
+
+template <typename T>
+void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
+  UniversalPrinter<T&>::Print(ref.get(), os);
+}
+
+inline const void* VoidifyPointer(const void* p) { return p; }
+inline const void* VoidifyPointer(volatile const void* p) {
+  return const_cast<const void*>(p);
+}
+
+template <typename T, typename Ptr>
+void PrintSmartPointer(const Ptr& ptr, std::ostream* os, char) {
+  if (ptr == nullptr) {
+    *os << "(nullptr)";
+  } else {
+    // We can't print the value. Just print the pointer..
+    *os << "(" << (VoidifyPointer)(ptr.get()) << ")";
+  }
+}
+template <typename T, typename Ptr,
+          typename = typename std::enable_if<!std::is_void<T>::value &&
+                                             !std::is_array<T>::value>::type>
+void PrintSmartPointer(const Ptr& ptr, std::ostream* os, int) {
+  if (ptr == nullptr) {
+    *os << "(nullptr)";
+  } else {
+    *os << "(ptr = " << (VoidifyPointer)(ptr.get()) << ", value = ";
+    UniversalPrinter<T>::Print(*ptr, os);
+    *os << ")";
+  }
+}
+
+template <typename T, typename D>
+void PrintTo(const std::unique_ptr<T, D>& ptr, std::ostream* os) {
+  (PrintSmartPointer<T>)(ptr, os, 0);
+}
+
+template <typename T>
+void PrintTo(const std::shared_ptr<T>& ptr, std::ostream* os) {
+  (PrintSmartPointer<T>)(ptr, os, 0);
+}
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T&, std::integral_constant<size_t, 0>,
+                  ::std::ostream*) {}
+
+template <typename T, size_t I>
+void PrintTupleTo(const T& t, std::integral_constant<size_t, I>,
+                  ::std::ostream* os) {
+  PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os);
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (I > 1) {
+    GTEST_INTENTIONAL_CONST_COND_POP_()
+    *os << ", ";
+  }
+  UniversalPrinter<typename std::tuple_element<I - 1, T>::type>::Print(
+      std::get<I - 1>(t), os);
+}
+
+template <typename... Types>
+void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
+  *os << "(";
+  PrintTupleTo(t, std::integral_constant<size_t, sizeof...(Types)>(), os);
+  *os << ")";
+}
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+};
+
+// Remove any const-qualifiers before passing a type to UniversalPrinter.
+template <typename T>
+class UniversalPrinter<const T> : public UniversalPrinter<T> {};
+
+#if GTEST_INTERNAL_HAS_ANY
+
+// Printer for std::any / absl::any
+
+template <>
+class UniversalPrinter<Any> {
+ public:
+  static void Print(const Any& value, ::std::ostream* os) {
+    if (value.has_value()) {
+      *os << "value of type " << GetTypeName(value);
+    } else {
+      *os << "no value";
+    }
+  }
+
+ private:
+  static std::string GetTypeName(const Any& value) {
+#if GTEST_HAS_RTTI
+    return internal::GetTypeName(value.type());
+#else
+    static_cast<void>(value);  // possibly unused
+    return "<unknown_type>";
+#endif  // GTEST_HAS_RTTI
+  }
+};
+
+#endif  // GTEST_INTERNAL_HAS_ANY
+
+#if GTEST_INTERNAL_HAS_OPTIONAL
+
+// Printer for std::optional / absl::optional
+
+template <typename T>
+class UniversalPrinter<Optional<T>> {
+ public:
+  static void Print(const Optional<T>& value, ::std::ostream* os) {
+    *os << '(';
+    if (!value) {
+      *os << "nullopt";
+    } else {
+      UniversalPrint(*value, os);
+    }
+    *os << ')';
+  }
+};
+
+template <>
+class UniversalPrinter<decltype(Nullopt())> {
+ public:
+  static void Print(decltype(Nullopt()), ::std::ostream* os) {
+    *os << "(nullopt)";
+  }
+};
+
+#endif  // GTEST_INTERNAL_HAS_OPTIONAL
+
+#if GTEST_INTERNAL_HAS_VARIANT
+
+// Printer for std::variant / absl::variant
+
+template <typename... T>
+class UniversalPrinter<Variant<T...>> {
+ public:
+  static void Print(const Variant<T...>& value, ::std::ostream* os) {
+    *os << '(';
+#ifdef GTEST_HAS_ABSL
+    absl::visit(Visitor{os, value.index()}, value);
+#else
+    std::visit(Visitor{os, value.index()}, value);
+#endif  // GTEST_HAS_ABSL
+    *os << ')';
+  }
+
+ private:
+  struct Visitor {
+    template <typename U>
+    void operator()(const U& u) const {
+      *os << "'" << GetTypeName<U>() << "(index = " << index
+          << ")' with value ";
+      UniversalPrint(u, os);
+    }
+    ::std::ostream* os;
+    std::size_t index;
+  };
+};
+
+#endif  // GTEST_INTERNAL_HAS_VARIANT
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(const char* begin, size_t len,
+                                    ::std::ostream* os);
+
+#ifdef __cpp_lib_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);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+
+template <typename T>
+class UniversalTersePrinter {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T>
+class UniversalTersePrinter<T&> {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T>
+class UniversalTersePrinter<std::reference_wrapper<T>> {
+ public:
+  static void Print(std::reference_wrapper<T> value, ::std::ostream* os) {
+    UniversalTersePrinter<T>::Print(value.get(), os);
+  }
+};
+template <typename T, size_t N>
+class UniversalTersePrinter<T[N]> {
+ public:
+  static void Print(const T (&value)[N], ::std::ostream* os) {
+    UniversalPrinter<T[N]>::Print(value, os);
+  }
+};
+template <>
+class UniversalTersePrinter<const char*> {
+ public:
+  static void Print(const char* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(std::string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
+};
+
+#ifdef __cpp_lib_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(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 <>
+class UniversalTersePrinter<const wchar_t*> {
+ public:
+  static void Print(const wchar_t* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::wstring(str), os);
+    }
+  }
+};
+#endif
+
+template <>
+class UniversalTersePrinter<wchar_t*> {
+ public:
+  static void Print(wchar_t* str, ::std::ostream* os) {
+    UniversalTersePrinter<const wchar_t*>::Print(str, os);
+  }
+};
+
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalTersePrinter<T>::Print(value, os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
+  // UniversalPrinter with T directly.
+  typedef T T1;
+  UniversalPrinter<T1>::Print(value, os);
+}
+
+typedef ::std::vector<::std::string> Strings;
+
+// Tersely prints the first N fields of a tuple to a string vector,
+// one element for each field.
+template <typename Tuple>
+void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
+                               Strings*) {}
+template <typename Tuple, size_t I>
+void TersePrintPrefixToStrings(const Tuple& t,
+                               std::integral_constant<size_t, I>,
+                               Strings* strings) {
+  TersePrintPrefixToStrings(t, std::integral_constant<size_t, I - 1>(),
+                            strings);
+  ::std::stringstream ss;
+  UniversalTersePrint(std::get<I - 1>(t), &ss);
+  strings->push_back(ss.str());
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TersePrintPrefixToStrings(
+      value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(),
+      &result);
+  return result;
+}
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+// Include any custom printer added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+#include "gtest/internal/custom/gtest-printers.h"
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-spi.h b/3rd-party/googletest/googletest/include/gtest/gtest-spi.h
new file mode 100644
index 0000000..c0613b6
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-spi.h
@@ -0,0 +1,250 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  ~ScopedFakeTestPartResultReporter() override;
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  void ReportTestPartResult(const TestPartResult& result) override;
+
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  ScopedFakeTestPartResultReporter(const ScopedFakeTestPartResultReporter&) =
+      delete;
+  ScopedFakeTestPartResultReporter& operator=(
+      const ScopedFakeTestPartResultReporter&) = delete;
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type, const std::string& substr);
+  ~SingleFailureChecker();
+
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const std::string substr_;
+
+  SingleFailureChecker(const SingleFailureChecker&) = delete;
+  SingleFailureChecker& operator=(const SingleFailureChecker&) = delete;
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures (e.g. a failure from an ASSERT_EQ, but
+// not a non-fatal failure, as from EXPECT_EQ).  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr)                               \
+  do {                                                                        \
+    class GTestExpectFatalFailureHelper {                                     \
+     public:                                                                  \
+      static void Execute() { statement; }                                    \
+    };                                                                        \
+    ::testing::TestPartResultArray gtest_failures;                            \
+    ::testing::internal::SingleFailureChecker gtest_checker(                  \
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
+    {                                                                         \
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(             \
+          ::testing::ScopedFakeTestPartResultReporter::                       \
+              INTERCEPT_ONLY_CURRENT_THREAD,                                  \
+          &gtest_failures);                                                   \
+      GTestExpectFatalFailureHelper::Execute();                               \
+    }                                                                         \
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr)                \
+  do {                                                                        \
+    class GTestExpectFatalFailureHelper {                                     \
+     public:                                                                  \
+      static void Execute() { statement; }                                    \
+    };                                                                        \
+    ::testing::TestPartResultArray gtest_failures;                            \
+    ::testing::internal::SingleFailureChecker gtest_checker(                  \
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
+    {                                                                         \
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(             \
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+          &gtest_failures);                                                   \
+      GTestExpectFatalFailureHelper::Execute();                               \
+    }                                                                         \
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures (e.g. a failure from an EXPECT_EQ,
+// but not from an ASSERT_EQ). It asserts that the given statement will cause
+// exactly one non-fatal Google Test failure with 'substr' being part of the
+// failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr)                    \
+  do {                                                                \
+    ::testing::TestPartResultArray gtest_failures;                    \
+    ::testing::internal::SingleFailureChecker gtest_checker(          \
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));                                                    \
+    {                                                                 \
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(     \
+          ::testing::ScopedFakeTestPartResultReporter::               \
+              INTERCEPT_ONLY_CURRENT_THREAD,                          \
+          &gtest_failures);                                           \
+      if (::testing::internal::AlwaysTrue()) {                        \
+        statement;                                                    \
+      }                                                               \
+    }                                                                 \
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr)             \
+  do {                                                                        \
+    ::testing::TestPartResultArray gtest_failures;                            \
+    ::testing::internal::SingleFailureChecker gtest_checker(                  \
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure,         \
+        (substr));                                                            \
+    {                                                                         \
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(             \
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+          &gtest_failures);                                                   \
+      if (::testing::internal::AlwaysTrue()) {                                \
+        statement;                                                            \
+      }                                                                       \
+    }                                                                         \
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-test-part.h b/3rd-party/googletest/googletest/include/gtest/gtest-test-part.h
new file mode 100644
index 0000000..41c8a9a
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-test-part.h
@@ -0,0 +1,192 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure,     // Failed and the test should be terminated.
+    kSkip              // Skipped.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name == nullptr ? "" : a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {}
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const {
+    return file_name_.empty() ? nullptr : file_name_.c_str();
+  }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true if and only if the test part was skipped.
+  bool skipped() const { return type_ == kSkip; }
+
+  // Returns true if and only if the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true if and only if the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true if and only if the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+
+  // Returns true if and only if the test part failed.
+  bool failed() const { return fatally_failed() || nonfatally_failed(); }
+
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static std::string ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // "" if the source file is unknown.
+  std::string file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  std::string summary_;  // The test failure summary.
+  std::string message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() = default;
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  TestPartResultArray(const TestPartResultArray&) = delete;
+  TestPartResultArray& operator=(const TestPartResultArray&) = delete;
+};
+
+// This interface knows how to report a test part result.
+class GTEST_API_ TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() = default;
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  ~HasNewFatalFailureHelper() override;
+  void ReportTestPartResult(const TestPartResult& result) override;
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  HasNewFatalFailureHelper(const HasNewFatalFailureHelper&) = delete;
+  HasNewFatalFailureHelper& operator=(const HasNewFatalFailureHelper&) = delete;
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest-typed-test.h b/3rd-party/googletest/googletest/include/gtest/gtest-typed-test.h
new file mode 100644
index 0000000..305b0b5
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest-typed-test.h
@@ -0,0 +1,335 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test suite, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_SUITE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_SUITE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test suite as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+// TYPED_TEST_SUITE takes an optional third argument which allows to specify a
+// class that generates custom test name suffixes based on the type. This should
+// be a class which has a static template function GetName(int index) returning
+// a string for each type. The provided integer index equals the index of the
+// type in the provided type list. In many cases the index can be ignored.
+//
+// For example:
+//   class MyTypeNames {
+//    public:
+//     template <typename T>
+//     static std::string GetName(int) {
+//       if (std::is_same<T, char>()) return "char";
+//       if (std::is_same<T, int>()) return "int";
+//       if (std::is_same<T, unsigned int>()) return "unsignedInt";
+//     }
+//   };
+//   TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test suite
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_SUITE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test suite as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test suite name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_SUITE_P(FooTest,
+                            DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test suite name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
+//
+// Similar to the optional argument of TYPED_TEST_SUITE above,
+// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
+// generate custom names.
+//   INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
+
+#endif  // 0
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test suite.
+#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
+
+// Expands to the name of the typedef for the NameGenerator, responsible for
+// creating the suffixes of the name.
+#define GTEST_NAME_GENERATOR_(TestSuiteName) \
+  gtest_type_params_##TestSuiteName##_NameGenerator
+
+#define TYPED_TEST_SUITE(CaseName, Types, ...)                          \
+  typedef ::testing::internal::GenerateTypeList<Types>::type            \
+      GTEST_TYPE_PARAMS_(CaseName);                                     \
+  typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
+  GTEST_NAME_GENERATOR_(CaseName)
+
+#define TYPED_TEST(CaseName, TestName)                                       \
+  static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1,                      \
+                "test-name must not be empty");                              \
+  template <typename gtest_TypeParam_>                                       \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName)                           \
+      : public CaseName<gtest_TypeParam_> {                                  \
+   private:                                                                  \
+    typedef CaseName<gtest_TypeParam_> TestFixture;                          \
+    typedef gtest_TypeParam_ TypeParam;                                      \
+    void TestBody() override;                                                \
+  };                                                                         \
+  GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool                          \
+      gtest_##CaseName##_##TestName##_registered_ =                          \
+          ::testing::internal::TypeParameterizedTest<                        \
+              CaseName,                                                      \
+              ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(       \
+                  CaseName, TestName)>,                                      \
+              GTEST_TYPE_PARAMS_(                                            \
+                  CaseName)>::Register("",                                   \
+                                       ::testing::internal::CodeLocation(    \
+                                           __FILE__, __LINE__),              \
+                                       GTEST_STRINGIFY_(CaseName),           \
+                                       GTEST_STRINGIFY_(TestName), 0,        \
+                                       ::testing::internal::GenerateNames<   \
+                                           GTEST_NAME_GENERATOR_(CaseName),  \
+                                           GTEST_TYPE_PARAMS_(CaseName)>()); \
+  template <typename gtest_TypeParam_>                                       \
+  void GTEST_TEST_CLASS_NAME_(CaseName,                                      \
+                              TestName)<gtest_TypeParam_>::TestBody()
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define TYPED_TEST_CASE                                                \
+  static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \
+  TYPED_TEST_SUITE
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Implements type-parameterized tests.
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test suite are defined in.  The exact
+// name of the namespace is subject to change without notice.
+#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test suite.
+#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
+  gtest_typed_test_suite_p_state_##TestSuiteName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test suite.
+#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
+  gtest_registered_test_names_##TestSuiteName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+#define TYPED_TEST_SUITE_P(SuiteName)              \
+  static ::testing::internal::TypedTestSuitePState \
+  GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define TYPED_TEST_CASE_P                                                 \
+  static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
+  TYPED_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+#define TYPED_TEST_P(SuiteName, TestName)                         \
+  namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                   \
+  template <typename gtest_TypeParam_>                            \
+  class TestName : public SuiteName<gtest_TypeParam_> {           \
+   private:                                                       \
+    typedef SuiteName<gtest_TypeParam_> TestFixture;              \
+    typedef gtest_TypeParam_ TypeParam;                           \
+    void TestBody() override;                                     \
+  };                                                              \
+  GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool               \
+      gtest_##TestName##_defined_ =                               \
+          GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
+              __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName),    \
+              GTEST_STRINGIFY_(TestName));                        \
+  }                                                               \
+  template <typename gtest_TypeParam_>                            \
+  void GTEST_SUITE_NAMESPACE_(                                    \
+      SuiteName)::TestName<gtest_TypeParam_>::TestBody()
+
+// Note: this won't work correctly if the trailing arguments are macros.
+#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...)                         \
+  namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                             \
+  typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_;      \
+  }                                                                         \
+  GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const            \
+  GTEST_REGISTERED_TEST_NAMES_(SuiteName) =                                 \
+      GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
+          GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define REGISTER_TYPED_TEST_CASE_P                                           \
+  static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
+                "");                                                         \
+  REGISTER_TYPED_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...)        \
+  static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1,                        \
+                "test-suit-prefix must not be empty");                       \
+  GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool                          \
+      gtest_##Prefix##_##SuiteName =                                         \
+          ::testing::internal::TypeParameterizedTestSuite<                   \
+              SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
+              ::testing::internal::GenerateTypeList<Types>::type>::          \
+              Register(                                                      \
+                  GTEST_STRINGIFY_(Prefix),                                  \
+                  ::testing::internal::CodeLocation(__FILE__, __LINE__),     \
+                  &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName),               \
+                  GTEST_STRINGIFY_(SuiteName),                               \
+                  GTEST_REGISTERED_TEST_NAMES_(SuiteName),                   \
+                  ::testing::internal::GenerateNames<                        \
+                      ::testing::internal::NameGeneratorSelector<            \
+                          __VA_ARGS__>::type,                                \
+                      ::testing::internal::GenerateTypeList<Types>::type>())
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define INSTANTIATE_TYPED_TEST_CASE_P                                      \
+  static_assert(                                                           \
+      ::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \
+  INSTANTIATE_TYPED_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest.h b/3rd-party/googletest/googletest/include/gtest/gtest.h
new file mode 100644
index 0000000..c899669
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest.h
@@ -0,0 +1,2338 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "gtest/gtest-assertion-result.h"  // IWYU pragma: export
+#include "gtest/gtest-death-test.h"  // IWYU pragma: export
+#include "gtest/gtest-matchers.h"  // IWYU pragma: export
+#include "gtest/gtest-message.h"  // IWYU pragma: export
+#include "gtest/gtest-param-test.h"  // IWYU pragma: export
+#include "gtest/gtest-printers.h"  // IWYU pragma: export
+#include "gtest/gtest-test-part.h"  // IWYU pragma: export
+#include "gtest/gtest-typed-test.h"  // IWYU pragma: export
+#include "gtest/gtest_pred_impl.h"  // IWYU pragma: export
+#include "gtest/gtest_prod.h"  // IWYU pragma: export
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag controls whether the test runner should continue execution past
+// first failure.
+GTEST_DECLARE_bool_(fail_fast);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag controls whether Google Test installs a signal handler that dumps
+// debugging information when fatal signals are raised.
+GTEST_DECLARE_bool_(install_failure_signal_handler);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints only test failures.
+GTEST_DECLARE_bool_(brief);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flags control whether Google Test prints UTF8 characters as text.
+GTEST_DECLARE_bool_(print_utf8);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test Environments are recreated for each
+// repeat of the tests. The default value is true. If set to false the global
+// test Environment objects are only set up once, for the first iteration, and
+// only torn down once, for the last.
+GTEST_DECLARE_bool_(recreate_environments_when_repeating);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise. For use with an external test framework.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+GTEST_DECLARE_string_(flagfile);
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+namespace testing {
+
+// Silence C4100 (unreferenced formal parameter) and 4805
+// unsafe mix of type 'const int' and type 'const bool'
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4805 4100)
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class StreamingListenerTest;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class UnitTestRecordPropertyTestHelper;
+class WindowsDeathTest;
+class FuchsiaDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message);
+std::set<std::string>* GetIgnoredParameterizedTestSuites();
+
+// A base class that prevents subclasses from being copyable.
+// We do this instead of using '= delete' so as to avoid triggering warnings
+// inside user code regarding any of our declarations.
+class GTestNonCopyable {
+ public:
+  GTestNonCopyable() = default;
+  GTestNonCopyable(const GTestNonCopyable&) = delete;
+  GTestNonCopyable& operator=(const GTestNonCopyable&) = delete;
+  ~GTestNonCopyable() = default;
+};
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestSuite;
+
+// Old API is still available but deprecated
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+using TestCase = TestSuite;
+#endif
+class TestInfo;
+class UnitTest;
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestSuites, and
+// each TestSuite contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used in a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     void SetUp() override { ... }
+//     void TearDown() override { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test suite.
+  //
+  // Google Test will call Foo::SetUpTestSuite() before running the first
+  // test in test suite Foo.  Hence a sub-class can define its own
+  // SetUpTestSuite() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestSuite() {}
+
+  // Tears down the stuff shared by all tests in this test suite.
+  //
+  // Google Test will call Foo::TearDownTestSuite() after running the last
+  // test in test suite Foo.  Hence a sub-class can define its own
+  // TearDownTestSuite() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestSuite() {}
+
+  // Legacy API is deprecated but still available. Use SetUpTestSuite and
+  // TearDownTestSuite instead.
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  static void TearDownTestCase() {}
+  static void SetUpTestCase() {}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Returns true if and only if the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true if and only if the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true if and only if the current test was skipped.
+  static bool IsSkipped();
+
+  // Returns true if and only if the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test, test suite, or for the entire
+  // invocation of the test program when used outside of the context of a
+  // test suite.  Only the last value for a given key is remembered.  These
+  // are public static so they can be called from utility functions that are
+  // not members of the test fixture.  Calls to RecordProperty made during
+  // lifespan of the test (from the moment its constructor starts to the
+  // moment its destructor finishes) will be output in XML as attributes of
+  // the <testcase> element.  Properties recorded from fixture's
+  // SetUpTestSuite or TearDownTestSuite are logged as attributes of the
+  // corresponding <testsuite> element.  Calls to RecordProperty made in the
+  // global context (before or after invocation of RUN_ALL_TESTS and from
+  // SetUp/TearDown method of Environment objects registered with Google
+  // Test) will be output as attributes of the <testsuites> element.
+  static void RecordProperty(const std::string& key, const std::string& value);
+  // We do not define a custom serialization except for values that can be
+  // converted to int64_t, but other values could be logged in this way.
+  template <typename T, std::enable_if_t<std::is_convertible<T, int64_t>::value,
+                                         bool> = true>
+  static void RecordProperty(const std::string& key, const T& value) {
+    RecordProperty(key, (Message() << value).GetString());
+  }
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true if and only if the current test has the same fixture class
+  // as the first test in the current test suite.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  const std::unique_ptr<GTEST_FLAG_SAVER_> gtest_flag_saver_;
+
+  // Often a user misspells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if void Setup() is declared in the user's
+  //   test fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if the method is called from the user's test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
+
+  // We disallow copying Tests.
+  Test(const Test&) = delete;
+  Test& operator=(const Test&) = delete;
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const std::string& a_key, const std::string& a_value)
+      : key_(a_key), value_(a_value) {}
+
+  // Gets the user supplied key.
+  const char* key() const { return key_.c_str(); }
+
+  // Gets the user supplied value.
+  const char* value() const { return value_.c_str(); }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const std::string& new_value) { value_ = new_value; }
+
+ private:
+  // The key supplied by the user.
+  std::string key_;
+  // The value supplied by the user.
+  std::string value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true if and only if the test passed (i.e. no test part failed).
+  bool Passed() const { return !Skipped() && !Failed(); }
+
+  // Returns true if and only if the test was skipped.
+  bool Skipped() const;
+
+  // Returns true if and only if the test failed.
+  bool Failed() const;
+
+  // Returns true if and only if the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true if and only if the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Gets the time of the test case start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Returns the i-th test part result among all the results. i can range from 0
+  // to total_part_count() - 1. If i is not in that range, aborts the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class TestSuite;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+  friend class internal::FuchsiaDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the start time.
+  void set_start_timestamp(TimeInMillis start) { start_timestamp_ = start; }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.  xml_element specifies the element for which the property is being
+  // recorded and is used for validation.
+  void RecordProperty(const std::string& xml_element,
+                      const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testsuite tags.  Returns true if the property is valid.
+  // FIXME: Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const std::string& xml_element,
+                                   const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properties_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The start time, in milliseconds since UNIX Epoch.
+  TimeInMillis start_timestamp_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  TestResult(const TestResult&) = delete;
+  TestResult& operator=(const TestResult&) = delete;
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test suite name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test suite name.
+  const char* test_suite_name() const { return test_suite_name_.c_str(); }
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const char* test_case_name() const { return test_suite_name(); }
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_ != nullptr) return type_param_->c_str();
+    return nullptr;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_ != nullptr) return value_param_->c_str();
+    return nullptr;
+  }
+
+  // Returns the file name where this test is defined.
+  const char* file() const { return location_.file.c_str(); }
+
+  // Returns the line where this test is defined.
+  int line() const { return location_.line; }
+
+  // Return true if this test should not be run because it's in another shard.
+  bool is_in_another_shard() const { return is_in_another_shard_; }
+
+  // Returns true if this test should run, that is if the test is not
+  // disabled (or it is disabled but the also_run_disabled_tests flag has
+  // been specified) and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test suite Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns true if and only if this test will appear in the XML report.
+  bool is_reportable() const {
+    // The XML report includes tests matching the filter, excluding those
+    // run in other shards.
+    return matches_filter_ && !is_in_another_shard_;
+  }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+#ifdef GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestSuite;
+  friend class internal::UnitTestImpl;
+  friend class internal::StreamingListenerTest;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      std::string test_suite_name, const char* name, const char* type_param,
+      const char* value_param, internal::CodeLocation code_location,
+      internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc,
+      internal::TearDownTestSuiteFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(std::string test_suite_name, std::string name,
+           const char* a_type_param,   // NULL if not a type-parameterized test
+           const char* a_value_param,  // NULL if not a value-parameterized test
+           internal::CodeLocation a_code_location,
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  // Skip and records the test result for this object.
+  void Skip();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_suite_name_;  // test suite name
+  const std::string name_;             // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const std::unique_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const std::unique_ptr<const ::std::string> value_param_;
+  internal::CodeLocation location_;
+  const internal::TypeId fixture_class_id_;  // ID of the test fixture class
+  bool should_run_;           // True if and only if this test should run
+  bool is_disabled_;          // True if and only if this test is disabled
+  bool matches_filter_;       // True if this test matches the
+                              // user-specified filter.
+  bool is_in_another_shard_;  // Will be run in another shard.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  TestInfo(const TestInfo&) = delete;
+  TestInfo& operator=(const TestInfo&) = delete;
+};
+
+// A test suite, which consists of a vector of TestInfos.
+//
+// TestSuite is not copyable.
+class GTEST_API_ TestSuite {
+ public:
+  // Creates a TestSuite with the given name.
+  //
+  // TestSuite does NOT have a default constructor.  Always use this
+  // constructor to create a TestSuite object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test suite
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test suite
+  //   tear_down_tc: pointer to the function that tears down the test suite
+  TestSuite(const std::string& name, const char* a_type_param,
+            internal::SetUpTestSuiteFunc set_up_tc,
+            internal::TearDownTestSuiteFunc tear_down_tc);
+
+  // Destructor of TestSuite.
+  virtual ~TestSuite();
+
+  // Gets the name of the TestSuite.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test suite.
+  const char* type_param() const {
+    if (type_param_ != nullptr) return type_param_->c_str();
+    return nullptr;
+  }
+
+  // Returns true if any test in this test suite should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test suite.
+  int successful_test_count() const;
+
+  // Gets the number of skipped tests in this test suite.
+  int skipped_test_count() const;
+
+  // Gets the number of failed tests in this test suite.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests in this test suite.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Get the number of tests in this test suite that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test suite.
+  int total_test_count() const;
+
+  // Returns true if and only if the test suite passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true if and only if the test suite failed.
+  bool Failed() const {
+    return failed_test_count() > 0 || ad_hoc_test_result().Failed();
+  }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Gets the time of the test suite start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+  // Returns the TestResult that holds test properties recorded during
+  // execution of SetUpTestSuite and TearDownTestSuite.
+  const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestSuite.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestSuite.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test suite.  Will delete the TestInfo upon
+  // destruction of the TestSuite object.
+  void AddTestInfo(TestInfo* test_info);
+
+  // Clears the results of all tests in this test suite.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test suite.
+  static void ClearTestSuiteResult(TestSuite* test_suite) {
+    test_suite->ClearResult();
+  }
+
+  // Runs every test in this TestSuite.
+  void Run();
+
+  // Skips the execution of tests under this TestSuite
+  void Skip();
+
+  // Runs SetUpTestSuite() for this TestSuite.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestSuite().
+  void RunSetUpTestSuite() {
+    if (set_up_tc_ != nullptr) {
+      (*set_up_tc_)();
+    }
+  }
+
+  // Runs TearDownTestSuite() for this TestSuite.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestSuite().
+  void RunTearDownTestSuite() {
+    if (tear_down_tc_ != nullptr) {
+      (*tear_down_tc_)();
+    }
+  }
+
+  // Returns true if and only if test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true if and only if test skipped.
+  static bool TestSkipped(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Skipped();
+  }
+
+  // Returns true if and only if test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true if and only if the test is disabled and will be reported in
+  // the XML report.
+  static bool TestReportableDisabled(const TestInfo* test_info) {
+    return test_info->is_reportable() && test_info->is_disabled_;
+  }
+
+  // Returns true if and only if test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true if and only if this test will appear in the XML report.
+  static bool TestReportable(const TestInfo* test_info) {
+    return test_info->is_reportable();
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test suite.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test suite.
+  std::string name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const std::unique_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test suite.
+  internal::SetUpTestSuiteFunc set_up_tc_;
+  // Pointer to the function that tears down the test suite.
+  internal::TearDownTestSuiteFunc tear_down_tc_;
+  // True if and only if any test in this test suite should run.
+  bool should_run_;
+  // The start time, in milliseconds since UNIX Epoch.
+  TimeInMillis start_timestamp_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+  // Holds test properties recorded during execution of SetUpTestSuite and
+  // TearDownTestSuite.
+  TestResult ad_hoc_test_result_;
+
+  // We disallow copying TestSuites.
+  TestSuite(const TestSuite&) = delete;
+  TestSuite& operator=(const TestSuite&) = delete;
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  You should subclass this to define your own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() = default;
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
+};
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Exception which can be thrown from TestEventListener::OnTestPartResult.
+class GTEST_API_ AssertionException
+    : public internal::GoogleTestFailureException {
+ public:
+  explicit AssertionException(const TestPartResult& result)
+      : GoogleTestFailureException(result) {}
+};
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() = default;
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test suite starts.
+  virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {}
+
+  //  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired when a test is disabled
+  virtual void OnTestDisabled(const TestInfo& /*test_info*/) {}
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  // If you want to throw an exception from this function to skip to the next
+  // TEST, it must be AssertionException defined above, or inherited from it.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test suite ends.
+  virtual void OnTestSuiteEnd(const TestSuite& /*test_suite*/) {}
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int /*iteration*/) override {}
+  void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {}
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& /*test_case*/) override {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnTestStart(const TestInfo& /*test_info*/) override {}
+  void OnTestDisabled(const TestInfo& /*test_info*/) override {}
+  void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
+  void OnTestEnd(const TestInfo& /*test_info*/) override {}
+  void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& /*test_case*/) override {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                          int /*iteration*/) override {}
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  void SuppressEventForwarding(bool);
+
+ private:
+  friend class TestSuite;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  TestEventListeners(const TestEventListeners&) = delete;
+  TestEventListeners& operator=(const TestEventListeners&) = delete;
+};
+
+// A UnitTest consists of a vector of TestSuites.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestSuite object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestSuite* current_test_suite() const GTEST_LOCK_EXCLUDED_(mutex_);
+
+// Legacy API is still available but deprecated
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const TestCase* current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_);
+#endif
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+  // Returns the ParameterizedTestSuiteRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestSuiteRegistry& parameterized_test_registry()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Gets the number of successful test suites.
+  int successful_test_suite_count() const;
+
+  // Gets the number of failed test suites.
+  int failed_test_suite_count() const;
+
+  // Gets the number of all test suites.
+  int total_test_suite_count() const;
+
+  // Gets the number of all test suites that contain at least one test
+  // that should run.
+  int test_suite_to_run_count() const;
+
+  //  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  int successful_test_case_count() const;
+  int failed_test_case_count() const;
+  int total_test_case_count() const;
+  int test_case_to_run_count() const;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of skipped tests.
+  int skipped_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true if and only if the unit test passed (i.e. all test suites
+  // passed).
+  bool Passed() const;
+
+  // Returns true if and only if the unit test failed (i.e. some test suite
+  // failed or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  const TestSuite* GetTestSuite(int i) const;
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const TestCase* GetTestCase(int i) const;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Returns the TestResult containing information on test failures and
+  // properties logged outside of individual test suites.
+  const TestResult& ad_hoc_test_result() const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name, int line_number,
+                         const std::string& message,
+                         const std::string& os_stack_trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Adds a TestProperty to the current TestResult object when invoked from
+  // inside a test, to current TestSuite's ad_hoc_test_result_ when invoked
+  // from SetUpTestSuite or TearDownTestSuite, or to the global property set
+  // when invoked elsewhere.  If the result already contains a property with
+  // the same key, the value will be updated.
+  void RecordProperty(const std::string& key, const std::string& value);
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  TestSuite* GetMutableTestSuite(int i);
+
+  // Invokes OsStackTrackGetterInterface::UponLeavingGTest. UponLeavingGTest()
+  // should be called immediately before Google Test calls user code. It saves
+  // some information about the current stack that CurrentStackTrace() will use
+  // to find and hide Google Test stack frames.
+  void UponLeavingGTest();
+
+  // Sets the TestSuite object for the test that's currently running.
+  void set_current_test_suite(TestSuite* a_current_test_suite)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Sets the TestInfo object for the test that's currently running.
+  void set_current_test_info(TestInfo* a_current_test_info)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and functions are friends as they need to access private
+  // members of UnitTest.
+  friend class ScopedTrace;
+  friend class Test;
+  friend class TestInfo;
+  friend class TestSuite;
+  friend class internal::AssertHelper;
+  friend class internal::StreamingListenerTest;
+  friend class internal::UnitTestRecordPropertyTestHelper;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend std::set<std::string>* internal::GetIgnoredParameterizedTestSuites();
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type, const std::string& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  UnitTest(const UnitTest&) = delete;
+  UnitTest& operator=(const UnitTest&) = delete;
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+// This overloaded version can be used on Arduino/embedded platforms where
+// there is no argc/argv.
+GTEST_API_ void InitGoogleTest();
+
+namespace internal {
+
+// Separate the error generating code from the code path to reduce the stack
+// frame size of CmpHelperEQ. This helps reduce the overhead of some sanitizers
+// when calling EXPECT_* in a tight loop.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQFailure(const char* lhs_expression,
+                                   const char* rhs_expression, const T1& lhs,
+                                   const T2& rhs) {
+  return EqFailure(lhs_expression, rhs_expression,
+                   FormatForComparisonFailureMessage(lhs, rhs),
+                   FormatForComparisonFailureMessage(rhs, lhs), false);
+}
+
+// This block of code defines operator==/!=
+// to block lexical scope lookup.
+// It prevents using invalid operator==/!= defined at namespace scope.
+struct faketype {};
+inline bool operator==(faketype, faketype) { return true; }
+inline bool operator!=(faketype, faketype) { return false; }
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* lhs_expression,
+                            const char* rhs_expression, const T1& lhs,
+                            const T2& rhs) {
+  if (lhs == rhs) {
+    return AssertionSuccess();
+  }
+
+  return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
+}
+
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <
+      typename T1, typename T2,
+      // Disable this overload for cases where one argument is a pointer
+      // and the other is the null pointer constant.
+      typename std::enable_if<!std::is_integral<T1>::value ||
+                              !std::is_pointer<T2>::value>::type* = nullptr>
+  static AssertionResult Compare(const char* lhs_expression,
+                                 const char* rhs_expression, const T1& lhs,
+                                 const T2& rhs) {
+    return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* lhs_expression,
+                                 const char* rhs_expression, BiggestInt lhs,
+                                 BiggestInt rhs) {
+    return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
+  }
+
+  template <typename T>
+  static AssertionResult Compare(
+      const char* lhs_expression, const char* rhs_expression,
+      // Handle cases where '0' is used as a null pointer literal.
+      std::nullptr_t /* lhs */, T* rhs) {
+    // We already know that 'lhs' is a null pointer.
+    return CmpHelperEQ(lhs_expression, rhs_expression, static_cast<T*>(nullptr),
+                       rhs);
+  }
+};
+
+// Separate the error generating code from the code path to reduce the stack
+// frame size of CmpHelperOP. This helps reduce the overhead of some sanitizers
+// when calling EXPECT_OP in a tight loop.
+template <typename T1, typename T2>
+AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
+                                   const T1& val1, const T2& val2,
+                                   const char* op) {
+  return AssertionFailure()
+         << "Expected: (" << expr1 << ") " << op << " (" << expr2
+         << "), actual: " << FormatForComparisonFailureMessage(val1, val2)
+         << " vs " << FormatForComparisonFailureMessage(val2, val1);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)                                \
+  template <typename T1, typename T2>                                      \
+  AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                     const T1& val1, const T2& val2) {     \
+    if (val1 op val2) {                                                    \
+      return AssertionSuccess();                                           \
+    } else {                                                               \
+      return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);            \
+    }                                                                      \
+  }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, <)
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, >)
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1, const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1, const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1, const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1, const char* s2);
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1, const wchar_t* s2);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1, const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
+                                       const char* haystack_expr,
+                                       const char* needle,
+                                       const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
+                                       const char* haystack_expr,
+                                       const wchar_t* needle,
+                                       const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
+                                          const char* haystack_expr,
+                                          const char* needle,
+                                          const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
+                                          const char* haystack_expr,
+                                          const wchar_t* needle,
+                                          const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
+                                       const char* haystack_expr,
+                                       const ::std::string& needle,
+                                       const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
+                                          const char* haystack_expr,
+                                          const ::std::string& needle,
+                                          const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
+                                       const char* haystack_expr,
+                                       const ::std::wstring& needle,
+                                       const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
+                                          const char* haystack_expr,
+                                          const ::std::wstring& needle,
+                                          const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
+                                         const char* rhs_expression,
+                                         RawType lhs_value, RawType rhs_value) {
+  const FloatingPoint<RawType> lhs(lhs_value), rhs(rhs_value);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream lhs_ss;
+  lhs_ss.precision(std::numeric_limits<RawType>::digits10 + 2);
+  lhs_ss << lhs_value;
+
+  ::std::stringstream rhs_ss;
+  rhs_ss.precision(std::numeric_limits<RawType>::digits10 + 2);
+  rhs_ss << rhs_value;
+
+  return EqFailure(lhs_expression, rhs_expression,
+                   StringStreamToString(&lhs_ss), StringStreamToString(&rhs_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1, double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type, const char* file, int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t, const char* srcfile, int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) {}
+
+    TestPartResult::Type const type;
+    const char* const file;
+    int const line;
+    std::string const message;
+
+   private:
+    AssertHelperData(const AssertHelperData&) = delete;
+    AssertHelperData& operator=(const AssertHelperData&) = delete;
+  };
+
+  AssertHelperData* const data_;
+
+  AssertHelper(const AssertHelper&) = delete;
+  AssertHelper& operator=(const AssertHelper&) = delete;
+};
+
+}  // namespace internal
+
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), Combine(), and ConvertGenerator<T>().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   ~FooTest() override {
+//     // Can use GetParam() here.
+//   }
+//   void SetUp() override {
+//     // Can use GetParam() here.
+//   }
+//   void TearDown override {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() = default;
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor.
+  static const ParamType& GetParam() {
+    GTEST_CHECK_(parameter_ != nullptr)
+        << "GetParam() can only be called inside a value-parameterized test "
+        << "-- did you intend to write TEST_P instead of TEST_F?";
+    return *parameter_;
+  }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) { parameter_ = parameter; }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass>
+  friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = nullptr;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {};
+
+// Macros for indicating success/failure in test code.
+
+// Skips test in runtime.
+// Skipping test aborts current function.
+// Skipped tests are neither successful nor failed.
+#define GTEST_SKIP() GTEST_SKIP_("")
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line)        \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Like GTEST_FAIL(), but at the given source file location.
+#define GTEST_FAIL_AT(file, line)                \
+  return GTEST_MESSAGE_AT_(file, line, "Failed", \
+                           ::testing::TestPartResult::kFatalFailure)
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
+#define FAIL() GTEST_FAIL()
+#define FAIL_AT(file, line) GTEST_FAIL_AT(file, line)
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
+#define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// 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 GTEST_EXPECT_TRUE(condition)                      \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define GTEST_EXPECT_FALSE(condition)                        \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define GTEST_ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, GTEST_FATAL_FAILURE_)
+#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 !(defined(GTEST_DONT_DEFINE_EXPECT_TRUE) && GTEST_DONT_DEFINE_EXPECT_TRUE)
+#define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_EXPECT_FALSE) && GTEST_DONT_DEFINE_EXPECT_FALSE)
+#define EXPECT_FALSE(condition) GTEST_EXPECT_FALSE(condition)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_TRUE) && GTEST_DONT_DEFINE_ASSERT_TRUE)
+#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_FALSE) && 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
+//    * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(v1, v2) is preferred to
+//   {ASSERT|EXPECT}_TRUE(v1 == v2), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(Foo(), 5);
+//   EXPECT_EQ(a_pointer, NULL);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
+#define EXPECT_NE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_EQ) && GTEST_DONT_DEFINE_ASSERT_EQ)
+#define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_NE) && GTEST_DONT_DEFINE_ASSERT_NE)
+#define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_LE) && GTEST_DONT_DEFINE_ASSERT_LE)
+#define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_LT) && GTEST_DONT_DEFINE_ASSERT_LT)
+#define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_GE) && GTEST_DONT_DEFINE_ASSERT_GE)
+#define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !(defined(GTEST_DONT_DEFINE_ASSERT_GT) && GTEST_DONT_DEFINE_ASSERT_GT)
+#define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C-string Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
+#define EXPECT_STRCASENE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
+#define ASSERT_STRCASENE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(val1, val2):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(val1, val2):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(val1, val2)                                         \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      val1, val2)
+
+#define EXPECT_DOUBLE_EQ(val1, val2)                                         \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      val1, val2)
+
+#define ASSERT_FLOAT_EQ(val1, val2)                                         \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      val1, val2)
+
+#define ASSERT_DOUBLE_EQ(val1, val2)                                         \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      val1, val2)
+
+#define EXPECT_NEAR(val1, val2, abs_error)                                   \
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, val1, val2, \
+                      abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)                                   \
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, val1, val2, \
+                      abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+#ifdef GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+#define EXPECT_HRESULT_SUCCEEDED(expr) \
+  EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+#define ASSERT_HRESULT_SUCCEEDED(expr) \
+  ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+#define EXPECT_HRESULT_FAILED(expr) \
+  EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#define ASSERT_HRESULT_FAILED(expr) \
+  ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+  GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+  GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the given source file path and line number,
+// and the given message) to be included in every test failure message generated
+// by code in the scope of the lifetime of an instance of this class. The effect
+// is undone with the destruction of the instance.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// Example:
+//   testing::ScopedTrace trace("file.cc", 123, "message");
+//
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+
+  // Template version. Uses Message() to convert the values into strings.
+  // Slow, but flexible.
+  template <typename T>
+  ScopedTrace(const char* file, int line, const T& message) {
+    PushTrace(file, line, (Message() << message).GetString());
+  }
+
+  // Optimize for some known types.
+  ScopedTrace(const char* file, int line, const char* message) {
+    PushTrace(file, line, message ? message : "(null)");
+  }
+
+  ScopedTrace(const char* file, int line, const std::string& message) {
+    PushTrace(file, line, message);
+  }
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  void PushTrace(const char* file, int line, std::string message);
+
+  ScopedTrace(const ScopedTrace&) = delete;
+  ScopedTrace& operator=(const ScopedTrace&) = delete;
+};
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+//
+// Assuming that each thread maintains its own stack of traces.
+// Therefore, a SCOPED_TRACE() would (correctly) only affect the
+// assertions in its own thread.
+#define SCOPED_TRACE(message)                                               \
+  const ::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)( \
+      __FILE__, __LINE__, (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles if and only if type1 and type2
+// are the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+constexpr bool StaticAssertTypeEq() noexcept {
+  static_assert(std::is_same<T1, T2>::value, "T1 and T2 are not the same type");
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test suite, and the second
+// parameter is the name of the test within the test suite.
+//
+// The convention is to end the test suite name with "Test".  For
+// example, a test suite for the Foo class can be named FooTest.
+//
+// Test code should appear between braces after an invocation of
+// this macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_suite_name, test_name)             \
+  GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \
+              ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !(defined(GTEST_DONT_DEFINE_TEST) && GTEST_DONT_DEFINE_TEST)
+#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test suite name.  The second parameter is the
+// name of the test within the test suite.
+//
+// A test fixture class must be declared earlier.  The user should put
+// the test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     void SetUp() override { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(a_.size(), 0);
+//     EXPECT_EQ(b_.size(), 1);
+//   }
+#define GTEST_TEST_F(test_fixture, test_name)        \
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+#if !(defined(GTEST_DONT_DEFINE_TEST_F) && GTEST_DONT_DEFINE_TEST_F)
+#define TEST_F(test_fixture, test_name) GTEST_TEST_F(test_fixture, test_name)
+#endif
+
+// Returns a path to a temporary directory, which should be writable. It is
+// implementation-dependent whether or not the path is terminated by the
+// directory-separator character.
+GTEST_API_ std::string TempDir();
+
+// Returns a path to a directory that contains ancillary data files that might
+// be used by tests. It is implementation dependent whether or not the path is
+// terminated by the directory-separator character. The directory and the files
+// in it should be considered read-only.
+GTEST_API_ std::string SrcDir();
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4805 4100
+
+// Dynamically registers a test with the framework.
+//
+// This is an advanced API only to be used when the `TEST` macros are
+// insufficient. The macros should be preferred when possible, as they avoid
+// most of the complexity of calling this function.
+//
+// The `factory` argument is a factory callable (move-constructible) object or
+// function pointer that creates a new instance of the Test object. It
+// handles ownership to the caller. The signature of the callable is
+// `Fixture*()`, where `Fixture` is the test fixture class for the test. All
+// tests registered with the same `test_suite_name` must return the same
+// fixture type. This is checked at runtime.
+//
+// The framework will infer the fixture class from the factory and will call
+// the `SetUpTestSuite` and `TearDownTestSuite` for it.
+//
+// Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is
+// undefined.
+//
+// Use case example:
+//
+// class MyFixture : public ::testing::Test {
+//  public:
+//   // All of these optional, just like in regular macro usage.
+//   static void SetUpTestSuite() { ... }
+//   static void TearDownTestSuite() { ... }
+//   void SetUp() override { ... }
+//   void TearDown() override { ... }
+// };
+//
+// class MyTest : public MyFixture {
+//  public:
+//   explicit MyTest(int data) : data_(data) {}
+//   void TestBody() override { ... }
+//
+//  private:
+//   int data_;
+// };
+//
+// void RegisterMyTests(const std::vector<int>& values) {
+//   for (int v : values) {
+//     ::testing::RegisterTest(
+//         "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr,
+//         std::to_string(v).c_str(),
+//         __FILE__, __LINE__,
+//         // Important to use the fixture type as the return type here.
+//         [=]() -> MyFixture* { return new MyTest(v); });
+//   }
+// }
+// ...
+// int main(int argc, char** argv) {
+//   ::testing::InitGoogleTest(&argc, argv);
+//   std::vector<int> values_to_test = LoadValuesFromConfig();
+//   RegisterMyTests(values_to_test);
+//   ...
+//   return RUN_ALL_TESTS();
+// }
+//
+template <int&... ExplicitParameterBarrier, typename Factory>
+TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
+                       const char* type_param, const char* value_param,
+                       const char* file, int line, Factory factory) {
+  using TestT = typename std::remove_pointer<decltype(factory())>::type;
+
+  class FactoryImpl : public internal::TestFactoryBase {
+   public:
+    explicit FactoryImpl(Factory f) : factory_(std::move(f)) {}
+    Test* CreateTest() override { return factory_(); }
+
+   private:
+    Factory factory_;
+  };
+
+  return internal::MakeAndRegisterTestInfo(
+      test_suite_name, test_name, type_param, value_param,
+      internal::CodeLocation(file, line), internal::GetTypeId<TestT>(),
+      internal::SuiteApiResolver<TestT>::GetSetUpCaseOrSuite(file, line),
+      internal::SuiteApiResolver<TestT>::GetTearDownCaseOrSuite(file, line),
+      new FactoryImpl{std::move(factory)});
+}
+
+}  // namespace testing
+
+// Use this function in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest(). RUN_ALL_TESTS will tear down and delete any
+// installed environments and should only be called once per binary.
+//
+// This function was formerly a macro; thus, it is in the global
+// namespace and has an all-caps name.
+int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+
+inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest_pred_impl.h b/3rd-party/googletest/googletest/include/gtest/gtest_pred_impl.h
new file mode 100644
index 0000000..47a24aa
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,279 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Implements a family of generic predicate assertion macros.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+#include "gtest/gtest-assertion-result.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure)                   \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                 \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ;                                                           \
+  else                                                          \
+    on_failure(gtest_ar.failure_message())
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred, typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text, const char* e1,
+                                  Pred pred, const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure) \
+  GTEST_ASSERT_(pred_format(#v1, v1), on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure) \
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, #v1, pred, v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred, typename T1, typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text, const char* e1,
+                                  const char* e2, Pred pred, const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2
+         << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure) \
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)                               \
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, #v1, #v2, pred, v1, v2), \
+                on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred, typename T1, typename T2, typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text, const char* e1,
+                                  const char* e2, const char* e3, Pred pred,
+                                  const T1& v1, const T2& v2, const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2 << ", " << e3
+         << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
+         << e3 << " evaluates to " << ::testing::PrintToString(v3);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure) \
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)                          \
+  GTEST_ASSERT_(                                                            \
+      ::testing::AssertPred3Helper(#pred, #v1, #v2, #v3, pred, v1, v2, v3), \
+      on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred, typename T1, typename T2, typename T3, typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text, const char* e1,
+                                  const char* e2, const char* e3,
+                                  const char* e4, Pred pred, const T1& v1,
+                                  const T2& v2, const T3& v3, const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
+         << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
+         << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
+         << e4 << " evaluates to " << ::testing::PrintToString(v4);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure) \
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)                        \
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, #v1, #v2, #v3, #v4, pred, \
+                                             v1, v2, v3, v4),                 \
+                on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred, typename T1, typename T2, typename T3, typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text, const char* e1,
+                                  const char* e2, const char* e3,
+                                  const char* e4, const char* e5, Pred pred,
+                                  const T1& v1, const T2& v2, const T3& v3,
+                                  const T4& v4, const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
+         << ", " << e5 << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
+         << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
+         << e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n"
+         << e5 << " evaluates to " << ::testing::PrintToString(v5);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)  \
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)                   \
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, #v1, #v2, #v3, #v4, #v5, \
+                                             pred, v1, v2, v3, v4, v5),      \
+                on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/gtest_prod.h b/3rd-party/googletest/googletest/include/gtest/gtest_prod.h
new file mode 100644
index 0000000..1f37dc3
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/gtest_prod.h
@@ -0,0 +1,60 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google C++ Testing and Mocking Framework definitions useful in production
+// code.
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void PrivateMethod();
+//   FRIEND_TEST(MyClassTest, PrivateMethodWorks);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, PrivateMethodWorks) {
+//   // Can call MyClass::PrivateMethod() here.
+// }
+//
+// Note: The test class must be in the same namespace as the class being tested.
+// For example, putting MyClassTest in an anonymous namespace will not work.
+
+#define FRIEND_TEST(test_case_name, test_name) \
+  friend class test_case_name##_##test_name##_Test
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/custom/README.md b/3rd-party/googletest/googletest/include/gtest/internal/custom/README.md
new file mode 100644
index 0000000..cb49e2c
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/custom/README.md
@@ -0,0 +1,44 @@
+# Customization Points
+
+The custom directory is an injection point for custom user configurations.
+
+## Header `gtest.h`
+
+### The following macros can be defined:
+
+*   `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of
+    `OsStackTraceGetterInterface`.
+*   `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See
+    `testing::TempDir` for semantics and signature.
+
+## Header `gtest-port.h`
+
+The following macros can be defined:
+
+### Logging:
+
+*   `GTEST_LOG_(severity)`
+*   `GTEST_CHECK_(condition)`
+*   Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too.
+
+### Threading:
+
+*   `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided.
+*   `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal`
+    are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)`
+    and `GTEST_DEFINE_STATIC_MUTEX_(mutex)`
+*   `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)`
+*   `GTEST_LOCK_EXCLUDED_(locks)`
+
+### Underlying library support features
+
+*   `GTEST_HAS_CXXABI_H_`
+
+### Exporting API symbols:
+
+*   `GTEST_API_` - Specifier for exported symbols.
+
+## Header `gtest-printers.h`
+
+*   See documentation at `gtest/gtest-printers.h` for details on how to define a
+    custom printer.
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest-port.h b/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest-port.h
new file mode 100644
index 0000000..db02881
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest-port.h
@@ -0,0 +1,37 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest-printers.h b/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest-printers.h
new file mode 100644
index 0000000..b9495d8
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest-printers.h
@@ -0,0 +1,42 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file provides an injection point for custom printers in a local
+// installation of gTest.
+// It will be included from gtest-printers.h and the overrides in this file
+// will be visible to everyone.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest.h b/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest.h
new file mode 100644
index 0000000..afaaf17
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/custom/gtest.h
@@ -0,0 +1,37 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644
index 0000000..b363259
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -0,0 +1,306 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include <stdio.h>
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest-matchers.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+namespace testing {
+namespace internal {
+
+// Name of the flag (needed for parsing Google Test flag).
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
+// and interpreted as a regex (rather than an Eq matcher) for legacy
+// compatibility.
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    ::testing::internal::RE regex) {
+  return ContainsRegex(regex.pattern());
+}
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
+  return ContainsRegex(regex);
+}
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    const ::std::string& regex) {
+  return ContainsRegex(regex);
+}
+
+// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
+// used directly.
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    Matcher<const ::std::string&> matcher) {
+  return matcher;
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _Exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, Matcher<const std::string&> matcher,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() = default;
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) {}
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+
+   private:
+    DeathTest* const test_;
+    ReturnSentinel(const ReturnSentinel&) = delete;
+    ReturnSentinel& operator=(const ReturnSentinel&) = delete;
+  };
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const std::string& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static std::string last_death_test_message_;
+
+  DeathTest(const DeathTest&) = delete;
+  DeathTest& operator=(const DeathTest&) = delete;
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() = default;
+  virtual bool Create(const char* statement,
+                      Matcher<const std::string&> matcher, const char* file,
+                      int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  bool Create(const char* statement, Matcher<const std::string&> matcher,
+              const char* file, int line, DeathTest** test) override;
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+#if GTEST_HAS_EXCEPTIONS
+#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test)           \
+  try {                                                                      \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);               \
+  } catch (const ::std::exception& gtest_exception) {                        \
+    fprintf(                                                                 \
+        stderr,                                                              \
+        "\n%s: Caught std::exception-derived exception escaping the "        \
+        "death test statement. Exception message: %s\n",                     \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what());                                             \
+    fflush(stderr);                                                          \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) {                                                            \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+#else
+#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+#endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail)        \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
+  if (::testing::internal::AlwaysTrue()) {                                     \
+    ::testing::internal::DeathTest* gtest_dt;                                  \
+    if (!::testing::internal::DeathTest::Create(                               \
+            #statement,                                                        \
+            ::testing::internal::MakeDeathTestMatcher(regex_or_matcher),       \
+            __FILE__, __LINE__, &gtest_dt)) {                                  \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__);                        \
+    }                                                                          \
+    if (gtest_dt != nullptr) {                                                 \
+      std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) {                                        \
+        case ::testing::internal::DeathTest::OVERSEE_TEST:                     \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) {                \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__);                  \
+          }                                                                    \
+          break;                                                               \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: {                   \
+          const ::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
+              gtest_dt);                                                       \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt);            \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE);   \
+          break;                                                               \
+        }                                                                      \
+      }                                                                        \
+    }                                                                          \
+  } else                                                                       \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__)                                \
+        : fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
+// NDEBUG mode. In this case we need the statements to be executed and the macro
+// must accept a streamed message even though the message is never printed.
+// The regex object is not evaluated, but it is used to prevent "unused"
+// warnings and to avoid an expression that doesn't compile in debug mode.
+#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher)    \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                  \
+  if (::testing::internal::AlwaysTrue()) {                       \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);   \
+  } else if (!::testing::internal::AlwaysTrue()) {               \
+    ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
+  } else                                                         \
+    ::testing::Message()
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const std::string& a_file, int a_line, int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index), write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0) posix::Close(write_fd_);
+  }
+
+  const std::string& file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  std::string file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  InternalRunDeathTestFlag(const InternalRunDeathTestFlag&) = delete;
+  InternalRunDeathTestFlag& operator=(const InternalRunDeathTestFlag&) = delete;
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-filepath.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-filepath.h
new file mode 100644
index 0000000..6dc47be
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-filepath.h
@@ -0,0 +1,233 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in gtest/internal/gtest-internal.h.
+// Do not include this header file separately!
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include <string>
+#include <utility>
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+#if GTEST_HAS_FILE_SYSTEM
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") {}
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
+  FilePath(FilePath&& rhs) noexcept : pathname_(std::move(rhs.pathname_)) {}
+
+  explicit FilePath(std::string pathname) : pathname_(std::move(pathname)) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+  FilePath& operator=(FilePath&& rhs) noexcept {
+    pathname_ = std::move(rhs.pathname_);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; }
+
+  const std::string& string() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name, int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true if and only if the path is "".
+  bool IsEmpty() const { return pathname_.empty(); }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurrence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  // Returns the length of the path root, including the directory separator at
+  // the end of the prefix. Returns zero by definition if the path is relative.
+  // Examples:
+  // - [Windows] "..\Sibling" => 0
+  // - [Windows] "\Windows" => 1
+  // - [Windows] "C:/Windows\Notepad.exe" => 3
+  // - [Windows] "\\Host\Share\C$/Windows" => 13
+  // - [UNIX] "/bin" => 1
+  size_t CalculateRootLength() const;
+
+  std::string pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-internal.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-internal.h
new file mode 100644
index 0000000..7e55dc6
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-internal.h
@@ -0,0 +1,1521 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_OS_LINUX
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+#include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+
+#include <cstdint>
+#include <functional>
+#include <limits>
+#include <map>
+#include <set>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// https://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
+
+// Stringifies its argument.
+// Work around a bug in visual studio which doesn't accept code like this:
+//
+//   #define GTEST_STRINGIFY_(name) #name
+//   #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ...
+//   MACRO(, x, y)
+//
+// Complaining about the argument to GTEST_STRINGIFY_ being empty.
+// This is allowed by the spec.
+#define GTEST_STRINGIFY_HELPER_(name, ...) #name
+#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, )
+
+namespace proto2 {
+class MessageLite;
+}
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;  // Result of an assertion.
+class Message;          // Represents a failure message.
+class Test;             // Represents a test.
+class TestInfo;         // Information about a test.
+class TestPartResult;   // Result of a test part.
+class UnitTest;         // A collection of test suites.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;    // Information about a trace point.
+class TestInfoImpl;  // Opaque implementation of TestInfo
+class UnitTestImpl;  // Opaque implementation of UnitTest
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// An IgnoredValue object can be implicitly constructed from ANY value.
+class IgnoredValue {
+  struct Sink {};
+
+ public:
+  // This constructor template allows any value to be implicitly
+  // converted to IgnoredValue.  The object has no data member and
+  // doesn't try to remember anything about the argument.  We
+  // deliberately omit the 'explicit' keyword in order to allow the
+  // conversion to be implicit.
+  // Disable the conversion if T already has a magical conversion operator.
+  // Otherwise we get ambiguity.
+  template <typename T,
+            typename std::enable_if<!std::is_convertible<T, Sink>::value,
+                                    int>::type = 0>
+  IgnoredValue(const T& /* ignored */) {}  // NOLINT(runtime/explicit)
+};
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ std::string AppendUserMessage(const std::string& gtest_msg,
+                                         const Message& user_msg);
+
+#if GTEST_HAS_EXCEPTIONS
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(
+    4275 /* an exported class was derived from a class that was not exported */)
+
+// This exception is thrown by (and only by) a failed Google Test
+// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
+// are enabled).  We derive it from std::runtime_error, which is for
+// errors presumably detectable only at run time.  Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure);
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4275
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+namespace edit_distance {
+// Returns the optimal edits to go from 'left' to 'right'.
+// All edits cost the same, with replace having lower priority than
+// add/remove.
+// Simple implementation of the Wagner-Fischer algorithm.
+// See https://en.wikipedia.org/wiki/Wagner-Fischer_algorithm
+enum EditType { kMatch, kAdd, kRemove, kReplace };
+GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<size_t>& left, const std::vector<size_t>& right);
+
+// Same as above, but the input is represented as strings.
+GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<std::string>& left,
+    const std::vector<std::string>& right);
+
+// Create a diff of the input strings in Unified diff format.
+GTEST_API_ std::string CreateUnifiedDiff(const std::vector<std::string>& left,
+                                         const std::vector<std::string>& right,
+                                         size_t context = 2);
+
+}  // namespace edit_distance
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true if and only if the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const std::string& expected_value,
+                                     const std::string& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result, const char* expression_text,
+    const char* actual_predicate_value, const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   https://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8 * sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+      std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask = ~static_cast<Bits>(0) >>
+                                       (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+  static const uint32_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() { return ReinterpretBits(kExponentBitMask); }
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits& bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true if and only if this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true if and only if this number is at most kMaxUlps ULP's away
+  // from rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
+           kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read https://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits& sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
+                                                     const Bits& sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test suite, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() = default;
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  TestFactoryBase(const TestFactoryBase&) = delete;
+  TestFactoryBase& operator=(const TestFactoryBase&) = delete;
+};
+
+// This class provides implementation of TestFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  Test* CreateTest() override { return new TestClass; }
+};
+
+#ifdef GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestSuite() and TearDownTestSuite() functions.
+using SetUpTestSuiteFunc = void (*)();
+using TearDownTestSuiteFunc = void (*)();
+
+struct CodeLocation {
+  CodeLocation(std::string a_file, int a_line)
+      : file(std::move(a_file)), line(a_line) {}
+
+  std::string file;
+  int line;
+};
+
+//  Helper to identify which setup function for TestCase / TestSuite to call.
+//  Only one function is allowed, either TestCase or TestSute but not both.
+
+// Utility functions to help SuiteApiResolver
+using SetUpTearDownSuiteFuncType = void (*)();
+
+inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull(
+    SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) {
+  return a == def ? nullptr : a;
+}
+
+template <typename T>
+//  Note that SuiteApiResolver inherits from T because
+//  SetUpTestSuite()/TearDownTestSuite() could be protected. This way
+//  SuiteApiResolver can access them.
+struct SuiteApiResolver : T {
+  // testing::Test is only forward declared at this point. So we make it a
+  // dependent class for the compiler to be OK with it.
+  using Test =
+      typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
+
+  static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
+                                                        int line_num) {
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+    SetUpTearDownSuiteFuncType test_case_fp =
+        GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
+    SetUpTearDownSuiteFuncType test_suite_fp =
+        GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite);
+
+    GTEST_CHECK_(!test_case_fp || !test_suite_fp)
+        << "Test can not provide both SetUpTestSuite and SetUpTestCase, please "
+           "make sure there is only one present at "
+        << filename << ":" << line_num;
+
+    return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
+#else
+    (void)(filename);
+    (void)(line_num);
+    return &T::SetUpTestSuite;
+#endif
+  }
+
+  static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
+                                                           int line_num) {
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+    SetUpTearDownSuiteFuncType test_case_fp =
+        GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
+    SetUpTearDownSuiteFuncType test_suite_fp =
+        GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite);
+
+    GTEST_CHECK_(!test_case_fp || !test_suite_fp)
+        << "Test can not provide both TearDownTestSuite and TearDownTestCase,"
+           " please make sure there is only one present at"
+        << filename << ":" << line_num;
+
+    return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
+#else
+    (void)(filename);
+    (void)(line_num);
+    return &T::TearDownTestSuite;
+#endif
+  }
+};
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_suite_name:  name of the test suite
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   code_location:    code location where the test is defined
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test suite
+//   tear_down_tc:     pointer to the function that tears down the test suite
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    std::string test_suite_name, const char* name, const char* type_param,
+    const char* value_param, CodeLocation code_location,
+    TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
+    TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// State of the definition of a type-parameterized test suite.
+class GTEST_API_ TypedTestSuitePState {
+ public:
+  TypedTestSuitePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test suite hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr,
+              "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    registered_tests_.emplace(test_name, CodeLocation(file, line));
+    return true;
+  }
+
+  bool TestExists(const std::string& test_name) const {
+    return registered_tests_.count(test_name) > 0;
+  }
+
+  const CodeLocation& GetCodeLocation(const std::string& test_name) const {
+    RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name);
+    GTEST_CHECK_(it != registered_tests_.end());
+    return it->second;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(const char* test_suite_name,
+                                        const char* file, int line,
+                                        const char* registered_tests);
+
+ private:
+  typedef ::std::map<std::string, CodeLocation, std::less<>> RegisteredTestsMap;
+
+  bool registered_;
+  RegisteredTestsMap registered_tests_;
+};
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+using TypedTestCasePState = TypedTestSuitePState;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == nullptr) {
+    return nullptr;
+  }
+  while (IsSpace(*(++comma))) {
+  }
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline std::string GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == nullptr ? str : std::string(str, comma);
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.
+void SplitString(const ::std::string& str, char delimiter,
+                 ::std::vector<::std::string>* dest);
+
+// The default argument to the template below for the case when the user does
+// not provide a name generator.
+struct DefaultNameGenerator {
+  template <typename T>
+  static std::string GetName(int i) {
+    return StreamableToString(i);
+  }
+};
+
+template <typename Provided = DefaultNameGenerator>
+struct NameGeneratorSelector {
+  typedef Provided type;
+};
+
+template <typename NameGenerator>
+void GenerateNamesRecursively(internal::None, std::vector<std::string>*, int) {}
+
+template <typename NameGenerator, typename Types>
+void GenerateNamesRecursively(Types, std::vector<std::string>* result, int i) {
+  result->push_back(NameGenerator::template GetName<typename Types::Head>(i));
+  GenerateNamesRecursively<NameGenerator>(typename Types::Tail(), result,
+                                          i + 1);
+}
+
+template <typename NameGenerator, typename Types>
+std::vector<std::string> GenerateNames() {
+  std::vector<std::string> result;
+  GenerateNamesRecursively<NameGenerator>(Types(), &result, 0);
+  return result;
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, CodeLocation code_location,
+                       const char* case_name, const char* test_names, int index,
+                       const std::vector<std::string>& type_names =
+                           GenerateNames<DefaultNameGenerator, Types>()) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
+         "/" + type_names[static_cast<size_t>(index)]),
+        StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
+        GetTypeName<Type>().c_str(),
+        nullptr,  // No value parameter.
+        code_location, GetTypeId<FixtureClass>(),
+        SuiteApiResolver<TestClass>::GetSetUpCaseOrSuite(
+            code_location.file.c_str(), code_location.line),
+        SuiteApiResolver<TestClass>::GetTearDownCaseOrSuite(
+            code_location.file.c_str(), code_location.line),
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>::
+        Register(prefix, std::move(code_location), case_name, test_names,
+                 index + 1, type_names);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, internal::None> {
+ public:
+  static bool Register(const char* /*prefix*/, CodeLocation,
+                       const char* /*case_name*/, const char* /*test_names*/,
+                       int /*index*/,
+                       const std::vector<std::string>& =
+                           std::vector<std::string>() /*type_names*/) {
+    return true;
+  }
+};
+
+GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
+                                                   CodeLocation code_location);
+GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation(
+    const char* case_name);
+
+// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestSuite {
+ public:
+  static bool Register(const char* prefix, CodeLocation code_location,
+                       const TypedTestSuitePState* state, const char* case_name,
+                       const char* test_names,
+                       const std::vector<std::string>& type_names =
+                           GenerateNames<DefaultNameGenerator, Types>()) {
+    RegisterTypeParameterizedTestSuiteInstantiation(case_name);
+    std::string test_name =
+        StripTrailingSpaces(GetPrefixUntilComma(test_names));
+    if (!state->TestExists(test_name)) {
+      fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
+              case_name, test_name.c_str(),
+              FormatFileLocation(code_location.file.c_str(), code_location.line)
+                  .c_str());
+      fflush(stderr);
+      posix::Abort();
+    }
+    const CodeLocation& test_location = state->GetCodeLocation(test_name);
+
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, test_location, case_name, test_names, 0, type_names);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
+                                      Types>::Register(prefix,
+                                                       std::move(code_location),
+                                                       state, case_name,
+                                                       SkipComma(test_names),
+                                                       type_names);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestSuite<Fixture, internal::None, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const CodeLocation&,
+                       const TypedTestSuitePState* /*state*/,
+                       const char* /*case_name*/, const char* /*test_names*/,
+                       const std::vector<std::string>& =
+                           std::vector<std::string>() /*type_names*/) {
+    return true;
+  }
+};
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// Helper for declaring std::string within 'if' statement
+// in pre C++17 build environment.
+struct TrueWithString {
+  TrueWithString() = default;
+  explicit TrueWithString(const char* str) : value(str) {}
+  explicit TrueWithString(const std::string& str) : value(str) {}
+  explicit operator bool() const { return true; }
+  std::string value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const uint32_t kMaxRange = 1u << 31;
+
+  explicit Random(uint32_t seed) : state_(seed) {}
+
+  void Reseed(uint32_t seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  uint32_t Generate(uint32_t range);
+
+ private:
+  uint32_t state_;
+  Random(const Random&) = delete;
+  Random& operator=(const Random&) = delete;
+};
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+  typename std::remove_const<typename std::remove_reference<T>::type>::type
+
+// HasDebugStringAndShortDebugString<T>::value is a compile-time bool constant
+// that's true if and only if T has methods DebugString() and ShortDebugString()
+// that return std::string.
+template <typename T>
+class HasDebugStringAndShortDebugString {
+ private:
+  template <typename C>
+  static auto CheckDebugString(C*) -> typename std::is_same<
+      std::string, decltype(std::declval<const C>().DebugString())>::type;
+  template <typename>
+  static std::false_type CheckDebugString(...);
+
+  template <typename C>
+  static auto CheckShortDebugString(C*) -> typename std::is_same<
+      std::string, decltype(std::declval<const C>().ShortDebugString())>::type;
+  template <typename>
+  static std::false_type CheckShortDebugString(...);
+
+  using HasDebugStringType = decltype(CheckDebugString<T>(nullptr));
+  using HasShortDebugStringType = decltype(CheckShortDebugString<T>(nullptr));
+
+ public:
+  static constexpr bool value =
+      HasDebugStringType::value && HasShortDebugStringType::value;
+};
+
+#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+template <typename T>
+constexpr bool HasDebugStringAndShortDebugString<T>::value;
+#endif
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// In C++11 mode we check the existence of a const_iterator and that an
+// iterator is properly implemented for the container.
+//
+// For pre-C++11 that we look for both C::iterator and C::const_iterator.
+// The reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C,
+          class Iterator = decltype(::std::declval<const C&>().begin()),
+          class = decltype(::std::declval<const C&>().end()),
+          class = decltype(++::std::declval<Iterator&>()),
+          class = decltype(*::std::declval<Iterator>()),
+          class = typename C::const_iterator>
+IsContainer IsContainerTest(int /* dummy */) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) {
+  return '\0';
+}
+
+// Trait to detect whether a type T is a hash table.
+// The heuristic used is that the type contains an inner type `hasher` and does
+// not contain an inner type `reverse_iterator`.
+// If the container is iterable in reverse, then order might actually matter.
+template <typename T>
+struct IsHashTable {
+ private:
+  template <typename U>
+  static char test(typename U::hasher*, typename U::reverse_iterator*);
+  template <typename U>
+  static int test(typename U::hasher*, ...);
+  template <typename U>
+  static char test(...);
+
+ public:
+  static const bool value = sizeof(test<T>(nullptr, nullptr)) == sizeof(int);
+};
+
+template <typename T>
+const bool IsHashTable<T>::value;
+
+template <typename C,
+          bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
+struct IsRecursiveContainerImpl;
+
+template <typename C>
+struct IsRecursiveContainerImpl<C, false> : public std::false_type {};
+
+// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
+// obey the same inconsistencies as the IsContainerTest, namely check if
+// something is a container is relying on only const_iterator in C++11 and
+// is relying on both const_iterator and iterator otherwise
+template <typename C>
+struct IsRecursiveContainerImpl<C, true> {
+  using value_type = decltype(*std::declval<typename C::const_iterator>());
+  using type =
+      std::is_same<typename std::remove_const<
+                       typename std::remove_reference<value_type>::type>::type,
+                   C>;
+};
+
+// IsRecursiveContainer<Type> is a unary compile-time predicate that
+// evaluates whether C is a recursive container type. A recursive container
+// type is a container type whose value_type is equal to the container type
+// itself. An example for a recursive container type is
+// boost::filesystem::path, whose iterator has a value_type that is equal to
+// boost::filesystem::path.
+template <typename C>
+struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) {
+  return lhs == rhs;
+}
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T (&lhs)[N], const U (&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i])) return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem)) return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) {
+  *to = from;
+}
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T (&from)[N], U (*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+// We use 2 different structs to allow non-copyable types to be used, as long
+// as RelationToSourceReference() is passed.
+struct RelationToSourceReference {};
+struct RelationToSourceCopy {};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array. References the source.
+  NativeArray(const Element* array, size_t count, RelationToSourceReference) {
+    InitRef(array, count);
+  }
+
+  // Constructs from a native array. Copies the source.
+  NativeArray(const Element* array, size_t count, RelationToSourceCopy) {
+    InitCopy(array, count);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    (this->*rhs.clone_)(rhs.array_, rhs.size_);
+  }
+
+  ~NativeArray() {
+    if (clone_ != &NativeArray::InitRef) delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() && ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  static_assert(!std::is_const<Element>::value, "Type must not be const");
+  static_assert(!std::is_reference<Element>::value,
+                "Type must not be a reference");
+
+  // Initializes this object with a copy of the input.
+  void InitCopy(const Element* array, size_t a_size) {
+    Element* const copy = new Element[a_size];
+    CopyArray(array, a_size, copy);
+    array_ = copy;
+    size_ = a_size;
+    clone_ = &NativeArray::InitCopy;
+  }
+
+  // Initializes this object with a reference of the input.
+  void InitRef(const Element* array, size_t a_size) {
+    array_ = array;
+    size_ = a_size;
+    clone_ = &NativeArray::InitRef;
+  }
+
+  const Element* array_;
+  size_t size_;
+  void (NativeArray::*clone_)(const Element*, size_t);
+};
+
+template <size_t>
+struct Ignore {
+  Ignore(...);  // NOLINT
+};
+
+template <typename>
+struct ElemFromListImpl;
+template <size_t... I>
+struct ElemFromListImpl<std::index_sequence<I...>> {
+  // We make Ignore a template to solve a problem with MSVC.
+  // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but
+  // MSVC doesn't understand how to deal with that pack expansion.
+  // Use `0 * I` to have a single instantiation of Ignore.
+  template <typename R>
+  static R Apply(Ignore<0 * I>..., R (*)(), ...);
+};
+
+template <size_t N, typename... T>
+struct ElemFromList {
+  using type = decltype(ElemFromListImpl<std::make_index_sequence<N>>::Apply(
+      static_cast<T (*)()>(nullptr)...));
+};
+
+struct FlatTupleConstructTag {};
+
+template <typename... T>
+class FlatTuple;
+
+template <typename Derived, size_t I>
+struct FlatTupleElemBase;
+
+template <typename... T, size_t I>
+struct FlatTupleElemBase<FlatTuple<T...>, I> {
+  using value_type = typename ElemFromList<I, T...>::type;
+  FlatTupleElemBase() = default;
+  template <typename Arg>
+  explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t)
+      : value(std::forward<Arg>(t)) {}
+  value_type value;
+};
+
+template <typename Derived, typename Idx>
+struct FlatTupleBase;
+
+template <size_t... Idx, typename... T>
+struct FlatTupleBase<FlatTuple<T...>, std::index_sequence<Idx...>>
+    : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
+  using Indices = std::index_sequence<Idx...>;
+  FlatTupleBase() = default;
+  template <typename... Args>
+  explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
+      : FlatTupleElemBase<FlatTuple<T...>, Idx>(FlatTupleConstructTag{},
+                                                std::forward<Args>(args))... {}
+
+  template <size_t I>
+  const typename ElemFromList<I, T...>::type& Get() const {
+    return FlatTupleElemBase<FlatTuple<T...>, I>::value;
+  }
+
+  template <size_t I>
+  typename ElemFromList<I, T...>::type& Get() {
+    return FlatTupleElemBase<FlatTuple<T...>, I>::value;
+  }
+
+  template <typename F>
+  auto Apply(F&& f) -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
+    return std::forward<F>(f)(Get<Idx>()...);
+  }
+
+  template <typename F>
+  auto Apply(F&& f) const -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
+    return std::forward<F>(f)(Get<Idx>()...);
+  }
+};
+
+// Analog to std::tuple but with different tradeoffs.
+// This class minimizes the template instantiation depth, thus allowing more
+// elements than std::tuple would. std::tuple has been seen to require an
+// instantiation depth of more than 10x the number of elements in some
+// implementations.
+// FlatTuple and ElemFromList are not recursive and have a fixed depth
+// regardless of T...
+// std::make_index_sequence, on the other hand, it is recursive but with an
+// instantiation depth of O(ln(N)).
+template <typename... T>
+class FlatTuple
+    : private FlatTupleBase<FlatTuple<T...>,
+                            std::make_index_sequence<sizeof...(T)>> {
+  using Indices =
+      typename FlatTupleBase<FlatTuple<T...>,
+                             std::make_index_sequence<sizeof...(T)>>::Indices;
+
+ public:
+  FlatTuple() = default;
+  template <typename... Args>
+  explicit FlatTuple(FlatTupleConstructTag tag, Args&&... args)
+      : FlatTuple::FlatTupleBase(tag, std::forward<Args>(args)...) {}
+
+  using FlatTuple::FlatTupleBase::Apply;
+  using FlatTuple::FlatTupleBase::Get;
+};
+
+// Utility functions to be called with static_assert to induce deprecation
+// warnings.
+GTEST_INTERNAL_DEPRECATED(
+    "INSTANTIATE_TEST_CASE_P is deprecated, please use "
+    "INSTANTIATE_TEST_SUITE_P")
+constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "TYPED_TEST_CASE_P is deprecated, please use "
+    "TYPED_TEST_SUITE_P")
+constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "TYPED_TEST_CASE is deprecated, please use "
+    "TYPED_TEST_SUITE")
+constexpr bool TypedTestCaseIsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
+    "REGISTER_TYPED_TEST_SUITE_P")
+constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
+    "INSTANTIATE_TYPED_TEST_SUITE_P")
+constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
+
+}  // namespace internal
+}  // namespace testing
+
+namespace std {
+// Some standard library implementations use `struct tuple_size` and some use
+// `class tuple_size`. Clang warns about the mismatch.
+// https://reviews.llvm.org/D55466
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+template <typename... Ts>
+struct tuple_size<testing::internal::FlatTuple<Ts...>>
+    : std::integral_constant<size_t, sizeof...(Ts)> {};
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+}  // namespace std
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type)             \
+  ::testing::internal::AssertHelper(result_type, file, line, message) = \
+      ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+#define GTEST_SKIP_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)
+
+// Suppress MSVC warning 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+// NOTE: The "else" is important to keep this expansion to prevent a top-level
+// "else" from attaching to our "if".
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) {                        \
+    statement;                                                    \
+  } else                     /* NOLINT */                         \
+    static_assert(true, "")  // User must have a semicolon after expansion.
+
+#if GTEST_HAS_EXCEPTIONS
+
+namespace testing {
+namespace internal {
+
+class NeverThrown {
+ public:
+  const char* what() const noexcept {
+    return "this exception should never be thrown";
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#if GTEST_HAS_RTTI
+
+#define GTEST_EXCEPTION_TYPE_(e) ::testing::internal::GetTypeName(typeid(e))
+
+#else  // GTEST_HAS_RTTI
+
+#define GTEST_EXCEPTION_TYPE_(e) \
+  std::string { "an std::exception-derived error" }
+
+#endif  // GTEST_HAS_RTTI
+
+#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)   \
+  catch (typename std::conditional<                                            \
+         std::is_same<typename std::remove_cv<typename std::remove_reference<  \
+                          expected_exception>::type>::type,                    \
+                      std::exception>::value,                                  \
+         const ::testing::internal::NeverThrown&, const std::exception&>::type \
+             e) {                                                              \
+    gtest_msg.value = "Expected: " #statement                                  \
+                      " throws an exception of type " #expected_exception      \
+                      ".\n  Actual: it throws ";                               \
+    gtest_msg.value += GTEST_EXCEPTION_TYPE_(e);                               \
+    gtest_msg.value += " with description \"";                                 \
+    gtest_msg.value += e.what();                                               \
+    gtest_msg.value += "\".";                                                  \
+    goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);                \
+  }
+
+#else  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail)              \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                             \
+  if (::testing::internal::TrueWithString gtest_msg{}) {                    \
+    bool gtest_caught_expected = false;                                     \
+    try {                                                                   \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);            \
+    } catch (expected_exception const&) {                                   \
+      gtest_caught_expected = true;                                         \
+    }                                                                       \
+    GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)    \
+    catch (...) {                                                           \
+      gtest_msg.value = "Expected: " #statement                             \
+                        " throws an exception of type " #expected_exception \
+                        ".\n  Actual: it throws a different type.";         \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);           \
+    }                                                                       \
+    if (!gtest_caught_expected) {                                           \
+      gtest_msg.value = "Expected: " #statement                             \
+                        " throws an exception of type " #expected_exception \
+                        ".\n  Actual: it throws nothing.";                  \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);           \
+    }                                                                       \
+  } else /*NOLINT*/                                                         \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__)                   \
+        : fail(gtest_msg.value.c_str())
+
+#if GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_()                \
+  catch (std::exception const& e) {                               \
+    gtest_msg.value = "it throws ";                               \
+    gtest_msg.value += GTEST_EXCEPTION_TYPE_(e);                  \
+    gtest_msg.value += " with description \"";                    \
+    gtest_msg.value += e.what();                                  \
+    gtest_msg.value += "\".";                                     \
+    goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+  }
+
+#else  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_()
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_NO_THROW_(statement, fail)                            \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                          \
+  if (::testing::internal::TrueWithString gtest_msg{}) {                 \
+    try {                                                                \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);         \
+    }                                                                    \
+    GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_()                           \
+    catch (...) {                                                        \
+      gtest_msg.value = "it throws.";                                    \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__);      \
+    }                                                                    \
+  } else                                                                 \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__)              \
+        : fail(("Expected: " #statement " doesn't throw an exception.\n" \
+                "  Actual: " +                                           \
+                gtest_msg.value)                                         \
+                   .c_str())
+
+#define GTEST_TEST_ANY_THROW_(statement, fail)                       \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                      \
+  if (::testing::internal::AlwaysTrue()) {                           \
+    bool gtest_caught_any = false;                                   \
+    try {                                                            \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);     \
+    } catch (...) {                                                  \
+      gtest_caught_any = true;                                       \
+    }                                                                \
+    if (!gtest_caught_any) {                                         \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    }                                                                \
+  } else                                                             \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__)         \
+        : fail("Expected: " #statement                               \
+               " throws an exception.\n"                             \
+               "  Actual: it doesn't.")
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// representation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                       \
+  if (const ::testing::AssertionResult gtest_ar_ =                    \
+          ::testing::AssertionResult(expression))                     \
+    ;                                                                 \
+  else                                                                \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(         \
+             gtest_ar_, text, #actual, #expected)                     \
+             .c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail)               \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                     \
+  if (::testing::internal::AlwaysTrue()) {                          \
+    const ::testing::internal::HasNewFatalFailureHelper             \
+        gtest_fatal_failure_checker;                                \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);      \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) {      \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    }                                                               \
+  } else /* NOLINT */                                               \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__)         \
+        : fail("Expected: " #statement                              \
+               " doesn't generate new fatal "                       \
+               "failures in the current thread.\n"                  \
+               "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
+  test_suite_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id)       \
+  static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1,                 \
+                "test_suite_name must not be empty");                          \
+  static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1,                       \
+                "test_name must not be empty");                                \
+  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                     \
+      : public parent_class {                                                  \
+   public:                                                                     \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default;            \
+    ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default;  \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                         \
+    (const GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &) = delete;     \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=(            \
+        const GTEST_TEST_CLASS_NAME_(test_suite_name,                          \
+                                     test_name) &) = delete; /* NOLINT */      \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                         \
+    (GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &&) noexcept = delete; \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=(            \
+        GTEST_TEST_CLASS_NAME_(test_suite_name,                                \
+                               test_name) &&) noexcept = delete; /* NOLINT */  \
+                                                                               \
+   private:                                                                    \
+    void TestBody() override;                                                  \
+    GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static ::testing::TestInfo* const    \
+        test_info_;                                                            \
+  };                                                                           \
+                                                                               \
+  ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name,           \
+                                                    test_name)::test_info_ =   \
+      ::testing::internal::MakeAndRegisterTestInfo(                            \
+          #test_suite_name, #test_name, nullptr, nullptr,                      \
+          ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id),  \
+          ::testing::internal::SuiteApiResolver<                               \
+              parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__),          \
+          ::testing::internal::SuiteApiResolver<                               \
+              parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__),       \
+          new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_(     \
+              test_suite_name, test_name)>);                                   \
+  void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-param-util.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-param-util.h
new file mode 100644
index 0000000..cc7ea53
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-param-util.h
@@ -0,0 +1,1030 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Type and function utilities for implementing parameterized tests.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <ctype.h>
+
+#include <cassert>
+#include <iterator>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+// Input to a parameterized test name generator, describing a test parameter.
+// Consists of the parameter value and the integer parameter index.
+template <class ParamType>
+struct TestParamInfo {
+  TestParamInfo(const ParamType& a_param, size_t an_index)
+      : param(a_param), index(an_index) {}
+  ParamType param;
+  size_t index;
+};
+
+// A builtin parameterized test name generator which returns the result of
+// testing::PrintToString.
+struct PrintToStringParamName {
+  template <class ParamType>
+  std::string operator()(const TestParamInfo<ParamType>& info) const {
+    return PrintToString(info.param);
+  }
+};
+
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// Utility Functions
+
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test suite. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
+                                           const CodeLocation& code_location);
+
+template <typename>
+class ParamGeneratorInterface;
+template <typename>
+class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() = default;
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other) impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  std::unique_ptr<ParamIteratorInterface<T>> impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() = default;
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template <typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  std::shared_ptr<const ParamGeneratorInterface<T>> impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin),
+        end_(end),
+        step_(step),
+        end_index_(CalculateEndIndex(begin, end, step)) {}
+  ~RangeGenerator() override = default;
+
+  ParamIteratorInterface<T>* Begin() const override {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  ParamIteratorInterface<T>* End() const override {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    ~Iterator() override = default;
+
+    const ParamGeneratorInterface<T>* BaseGenerator() const override {
+      return base_;
+    }
+    void Advance() override {
+      value_ = static_cast<T>(value_ + step_);
+      index_++;
+    }
+    ParamIteratorInterface<T>* Clone() const override {
+      return new Iterator(*this);
+    }
+    const T* Current() const override { return &value_; }
+    bool Equals(const ParamIteratorInterface<T>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          value_(other.value_),
+          index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin, const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = static_cast<T>(i + step)) end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  ~ValuesInIteratorRangeGenerator() override = default;
+
+  ParamIteratorInterface<T>* Begin() const override {
+    return new Iterator(this, container_.begin());
+  }
+  ParamIteratorInterface<T>* End() const override {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    ~Iterator() override = default;
+
+    const ParamGeneratorInterface<T>* BaseGenerator() const override {
+      return base_;
+    }
+    void Advance() override {
+      ++iterator_;
+      value_.reset();
+    }
+    ParamIteratorInterface<T>* Clone() const override {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    const T* Current() const override {
+      if (value_.get() == nullptr) value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    bool Equals(const ParamIteratorInterface<T>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+             CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        // The explicit constructor call suppresses a false warning
+        // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of std::unique_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable std::unique_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Default parameterized test name generator, returns a string containing the
+// integer test parameter index.
+template <class ParamType>
+std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
+  return std::to_string(info.index);
+}
+
+template <typename T = int>
+void TestNotEmpty() {
+  static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
+}
+template <typename T = int>
+void TestNotEmpty(const T&) {}
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter)
+      : parameter_(parameter) {}
+  Test* CreateTest() override {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  ParameterizedTestFactory(const ParameterizedTestFactory&) = delete;
+  ParameterizedTestFactory& operator=(const ParameterizedTestFactory&) = delete;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() = default;
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestSuiteInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestSuite>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestSuite::ParamType> {
+ public:
+  using ParamType = typename TestSuite::ParamType;
+
+  TestMetaFactory() = default;
+
+  TestFactoryBase* CreateTestFactory(ParamType parameter) override {
+    return new ParameterizedTestFactory<TestSuite>(parameter);
+  }
+
+ private:
+  TestMetaFactory(const TestMetaFactory&) = delete;
+  TestMetaFactory& operator=(const TestMetaFactory&) = delete;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestSuiteInfoBase is a generic interface
+// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
+// a collection of pointers to the ParameterizedTestSuiteInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestSuiteInfoBase {
+ public:
+  virtual ~ParameterizedTestSuiteInfoBase() = default;
+
+  // Base part of test suite name for display purposes.
+  virtual const std::string& GetTestSuiteName() const = 0;
+  // Test suite id to verify identity.
+  virtual TypeId GetTestSuiteTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test suite right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more than once on any single
+  // instance of a ParameterizedTestSuiteInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestSuiteInfoBase() {}
+
+ private:
+  ParameterizedTestSuiteInfoBase(const ParameterizedTestSuiteInfoBase&) =
+      delete;
+  ParameterizedTestSuiteInfoBase& operator=(
+      const ParameterizedTestSuiteInfoBase&) = delete;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Report a the name of a test_suit as safe to ignore
+// as the side effect of construction of this type.
+struct GTEST_API_ MarkAsIgnored {
+  explicit MarkAsIgnored(const char* test_suite);
+};
+
+GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
+                                        CodeLocation location, bool has_test_p);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test suite and generators
+// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
+// test suite. It registers tests with all values generated by all
+// generators when asked.
+template <class TestSuite>
+class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestSuiteInstantiation().
+  using ParamType = typename TestSuite::ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+  using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
+
+  explicit ParameterizedTestSuiteInfo(std::string name,
+                                      CodeLocation code_location)
+      : test_suite_name_(std::move(name)),
+        code_location_(std::move(code_location)) {}
+
+  // Test suite base name for display purposes.
+  const std::string& GetTestSuiteName() const override {
+    return test_suite_name_;
+  }
+  // Test suite id to verify identity.
+  TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_suite_name is the base name of the test suite (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test suite base name and DoBar is test base name.
+  void AddTestPattern(const char*,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory,
+                      CodeLocation code_location) {
+    tests_.emplace_back(
+        new TestInfo(test_base_name, meta_factory, std::move(code_location)));
+  }
+  // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestSuiteInstantiation(std::string instantiation_name,
+                                GeneratorCreationFunc* func,
+                                ParamNameGeneratorFunc* name_func,
+                                const char* file, int line) {
+    instantiations_.emplace_back(std::move(instantiation_name), func, name_func,
+                                 file, line);
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test suite
+  // right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more than once on any single
+  // instance of a ParameterizedTestSuiteInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more than once.
+  void RegisterTests() override {
+    bool generated_instantiations = false;
+
+    std::string test_suite_name;
+    std::string test_name;
+    for (const std::shared_ptr<TestInfo>& test_info : tests_) {
+      for (const InstantiationInfo& instantiation : instantiations_) {
+        const std::string& instantiation_name = instantiation.name;
+        ParamGenerator<ParamType> generator((*instantiation.generator)());
+        ParamNameGeneratorFunc* name_func = instantiation.name_func;
+        const char* file = instantiation.file;
+        int line = instantiation.line;
+
+        if (!instantiation_name.empty())
+          test_suite_name = instantiation_name + "/";
+        else
+          test_suite_name.clear();
+        test_suite_name += test_suite_name_;
+
+        size_t i = 0;
+        std::set<std::string> test_param_names;
+        for (const auto& param : generator) {
+          generated_instantiations = true;
+
+          test_name.clear();
+
+          std::string param_name =
+              name_func(TestParamInfo<ParamType>(param, i));
+
+          GTEST_CHECK_(IsValidParamName(param_name))
+              << "Parameterized test name '" << param_name
+              << "' is invalid (contains spaces, dashes, or any "
+                 "non-alphanumeric characters other than underscores), in "
+              << file << " line " << line << "" << std::endl;
+
+          GTEST_CHECK_(test_param_names.count(param_name) == 0)
+              << "Duplicate parameterized test name '" << param_name << "', in "
+              << file << " line " << line << std::endl;
+
+          if (!test_info->test_base_name.empty()) {
+            test_name.append(test_info->test_base_name).append("/");
+          }
+          test_name += param_name;
+
+          test_param_names.insert(std::move(param_name));
+
+          MakeAndRegisterTestInfo(
+              test_suite_name, test_name.c_str(),
+              nullptr,  // No type parameter.
+              PrintToString(param).c_str(), test_info->code_location,
+              GetTestSuiteTypeId(),
+              SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
+              SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
+              test_info->test_meta_factory->CreateTestFactory(param));
+          ++i;
+        }  // for param
+      }  // for instantiation
+    }  // for test_info
+
+    if (!generated_instantiations) {
+      // There are no generaotrs, or they all generate nothing ...
+      InsertSyntheticTestCase(GetTestSuiteName(), code_location_,
+                              !tests_.empty());
+    }
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory,
+             CodeLocation a_code_location)
+        : test_base_name(a_test_base_name),
+          test_meta_factory(a_test_meta_factory),
+          code_location(std::move(a_code_location)) {}
+
+    const std::string test_base_name;
+    const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
+    const CodeLocation code_location;
+  };
+  using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo>>;
+  // Records data received from INSTANTIATE_TEST_SUITE_P macros:
+  //  <Instantiation name, Sequence generator creation function,
+  //     Name generator function, Source file, Source line>
+  struct InstantiationInfo {
+    InstantiationInfo(std::string name_in, GeneratorCreationFunc* generator_in,
+                      ParamNameGeneratorFunc* name_func_in, const char* file_in,
+                      int line_in)
+        : name(std::move(name_in)),
+          generator(generator_in),
+          name_func(name_func_in),
+          file(file_in),
+          line(line_in) {}
+
+    std::string name;
+    GeneratorCreationFunc* generator;
+    ParamNameGeneratorFunc* name_func;
+    const char* file;
+    int line;
+  };
+  typedef ::std::vector<InstantiationInfo> InstantiationContainer;
+
+  static bool IsValidParamName(const std::string& name) {
+    // Check for empty string
+    if (name.empty()) return false;
+
+    // Check for invalid characters
+    for (std::string::size_type index = 0; index < name.size(); ++index) {
+      if (!IsAlNum(name[index]) && name[index] != '_') return false;
+    }
+
+    return true;
+  }
+
+  const std::string test_suite_name_;
+  CodeLocation code_location_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  ParameterizedTestSuiteInfo(const ParameterizedTestSuiteInfo&) = delete;
+  ParameterizedTestSuiteInfo& operator=(const ParameterizedTestSuiteInfo&) =
+      delete;
+};  // class ParameterizedTestSuiteInfo
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+template <class TestCase>
+using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestSuiteRegistry contains a map of
+// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
+// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
+// ParameterizedTestSuiteInfo descriptors.
+class ParameterizedTestSuiteRegistry {
+ public:
+  ParameterizedTestSuiteRegistry() = default;
+  ~ParameterizedTestSuiteRegistry() {
+    for (auto& test_suite_info : test_suite_infos_) {
+      delete test_suite_info;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test suite.
+  template <class TestSuite>
+  ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
+      std::string test_suite_name, CodeLocation code_location) {
+    ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
+
+    auto item_it = suite_name_to_info_index_.find(test_suite_name);
+    if (item_it != suite_name_to_info_index_.end()) {
+      auto* test_suite_info = test_suite_infos_[item_it->second];
+      if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
+        // Complain about incorrect usage of Google Test facilities
+        // and terminate the program since we cannot guaranty correct
+        // test suite setup and tear-down in this case.
+        ReportInvalidTestSuiteType(test_suite_name.c_str(), code_location);
+        posix::Abort();
+      } else {
+        // At this point we are sure that the object we found is of the same
+        // type we are looking for, so we downcast it to that type
+        // without further checks.
+        typed_test_info =
+            CheckedDowncastToActualType<ParameterizedTestSuiteInfo<TestSuite>>(
+                test_suite_info);
+      }
+    }
+    if (typed_test_info == nullptr) {
+      typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
+          test_suite_name, std::move(code_location));
+      suite_name_to_info_index_.emplace(std::move(test_suite_name),
+                                        test_suite_infos_.size());
+      test_suite_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (auto& test_suite_info : test_suite_infos_) {
+      test_suite_info->RegisterTests();
+    }
+  }
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      std::string test_case_name, CodeLocation code_location) {
+    return GetTestSuitePatternHolder<TestCase>(std::move(test_case_name),
+                                               std::move(code_location));
+  }
+
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+ private:
+  using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
+
+  TestSuiteInfoContainer test_suite_infos_;
+  ::std::unordered_map<std::string, size_t> suite_name_to_info_index_;
+
+  ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
+      delete;
+  ParameterizedTestSuiteRegistry& operator=(
+      const ParameterizedTestSuiteRegistry&) = delete;
+};
+
+// Keep track of what type-parameterized test suite are defined and
+// where as well as which are intatiated. This allows susequently
+// identifying suits that are defined but never used.
+class TypeParameterizedTestSuiteRegistry {
+ public:
+  // Add a suite definition
+  void RegisterTestSuite(const char* test_suite_name,
+                         CodeLocation code_location);
+
+  // Add an instantiation of a suit.
+  void RegisterInstantiation(const char* test_suite_name);
+
+  // For each suit repored as defined but not reported as instantiation,
+  // emit a test that reports that fact (configurably, as an error).
+  void CheckForInstantiations();
+
+ private:
+  struct TypeParameterizedTestSuiteInfo {
+    explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
+        : code_location(std::move(c)), instantiated(false) {}
+
+    CodeLocation code_location;
+    bool instantiated;
+  };
+
+  std::map<std::string, TypeParameterizedTestSuiteInfo> suites_;
+};
+
+}  // namespace internal
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+// Used in the Values() function to provide polymorphic capabilities.
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
+
+template <typename... Ts>
+class ValueArray {
+ public:
+  explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {  // NOLINT
+    return ValuesIn(MakeVector<T>(std::make_index_sequence<sizeof...(Ts)>()));
+  }
+
+ private:
+  template <typename T, size_t... I>
+  std::vector<T> MakeVector(std::index_sequence<I...>) const {
+    return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
+  }
+
+  FlatTuple<Ts...> v_;
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
+
+template <typename... T>
+class CartesianProductGenerator
+    : public ParamGeneratorInterface<::std::tuple<T...>> {
+ public:
+  typedef ::std::tuple<T...> ParamType;
+
+  CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
+      : generators_(g) {}
+  ~CartesianProductGenerator() override = default;
+
+  ParamIteratorInterface<ParamType>* Begin() const override {
+    return new Iterator(this, generators_, false);
+  }
+  ParamIteratorInterface<ParamType>* End() const override {
+    return new Iterator(this, generators_, true);
+  }
+
+ private:
+  template <class I>
+  class IteratorImpl;
+  template <size_t... I>
+  class IteratorImpl<std::index_sequence<I...>>
+      : public ParamIteratorInterface<ParamType> {
+   public:
+    IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
+                 const std::tuple<ParamGenerator<T>...>& generators,
+                 bool is_end)
+        : base_(base),
+          begin_(std::get<I>(generators).begin()...),
+          end_(std::get<I>(generators).end()...),
+          current_(is_end ? end_ : begin_) {
+      ComputeCurrentValue();
+    }
+    ~IteratorImpl() override = default;
+
+    const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    void Advance() override {
+      assert(!AtEnd());
+      // Advance the last iterator.
+      ++std::get<sizeof...(T) - 1>(current_);
+      // if that reaches end, propagate that up.
+      AdvanceIfEnd<sizeof...(T) - 1>();
+      ComputeCurrentValue();
+    }
+    ParamIteratorInterface<ParamType>* Clone() const override {
+      return new IteratorImpl(*this);
+    }
+
+    const ParamType* Current() const override { return current_value_.get(); }
+
+    bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const IteratorImpl* typed_other =
+          CheckedDowncastToActualType<const IteratorImpl>(&other);
+
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      if (AtEnd() && typed_other->AtEnd()) return true;
+
+      bool same = true;
+      bool dummy[] = {
+          (same = same && std::get<I>(current_) ==
+                              std::get<I>(typed_other->current_))...};
+      (void)dummy;
+      return same;
+    }
+
+   private:
+    template <size_t ThisI>
+    void AdvanceIfEnd() {
+      if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
+
+      bool last = ThisI == 0;
+      if (last) {
+        // We are done. Nothing else to propagate.
+        return;
+      }
+
+      constexpr size_t NextI = ThisI - (ThisI != 0);
+      std::get<ThisI>(current_) = std::get<ThisI>(begin_);
+      ++std::get<NextI>(current_);
+      AdvanceIfEnd<NextI>();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
+    }
+    bool AtEnd() const {
+      bool at_end = false;
+      bool dummy[] = {
+          (at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
+      (void)dummy;
+      return at_end;
+    }
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    std::tuple<typename ParamGenerator<T>::iterator...> begin_;
+    std::tuple<typename ParamGenerator<T>::iterator...> end_;
+    std::tuple<typename ParamGenerator<T>::iterator...> current_;
+    std::shared_ptr<ParamType> current_value_;
+  };
+
+  using Iterator = IteratorImpl<std::make_index_sequence<sizeof...(T)>>;
+
+  std::tuple<ParamGenerator<T>...> generators_;
+};
+
+template <class... Gen>
+class CartesianProductHolder {
+ public:
+  CartesianProductHolder(const Gen&... g) : generators_(g...) {}
+  template <typename... T>
+  operator ParamGenerator<::std::tuple<T...>>() const {
+    return ParamGenerator<::std::tuple<T...>>(
+        new CartesianProductGenerator<T...>(generators_));
+  }
+
+ private:
+  std::tuple<Gen...> generators_;
+};
+
+template <typename From, typename To>
+class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
+ public:
+  ParamGeneratorConverter(ParamGenerator<From> gen)  // NOLINT
+      : generator_(std::move(gen)) {}
+
+  ParamIteratorInterface<To>* Begin() const override {
+    return new Iterator(this, generator_.begin(), generator_.end());
+  }
+  ParamIteratorInterface<To>* End() const override {
+    return new Iterator(this, generator_.end(), generator_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<To> {
+   public:
+    Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it,
+             ParamIterator<From> end)
+        : base_(base), it_(it), end_(end) {
+      if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
+    }
+    ~Iterator() override = default;
+
+    const ParamGeneratorInterface<To>* BaseGenerator() const override {
+      return base_;
+    }
+    void Advance() override {
+      ++it_;
+      if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
+    }
+    ParamIteratorInterface<To>* Clone() const override {
+      return new Iterator(*this);
+    }
+    const To* Current() const override { return value_.get(); }
+    bool Equals(const ParamIteratorInterface<To>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const ParamIterator<From> other_it =
+          CheckedDowncastToActualType<const Iterator>(&other)->it_;
+      return it_ == other_it;
+    }
+
+   private:
+    Iterator(const Iterator& other) = default;
+
+    const ParamGeneratorInterface<To>* const base_;
+    ParamIterator<From> it_;
+    ParamIterator<From> end_;
+    std::shared_ptr<To> value_;
+  };  // class ParamGeneratorConverter::Iterator
+
+  ParamGenerator<From> generator_;
+};  // class ParamGeneratorConverter
+
+template <class Gen>
+class ParamConverterGenerator {
+ public:
+  ParamConverterGenerator(ParamGenerator<Gen> g)  // NOLINT
+      : generator_(std::move(g)) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {  // NOLINT
+    return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_));
+  }
+
+ private:
+  ParamGenerator<Gen> generator_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-port-arch.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
new file mode 100644
index 0000000..7ec968f
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
@@ -0,0 +1,124 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the GTEST_OS_* macro.
+// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+#define GTEST_OS_CYGWIN 1
+#elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
+#define GTEST_OS_WINDOWS_MINGW 1
+#define GTEST_OS_WINDOWS 1
+#elif defined _WIN32
+#define GTEST_OS_WINDOWS 1
+#ifdef _WIN32_WCE
+#define GTEST_OS_WINDOWS_MOBILE 1
+#elif defined(WINAPI_FAMILY)
+#include <winapifamily.h>
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#define GTEST_OS_WINDOWS_DESKTOP 1
+#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+#define GTEST_OS_WINDOWS_PHONE 1
+#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+#define GTEST_OS_WINDOWS_RT 1
+#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
+#define GTEST_OS_WINDOWS_PHONE 1
+#define GTEST_OS_WINDOWS_TV_TITLE 1
+#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES)
+#define GTEST_OS_WINDOWS_GAMES 1
+#else
+// WINAPI_FAMILY defined but no known partition matched.
+// Default to desktop.
+#define GTEST_OS_WINDOWS_DESKTOP 1
+#endif
+#else
+#define GTEST_OS_WINDOWS_DESKTOP 1
+#endif  // _WIN32_WCE
+#elif defined __OS2__
+#define GTEST_OS_OS2 1
+#elif defined __APPLE__
+#define GTEST_OS_MAC 1
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#define GTEST_OS_IOS 1
+#endif
+#elif defined __DragonFly__
+#define GTEST_OS_DRAGONFLY 1
+#elif defined __FreeBSD__
+#define GTEST_OS_FREEBSD 1
+#elif defined __Fuchsia__
+#define GTEST_OS_FUCHSIA 1
+#elif defined(__GNU__)
+#define GTEST_OS_GNU_HURD 1
+#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+#define GTEST_OS_GNU_KFREEBSD 1
+#elif defined __linux__
+#define GTEST_OS_LINUX 1
+#if defined __ANDROID__
+#define GTEST_OS_LINUX_ANDROID 1
+#endif
+#elif defined __MVS__
+#define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+#define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+#define GTEST_OS_AIX 1
+#elif defined(__hpux)
+#define GTEST_OS_HPUX 1
+#elif defined __native_client__
+#define GTEST_OS_NACL 1
+#elif defined __NetBSD__
+#define GTEST_OS_NETBSD 1
+#elif defined __OpenBSD__
+#define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+#define GTEST_OS_QNX 1
+#elif defined(__HAIKU__)
+#define GTEST_OS_HAIKU 1
+#elif defined ESP8266
+#define GTEST_OS_ESP8266 1
+#elif defined ESP32
+#define GTEST_OS_ESP32 1
+#elif defined(__XTENSA__)
+#define GTEST_OS_XTENSA 1
+#elif defined(__hexagon__)
+#define GTEST_OS_QURT 1
+#elif defined(CPU_QN9090) || defined(CPU_QN9090HN)
+#define GTEST_OS_NXP_QN9090 1
+#elif defined(NRF52)
+#define GTEST_OS_NRF52 1
+#endif  // __CYGWIN__
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-port.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-port.h
new file mode 100644
index 0000000..8d27c2c
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-port.h
@@ -0,0 +1,2536 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Low-level types and utilities for porting Google Test to various
+// platforms.  All macros ending with _ and symbols defined in an
+// internal namespace are subject to change without notice.  Code
+// outside Google Test MUST NOT USE THEM DIRECTLY.  Macros that don't
+// end with _ are part of Google Test's public API and can be used by
+// code outside Google Test.
+//
+// This file is fundamental to Google Test.  All other Google Test source
+// files are expected to #include this.  Therefore, it cannot #include
+// any other Google Test header.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// Environment-describing macros
+// -----------------------------
+//
+// Google Test can be used in many different environments.  Macros in
+// this section tell Google Test what kind of environment it is being
+// used in, such that Google Test can provide environment-specific
+// features and implementations.
+//
+// Google Test tries to automatically detect the properties of its
+// environment, so users usually don't need to worry about these
+// macros.  However, the automatic detection is not perfect.
+// Sometimes it's necessary for a user to define some of the following
+// macros in the build script to override Google Test's decisions.
+//
+// If the user doesn't define a macro in the list, Google Test will
+// provide a default definition.  After this header is #included, all
+// macros in this list will be defined to either 1 or 0.
+//
+// Notes to maintainers:
+//   - Each macro here is a user-tweakable knob; do not grow the list
+//     lightly.
+//   - Use #if to key off these macros.  Don't use #ifdef or "#if
+//     defined(...)", which will not work as these macros are ALWAYS
+//     defined.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_FILE_SYSTEM    - Define it to 1/0 to indicate whether or not a
+//                              file system is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+//   GTEST_DEFAULT_DEATH_TEST_STYLE
+//                            - The default value of --gtest_death_test_style.
+//                              The legacy default has been "fast" in the open
+//                              source version since 2008. The recommended value
+//                              is "threadsafe", and can be set in
+//                              custom/gtest-port.h.
+
+// Platform-indicating macros
+// --------------------------
+//
+// Macros indicating the platform on which Google Test is being used
+// (a macro is defined to 1 if compiled on the given platform;
+// otherwise UNDEFINED -- it's never defined to 0.).  Google Test
+// defines these macros automatically.  Code outside Google Test MUST
+// NOT define them.
+//
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_DRAGONFLY - DragonFlyBSD
+//   GTEST_OS_FREEBSD  - FreeBSD
+//   GTEST_OS_FUCHSIA  - Fuchsia
+//   GTEST_OS_GNU_HURD - GNU/Hurd
+//   GTEST_OS_GNU_KFREEBSD - GNU/kFreeBSD
+//   GTEST_OS_HAIKU    - Haiku
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//     GTEST_OS_IOS    - iOS
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_NETBSD   - NetBSD
+//   GTEST_OS_OPENBSD  - OpenBSD
+//   GTEST_OS_OS2      - OS/2
+//   GTEST_OS_QNX      - QNX
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//     GTEST_OS_WINDOWS_PHONE    - Windows Phone
+//     GTEST_OS_WINDOWS_RT       - Windows Store App/WinRT
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Mac OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// It is possible that none of the GTEST_OS_* macros are defined.
+
+// Feature-indicating macros
+// -------------------------
+//
+// Macros indicating which Google Test features are available (a macro
+// is defined to 1 if the corresponding feature is supported;
+// otherwise UNDEFINED -- it's never defined to 0.).  Google Test
+// defines these macros automatically.  Code outside Google Test MUST
+// NOT define them.
+//
+// These macros are public so that portable tests can be written.
+// Such tests typically surround code using a feature with an #ifdef
+// which controls that code.  For example:
+//
+// #ifdef GTEST_HAS_DEATH_TEST
+//   EXPECT_DEATH(DoSomethingDeadly());
+// #endif
+//
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_IS_THREADSAFE    - Google Test is thread-safe.
+//   GTEST_USES_RE2         - the RE2 regular expression library is used
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above RE\b(s) are mutually exclusive.
+//   GTEST_HAS_ABSL         - Google Test is compiled with Abseil.
+
+// Misc public macros
+// ------------------
+//
+//   GTEST_FLAG(flag_name)  - references the variable corresponding to
+//                            the given Google Test flag.
+
+// Internal utilities
+// ------------------
+//
+// The following macros and utilities are for Google Test's INTERNAL
+// use only.  Code outside Google Test MUST NOT USE THEM DIRECTLY.
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//   GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
+//                                        suppressed (constant conditional).
+//   GTEST_INTENTIONAL_CONST_COND_POP_  - finish code section where MSVC C4127
+//                                        is suppressed.
+//   GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter<std::any> or
+//                            UniversalPrinter<absl::any> specializations.
+//                            Always defined to 0 or 1.
+//   GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter<std::optional>
+//   or
+//                                 UniversalPrinter<absl::optional>
+//                                 specializations. Always defined to 0 or 1.
+//   GTEST_INTERNAL_HAS_STD_SPAN - for enabling UniversalPrinter<std::span>
+//                                 specializations. Always defined to 0 or 1
+//   GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
+//                                    Matcher<absl::string_view>
+//                                    specializations. Always defined to 0 or 1.
+//   GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter<std::variant> or
+//                                UniversalPrinter<absl::variant>
+//                                specializations. Always defined to 0 or 1.
+//   GTEST_USE_OWN_FLAGFILE_FLAG_ - Always defined to 0 or 1.
+//   GTEST_HAS_CXXABI_H_ - Always defined to 0 or 1.
+//   GTEST_CAN_STREAM_RESULTS_ - Always defined to 0 or 1.
+//   GTEST_HAS_ALT_PATH_SEP_ - Always defined to 0 or 1.
+//   GTEST_WIDE_STRING_USES_UTF16_ - Always defined to 0 or 1.
+//   GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Always defined to 0 or 1.
+//   GTEST_HAS_NOTIFICATION_- Always defined to 0 or 1.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                            - synchronization primitives.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using
+//                     1) the RE2 syntax on all platforms when built with RE2
+//                        and Abseil as dependencies
+//                     2) the POSIX Extended Regular Expression syntax on
+//                        UNIX-like platforms,
+//                     3) A reduced regular exception syntax on other platforms,
+//                        including Windows.
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   TimeInMillis   - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GetInjectableArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an int32_t environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+//
+// Deprecation warnings:
+//   GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
+//                                        deprecated; calling a marked function
+//                                        should generate a compiler warning
+
+// The definition of GTEST_INTERNAL_CPLUSPLUS_LANG comes first because it can
+// potentially be used as an #include guard.
+#if defined(_MSVC_LANG)
+#define GTEST_INTERNAL_CPLUSPLUS_LANG _MSVC_LANG
+#elif defined(__cplusplus)
+#define GTEST_INTERNAL_CPLUSPLUS_LANG __cplusplus
+#endif
+
+#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
+    GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
+#error C++ versions less than C++14 are not supported.
+#endif
+
+// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
+#ifdef __has_include
+#define GTEST_INTERNAL_HAS_INCLUDE __has_include
+#else
+#define GTEST_INTERNAL_HAS_INCLUDE(...) 0
+#endif
+
+// Detect C++ feature test macros as gracefully as possible.
+// MSVC >= 19.15, Clang >= 3.4.1, and GCC >= 4.1.2 support feature test macros.
+#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L && \
+    (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<version>))
+#include <version>  // C++20 and later
+#elif (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<ciso646>))
+#include <ciso646>  // Pre-C++20
+#endif
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cerrno>
+// #include <condition_variable>  // Guarded by GTEST_IS_THREADSAFE below
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <locale>
+#include <memory>
+#include <ostream>
+#include <string>
+// #include <mutex>  // Guarded by GTEST_IS_THREADSAFE below
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+#ifndef _WIN32_WCE
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif  // !_WIN32_WCE
+
+#if defined __APPLE__
+#include <AvailabilityMacros.h>
+#include <TargetConditionals.h>
+#endif
+
+#include "gtest/internal/custom/gtest-port.h"
+#include "gtest/internal/gtest-port-arch.h"
+
+#ifndef GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+#define GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ 0
+#endif
+
+#ifndef GTEST_HAS_NOTIFICATION_
+#define GTEST_HAS_NOTIFICATION_ 0
+#endif
+
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+#define GTEST_INTERNAL_HAS_ABSL_FLAGS  // Used only in this file.
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
+#endif
+
+#if !defined(GTEST_DEV_EMAIL_)
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "https://github.com/google/googletest/"
+#endif  // !defined(GTEST_DEV_EMAIL_)
+
+#if !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
+#define GTEST_INIT_GOOGLE_TEST_NAME_ "testing::InitGoogleTest"
+#endif  // !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+#define GTEST_GCC_VER_ \
+  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Macros for disabling Microsoft Visual C++ warnings.
+//
+//   GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385)
+//   /* code that triggers warnings C4800 and C4385 */
+//   GTEST_DISABLE_MSC_WARNINGS_POP_()
+#if defined(_MSC_VER)
+#define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \
+  __pragma(warning(push)) __pragma(warning(disable : warnings))
+#define GTEST_DISABLE_MSC_WARNINGS_POP_() __pragma(warning(pop))
+#else
+// Not all compilers are MSVC
+#define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings)
+#define GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+// Clang on Windows does not understand MSVC's pragma warning.
+// We need clang-specific way to disable function deprecation warning.
+#ifdef __clang__
+#define GTEST_DISABLE_MSC_DEPRECATED_PUSH_()                            \
+  _Pragma("clang diagnostic push")                                      \
+      _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
+          _Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"")
+#define GTEST_DISABLE_MSC_DEPRECATED_POP_() _Pragma("clang diagnostic pop")
+#else
+#define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
+#define GTEST_DISABLE_MSC_DEPRECATED_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#ifdef GTEST_OS_WINDOWS
+#ifndef GTEST_OS_WINDOWS_MOBILE
+#include <direct.h>
+#include <io.h>
+#endif
+// In order to avoid having to include <windows.h>, use forward declaration
+#if defined(GTEST_OS_WINDOWS_MINGW) && !defined(__MINGW64_VERSION_MAJOR)
+// MinGW defined _CRITICAL_SECTION and _RTL_CRITICAL_SECTION as two
+// separate (equivalent) structs, instead of using typedef
+typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION;
+#else
+// Assume CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
+// This assumption is verified by
+// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION.
+typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
+#endif
+#elif defined(GTEST_OS_XTENSA)
+#include <unistd.h>
+// Xtensa toolchains define strcasecmp in the string.h header instead of
+// strings.h. string.h is already included.
+#else
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+#include <strings.h>
+#include <unistd.h>
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef GTEST_OS_LINUX_ANDROID
+// Used to define __ANDROID_API__ matching the target NDK API level.
+#include <android/api-level.h>  // NOLINT
+#endif
+
+// Defines this to true if and only if Google Test can use POSIX regular
+// expressions.
+#ifndef GTEST_HAS_POSIX_RE
+#ifdef GTEST_OS_LINUX_ANDROID
+// On Android, <regex.h> is only available starting with Gingerbread.
+#define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
+#else
+#if !(defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_XTENSA) || \
+      defined(GTEST_OS_QURT))
+#define GTEST_HAS_POSIX_RE 1
+#else
+#define GTEST_HAS_POSIX_RE 0
+#endif
+#endif  // GTEST_OS_LINUX_ANDROID
+#endif
+
+// Select the regular expression implementation.
+#ifdef GTEST_HAS_ABSL
+// When using Abseil, RE2 is required.
+#include "absl/strings/string_view.h"
+#include "re2/re2.h"
+#define GTEST_USES_RE2 1
+#elif GTEST_HAS_POSIX_RE
+#include <regex.h>  // NOLINT
+#define GTEST_USES_POSIX_RE 1
+#else
+// Use our own simple regex implementation.
+#define GTEST_USES_SIMPLE_RE 1
+#endif
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+#if defined(_MSC_VER) && defined(_CPPUNWIND)
+// MSVC defines _CPPUNWIND to 1 if and only if exceptions are enabled.
+#define GTEST_HAS_EXCEPTIONS 1
+#elif defined(__BORLANDC__)
+// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#ifndef _HAS_EXCEPTIONS
+#define _HAS_EXCEPTIONS 1
+#endif  // _HAS_EXCEPTIONS
+#define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+#elif defined(__clang__)
+// clang defines __EXCEPTIONS if and only if exceptions are enabled before clang
+// 220714, but if and only if cleanups are enabled after that. In Obj-C++ files,
+// there can be cleanups for ObjC exceptions which also need cleanups, even if
+// C++ exceptions are disabled. clang has __has_feature(cxx_exceptions) which
+// checks for C++ exceptions starting at clang r206352, but which checked for
+// cleanups prior to that. To reliably check for C++ exception availability with
+// clang, check for
+// __EXCEPTIONS && __has_feature(cxx_exceptions).
+#if defined(__EXCEPTIONS) && __EXCEPTIONS && __has_feature(cxx_exceptions)
+#define GTEST_HAS_EXCEPTIONS 1
+#else
+#define GTEST_HAS_EXCEPTIONS 0
+#endif
+#elif defined(__GNUC__) && defined(__EXCEPTIONS) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 if and only if exceptions are enabled.
+#define GTEST_HAS_EXCEPTIONS 1
+#elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#define GTEST_HAS_EXCEPTIONS 1
+#elif defined(__IBMCPP__) && defined(__EXCEPTIONS) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 if and only if exceptions are enabled.
+#define GTEST_HAS_EXCEPTIONS 1
+#elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#define GTEST_HAS_EXCEPTIONS 1
+#else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#define GTEST_HAS_EXCEPTIONS 0
+#endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+#if (!(defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_CYGWIN) || \
+       defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) ||        \
+       defined(GTEST_OS_ESP32) || defined(GTEST_OS_ESP8266) ||        \
+       defined(GTEST_OS_XTENSA) || defined(GTEST_OS_QURT) ||          \
+       defined(GTEST_OS_NXP_QN9090) || defined(GTEST_OS_NRF52)))
+#define GTEST_HAS_STD_WSTRING 1
+#else
+#define GTEST_HAS_STD_WSTRING 0
+#endif
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_FILE_SYSTEM
+// Most platforms support a file system.
+#define GTEST_HAS_FILE_SYSTEM 1
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+#ifdef _MSC_VER
+
+#ifdef _CPPRTTI  // MSVC defines this macro if and only if RTTI is enabled.
+#define GTEST_HAS_RTTI 1
+#else
+#define GTEST_HAS_RTTI 0
+#endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI if and only if RTTI is
+// enabled.
+#elif defined(__GNUC__)
+
+#ifdef __GXX_RTTI
+// When building against STLport with the Android NDK and with
+// -frtti -fno-exceptions, the build fails at link time with undefined
+// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
+// so disable RTTI when detected.
+#if defined(GTEST_OS_LINUX_ANDROID) && defined(_STLPORT_MAJOR) && \
+    !defined(__EXCEPTIONS)
+#define GTEST_HAS_RTTI 0
+#else
+#define GTEST_HAS_RTTI 1
+#endif  // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
+#else
+#define GTEST_HAS_RTTI 0
+#endif  // __GXX_RTTI
+
+// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
+// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
+// first version with C++ support.
+#elif defined(__clang__)
+
+#define GTEST_HAS_RTTI __has_feature(cxx_rtti)
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+#elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#ifdef __RTTI_ALL__
+#define GTEST_HAS_RTTI 1
+#else
+#define GTEST_HAS_RTTI 0
+#endif
+
+#else
+
+// For all other compilers, we assume RTTI is enabled.
+#define GTEST_HAS_RTTI 1
+
+#endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+#include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we make reasonable assumptions about
+// which platforms have pthreads support.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+#if (defined(GTEST_OS_LINUX) || defined(GTEST_OS_MAC) ||              \
+     defined(GTEST_OS_HPUX) || defined(GTEST_OS_QNX) ||               \
+     defined(GTEST_OS_FREEBSD) || defined(GTEST_OS_NACL) ||           \
+     defined(GTEST_OS_NETBSD) || defined(GTEST_OS_FUCHSIA) ||         \
+     defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \
+     defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_HAIKU) ||          \
+     defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_SOLARIS) ||       \
+     defined(GTEST_OS_AIX) || defined(GTEST_OS_ZOS))
+#define GTEST_HAS_PTHREAD 1
+#else
+#define GTEST_HAS_PTHREAD 0
+#endif
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+#include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+#include <time.h>  // NOLINT
+#endif
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see https://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+#if defined(GTEST_OS_LINUX) && !defined(__ia64__)
+#if defined(GTEST_OS_LINUX_ANDROID)
+// On Android, clone() became available at different API levels for each 32-bit
+// architecture.
+#if defined(__LP64__) || (defined(__arm__) && __ANDROID_API__ >= 9) || \
+    (defined(__mips__) && __ANDROID_API__ >= 12) ||                    \
+    (defined(__i386__) && __ANDROID_API__ >= 17)
+#define GTEST_HAS_CLONE 1
+#else
+#define GTEST_HAS_CLONE 0
+#endif
+#else
+#define GTEST_HAS_CLONE 1
+#endif
+#else
+#define GTEST_HAS_CLONE 0
+#endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile / embedded ones. Also, if the port doesn't have
+// a file system, stream redirection is not supported.
+#if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_PHONE) || \
+    defined(GTEST_OS_WINDOWS_RT) || defined(GTEST_OS_WINDOWS_GAMES) ||     \
+    defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) ||               \
+    defined(GTEST_OS_QURT) || !GTEST_HAS_FILE_SYSTEM
+#define GTEST_HAS_STREAM_REDIRECTION 0
+#else
+#define GTEST_HAS_STREAM_REDIRECTION 1
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (defined(GTEST_OS_LINUX) || defined(GTEST_OS_CYGWIN) ||           \
+     defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_ZOS) ||            \
+     (defined(GTEST_OS_MAC) && !defined(GTEST_OS_IOS)) ||             \
+     (defined(GTEST_OS_WINDOWS_DESKTOP) && _MSC_VER) ||               \
+     defined(GTEST_OS_WINDOWS_MINGW) || defined(GTEST_OS_AIX) ||      \
+     defined(GTEST_OS_HPUX) || defined(GTEST_OS_OPENBSD) ||           \
+     defined(GTEST_OS_QNX) || defined(GTEST_OS_FREEBSD) ||            \
+     defined(GTEST_OS_NETBSD) || defined(GTEST_OS_FUCHSIA) ||         \
+     defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \
+     defined(GTEST_OS_HAIKU) || defined(GTEST_OS_GNU_HURD))
+// Death tests require a file system to work properly.
+#if GTEST_HAS_FILE_SYSTEM
+#define GTEST_HAS_DEATH_TEST 1
+#endif  // GTEST_HAS_FILE_SYSTEM
+#endif
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+#define GTEST_HAS_TYPED_TEST 1
+#define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_CYGWIN) || \
+    defined(GTEST_OS_AIX) || defined(GTEST_OS_OS2)
+#define GTEST_WIDE_STRING_USES_UTF16_ 1
+#else
+#define GTEST_WIDE_STRING_USES_UTF16_ 0
+#endif
+
+// Determines whether test results can be streamed to a socket.
+#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_GNU_KFREEBSD) || \
+    defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) ||  \
+    defined(GTEST_OS_NETBSD) || defined(GTEST_OS_OPENBSD) ||     \
+    defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_MAC)
+#define GTEST_CAN_STREAM_RESULTS_ 1
+#else
+#define GTEST_CAN_STREAM_RESULTS_ 0
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+#define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  switch (0)                          \
+  case 0:                             \
+  default:  // NOLINT
+#endif
+
+// GTEST_HAVE_ATTRIBUTE_
+//
+// A function-like feature checking macro that is a wrapper around
+// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
+// nonzero constant integer if the attribute is supported or 0 if not.
+//
+// It evaluates to zero if `__has_attribute` is not defined by the compiler.
+//
+// GCC: https://gcc.gnu.org/gcc-5/changes.html
+// Clang: https://clang.llvm.org/docs/LanguageExtensions.html
+#ifdef __has_attribute
+#define GTEST_HAVE_ATTRIBUTE_(x) __has_attribute(x)
+#else
+#define GTEST_HAVE_ATTRIBUTE_(x) 0
+#endif
+
+// GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE
+//
+// A function-like feature checking macro that accepts C++11 style attributes.
+// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// find `__has_cpp_attribute`, will evaluate to 0.
+#if defined(__has_cpp_attribute)
+// NOTE: requiring __cplusplus above should not be necessary, but
+// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
+#define GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+#define GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(x) 0
+#endif
+
+// GTEST_HAVE_FEATURE_
+//
+// A function-like feature checking macro that is a wrapper around
+// `__has_feature`.
+#ifdef __has_feature
+#define GTEST_HAVE_FEATURE_(x) __has_feature(x)
+#else
+#define GTEST_HAVE_FEATURE_(x) 0
+#endif
+
+// Use this annotation after a variable or parameter declaration to tell the
+// compiler the variable/parameter may be used.
+// Example:
+//
+//   GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED int foo = bar();
+//
+// This can be removed once we only support only C++17 or newer and
+// [[maybe_unused]] is available on all supported platforms.
+#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(maybe_unused)
+#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
+#elif GTEST_HAVE_ATTRIBUTE_(unused)
+// This is inferior to [[maybe_unused]] as it can produce a
+// -Wused-but-marked-unused warning on optionally used symbols, but it is all we
+// have.
+#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED __attribute__((__unused__))
+#else
+#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED
+#endif
+
+// Use this annotation before a function that takes a printf format string.
+#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
+// MinGW has two different printf implementations. Ensure the format macro
+// matches the selected implementation. See
+// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
+#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
+  __attribute__((format(__MINGW_PRINTF_FORMAT, string_index, first_to_check)))
+#elif GTEST_HAVE_ATTRIBUTE_(format)
+#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
+  __attribute__((format(printf, string_index, first_to_check)))
+#else
+#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
+#endif
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if GTEST_HAVE_ATTRIBUTE_(warn_unused_result)
+#define GTEST_MUST_USE_RESULT_ __attribute__((warn_unused_result))
+#else
+#define GTEST_MUST_USE_RESULT_
+#endif
+
+// MS C++ compiler emits warning when a conditional expression is compile time
+// constant. In some contexts this warning is false positive and needs to be
+// suppressed. Use the following two macros in such cases:
+//
+// GTEST_INTENTIONAL_CONST_COND_PUSH_()
+// while (true) {
+// GTEST_INTENTIONAL_CONST_COND_POP_()
+// }
+#define GTEST_INTENTIONAL_CONST_COND_PUSH_() \
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127)
+#define GTEST_INTENTIONAL_CONST_COND_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#define GTEST_HAS_SEH 1
+#else
+// Assume no SEH.
+#define GTEST_HAS_SEH 0
+#endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifndef GTEST_IS_THREADSAFE
+
+#if (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ ||                              \
+     (defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+      !defined(GTEST_OS_WINDOWS_RT)) ||                                \
+     GTEST_HAS_PTHREAD)
+#define GTEST_IS_THREADSAFE 1
+#endif
+
+#endif  // GTEST_IS_THREADSAFE
+
+#ifdef GTEST_IS_THREADSAFE
+// Some platforms don't support including these threading related headers.
+#include <condition_variable>  // NOLINT
+#include <mutex>               // NOLINT
+#endif                         // GTEST_IS_THREADSAFE
+
+// GTEST_API_ qualifies all symbols that must be exported. The definitions below
+// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in
+// gtest/internal/custom/gtest-port.h
+#ifndef GTEST_API_
+
+#ifdef _MSC_VER
+#if defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY
+#define GTEST_API_ __declspec(dllimport)
+#elif defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY
+#define GTEST_API_ __declspec(dllexport)
+#endif
+#elif GTEST_HAVE_ATTRIBUTE_(visibility)
+#define GTEST_API_ __attribute__((visibility("default")))
+#endif  // _MSC_VER
+
+#endif  // GTEST_API_
+
+#ifndef GTEST_API_
+#define GTEST_API_
+#endif  // GTEST_API_
+
+#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE
+#define GTEST_DEFAULT_DEATH_TEST_STYLE "fast"
+#endif  // GTEST_DEFAULT_DEATH_TEST_STYLE
+
+#if GTEST_HAVE_ATTRIBUTE_(noinline)
+// Ask the compiler to never inline a given function.
+#define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+#define GTEST_NO_INLINE_
+#endif
+
+#if GTEST_HAVE_ATTRIBUTE_(disable_tail_calls)
+// Ask the compiler not to perform tail call optimization inside
+// the marked function.
+#define GTEST_NO_TAIL_CALL_ __attribute__((disable_tail_calls))
+#elif defined(__GNUC__) && !defined(__NVCOMPILER)
+#define GTEST_NO_TAIL_CALL_ \
+  __attribute__((optimize("no-optimize-sibling-calls")))
+#else
+#define GTEST_NO_TAIL_CALL_
+#endif
+
+// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
+#if !defined(GTEST_HAS_CXXABI_H_)
+#if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
+#define GTEST_HAS_CXXABI_H_ 1
+#else
+#define GTEST_HAS_CXXABI_H_ 0
+#endif
+#endif
+
+// A function level attribute to disable checking for use of uninitialized
+// memory when built with MemorySanitizer.
+#if GTEST_HAVE_ATTRIBUTE_(no_sanitize_memory)
+#define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ __attribute__((no_sanitize_memory))
+#else
+#define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+#endif
+
+// A function level attribute to disable AddressSanitizer instrumentation.
+#if GTEST_HAVE_ATTRIBUTE_(no_sanitize_address)
+#define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \
+  __attribute__((no_sanitize_address))
+#else
+#define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+#endif
+
+// A function level attribute to disable HWAddressSanitizer instrumentation.
+#if GTEST_HAVE_FEATURE_(hwaddress_sanitizer) && \
+    GTEST_HAVE_ATTRIBUTE_(no_sanitize)
+#define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ \
+  __attribute__((no_sanitize("hwaddress")))
+#else
+#define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+#endif
+
+// A function level attribute to disable ThreadSanitizer instrumentation.
+#if GTEST_HAVE_ATTRIBUTE_(no_sanitize_thread)
+#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ __attribute((no_sanitize_thread))
+#else
+#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+#endif
+
+namespace testing {
+
+class Message;
+
+// Legacy imports for backwards compatibility.
+// New code should use std:: names directly.
+using std::get;
+using std::make_tuple;
+using std::tuple;
+using std::tuple_element;
+using std::tuple_size;
+
+namespace internal {
+
+// A secret type that Google Test users don't know about.  It has no
+// accessible constructors on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret {
+  Secret(const Secret&) = delete;
+};
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines RE.
+
+#ifdef GTEST_USES_RE2
+
+// This is almost `using RE = ::RE2`, except it is copy-constructible, and it
+// needs to disambiguate the `std::string`, `absl::string_view`, and `const
+// char*` constructors.
+class GTEST_API_ RE {
+ public:
+  RE(absl::string_view regex) : regex_(regex) {}                  // NOLINT
+  RE(const char* regex) : RE(absl::string_view(regex)) {}         // NOLINT
+  RE(const std::string& regex) : RE(absl::string_view(regex)) {}  // NOLINT
+  RE(const RE& other) : RE(other.pattern()) {}
+
+  const std::string& pattern() const { return regex_.pattern(); }
+
+  static bool FullMatch(absl::string_view str, const RE& re) {
+    return RE2::FullMatch(str, re.regex_);
+  }
+  static bool PartialMatch(absl::string_view str, const RE& re) {
+    return RE2::PartialMatch(str, re.regex_);
+  }
+
+ private:
+  RE2 regex_;
+};
+
+#elif defined(GTEST_USES_POSIX_RE) || defined(GTEST_USES_SIMPLE_RE)
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_.c_str(); }
+
+  // FullMatch(str, re) returns true if and only if regular expression re
+  // matches the entire str.
+  // PartialMatch(str, re) returns true if and only if regular expression re
+  // matches a substring of str (including str itself).
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+  std::string pattern_;
+  bool is_valid_;
+
+#ifdef GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  std::string full_pattern_;  // For FullMatch();
+
+#endif
+};
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4251
+#endif  // ::testing::internal::RE implementation
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity { GTEST_INFO, GTEST_WARNING, GTEST_ERROR, GTEST_FATAL };
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTestLog(const GTestLog&) = delete;
+  GTestLog& operator=(const GTestLog&) = delete;
+};
+
+#if !defined(GTEST_LOG_)
+
+#define GTEST_LOG_(severity)                                           \
+  ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                __FILE__, __LINE__)                    \
+      .GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(nullptr); }
+
+#endif  // !defined(GTEST_LOG_)
+
+#if !defined(GTEST_CHECK_)
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsis:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition)               \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_               \
+  if (::testing::internal::IsTrue(condition)) \
+    ;                                         \
+  else                                        \
+    GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+#endif  // !defined(GTEST_CHECK_)
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call))    \
+  GTEST_LOG_(FATAL) << #posix_call << "failed with error " << gtest_error
+
+// Transforms "T" into "const T&" according to standard reference collapsing
+// rules (this is only needed as a backport for C++98 compilers that do not
+// support reference collapsing). Specifically, it transforms:
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> char&
+//   const char&  ==> const char&
+//
+// Note that the non-const reference will not have "const" added. This is
+// standard, and necessary so that "T" can always bind to "const T&".
+template <typename T>
+struct ConstRef {
+  typedef const T& type;
+};
+template <typename T>
+struct ConstRef<T&> {
+  typedef T& type;
+};
+
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+  typename ::testing::internal::ConstRef<T>::type
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertible to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template <typename To>
+inline To ImplicitCast_(To x) {
+  return x;
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+  static_assert(std::is_base_of<Base, Derived>::value,
+                "target type not derived from source type");
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(base == nullptr || dynamic_cast<Derived*>(base) != nullptr);
+#endif
+  return static_cast<Derived*>(base);
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ std::string GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ std::string GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+// Returns the size (in bytes) of a file.
+GTEST_API_ size_t GetFileSize(FILE* file);
+
+// Reads the entire content of a file as a string.
+GTEST_API_ std::string ReadEntireFile(FILE* file);
+
+// All command line arguments.
+GTEST_API_ std::vector<std::string> GetArgvs();
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+std::vector<std::string> GetInjectableArgvs();
+// Deprecated: pass the args vector by value instead.
+void SetInjectableArgvs(const std::vector<std::string>* new_argvs);
+void SetInjectableArgvs(const std::vector<std::string>& new_argvs);
+void ClearInjectableArgvs();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+#ifdef GTEST_IS_THREADSAFE
+
+#ifdef GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+// Used in death tests and in threading support.
+class GTEST_API_ AutoHandle {
+ public:
+  // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
+  // avoid including <windows.h> in this header file. Including <windows.h> is
+  // undesirable because it defines a lot of symbols and macros that tend to
+  // conflict with client code. This assumption is verified by
+  // WindowsTypesTest.HANDLEIsVoidStar.
+  typedef void* Handle;
+  AutoHandle();
+  explicit AutoHandle(Handle handle);
+
+  ~AutoHandle();
+
+  Handle Get() const;
+  void Reset();
+  void Reset(Handle handle);
+
+ private:
+  // Returns true if and only if the handle is a valid handle object that can be
+  // closed.
+  bool IsCloseable() const;
+
+  Handle handle_;
+
+  AutoHandle(const AutoHandle&) = delete;
+  AutoHandle& operator=(const AutoHandle&) = delete;
+};
+#endif
+
+#if GTEST_HAS_NOTIFICATION_
+// Notification has already been imported into the namespace.
+// Nothing to do here.
+
+#else
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+// TODO(b/203539622): Replace unconditionally with absl::Notification.
+class GTEST_API_ Notification {
+ public:
+  Notification() : notified_(false) {}
+  Notification(const Notification&) = delete;
+  Notification& operator=(const Notification&) = delete;
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() {
+    std::lock_guard<std::mutex> lock(mu_);
+    notified_ = true;
+    cv_.notify_all();
+  }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    std::unique_lock<std::mutex> lock(mu_);
+    cv_.wait(lock, [this]() { return notified_; });
+  }
+
+ private:
+  std::mutex mu_;
+  std::condition_variable cv_;
+  bool notified_;
+};
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4251
+#endif  // GTEST_HAS_NOTIFICATION_
+
+// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD
+// defined, but we don't want to use MinGW's pthreads implementation, which
+// has conformance problems with some versions of the POSIX standard.
+#if GTEST_HAS_PTHREAD && !defined(GTEST_OS_WINDOWS_MINGW)
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() = default;
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return nullptr;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void UserThreadFunc(T);
+
+  ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, nullptr, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() override { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, nullptr));
+      finished_ = true;
+    }
+  }
+
+  void Run() override {
+    if (thread_can_start_ != nullptr) thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  UserThreadFunc* const func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true if and only if we know that the thread function has
+                   // finished.
+  pthread_t thread_;  // The native thread object.
+
+  ThreadWithParam(const ThreadWithParam&) = delete;
+  ThreadWithParam& operator=(const ThreadWithParam&) = delete;
+};
+#endif  // !GTEST_OS_WINDOWS && GTEST_HAS_PTHREAD ||
+        // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+
+#if GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+// Mutex and ThreadLocal have already been imported into the namespace.
+// Nothing to do here.
+
+#elif defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT)
+
+// Mutex implements mutex on Windows platforms.  It is used in conjunction
+// with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the
+//                            // end of the current scope.
+//
+// A static Mutex *must* be defined or declared using one of the following
+// macros:
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// (A non-static Mutex is defined/declared in the usual way).
+class GTEST_API_ Mutex {
+ public:
+  enum MutexType { kStatic = 0, kDynamic = 1 };
+  // We rely on kStaticMutex being 0 as it is to what the linker initializes
+  // type_ in static mutexes.  critical_section_ will be initialized lazily
+  // in ThreadSafeLazyInit().
+  enum StaticConstructorSelector { kStaticMutex = 0 };
+
+  // This constructor intentionally does nothing.  It relies on type_ being
+  // statically initialized to 0 (effectively setting it to kStatic) and on
+  // ThreadSafeLazyInit() to lazily initialize the rest of the members.
+  explicit Mutex(StaticConstructorSelector /*dummy*/) {}
+
+  Mutex();
+  ~Mutex();
+
+  void Lock();
+
+  void Unlock();
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld();
+
+ private:
+  // Initializes owner_thread_id_ and critical_section_ in static mutexes.
+  void ThreadSafeLazyInit();
+
+  // Per https://blogs.msdn.microsoft.com/oldnewthing/20040223-00/?p=40503,
+  // we assume that 0 is an invalid value for thread IDs.
+  unsigned int owner_thread_id_;
+
+  // For static mutexes, we rely on these members being initialized to zeros
+  // by the linker.
+  MutexType type_;
+  long critical_section_init_phase_;  // NOLINT
+  GTEST_CRITICAL_SECTION* critical_section_;
+
+  Mutex(const Mutex&) = delete;
+  Mutex& operator=(const Mutex&) = delete;
+};
+
+#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+  ::testing::internal::Mutex mutex(::testing::internal::Mutex::kStaticMutex)
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  Mutex* const mutex_;
+
+  GTestMutexLock(const GTestMutexLock&) = delete;
+  GTestMutexLock& operator=(const GTestMutexLock&) = delete;
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Base class for ValueHolder<T>.  Allows a caller to hold and delete a value
+// without knowing its type.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Provides a way for a thread to send notifications to a ThreadLocal
+// regardless of its parameter type.
+class ThreadLocalBase {
+ public:
+  // Creates a new ValueHolder<T> object holding a default value passed to
+  // this ThreadLocal<T>'s constructor and returns it.  It is the caller's
+  // responsibility not to call this when the ThreadLocal<T> instance already
+  // has a value on the current thread.
+  virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0;
+
+ protected:
+  ThreadLocalBase() {}
+  virtual ~ThreadLocalBase() {}
+
+ private:
+  ThreadLocalBase(const ThreadLocalBase&) = delete;
+  ThreadLocalBase& operator=(const ThreadLocalBase&) = delete;
+};
+
+// Maps a thread to a set of ThreadLocals that have values instantiated on that
+// thread and notifies them when the thread exits.  A ThreadLocal instance is
+// expected to persist until all threads it has values on have terminated.
+class GTEST_API_ ThreadLocalRegistry {
+ public:
+  // Registers thread_local_instance as having value on the current thread.
+  // Returns a value that can be used to identify the thread from other threads.
+  static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance);
+
+  // Invoked when a ThreadLocal instance is destroyed.
+  static void OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance);
+};
+
+class GTEST_API_ ThreadWithParamBase {
+ public:
+  void Join();
+
+ protected:
+  class Runnable {
+   public:
+    virtual ~Runnable() {}
+    virtual void Run() = 0;
+  };
+
+  ThreadWithParamBase(Runnable* runnable, Notification* thread_can_start);
+  virtual ~ThreadWithParamBase();
+
+ private:
+  AutoHandle thread_;
+};
+
+// Helper class for testing Google Test's multi-threading constructs.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void UserThreadFunc(T);
+
+  ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
+      : ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) {}
+  virtual ~ThreadWithParam() {}
+
+ private:
+  class RunnableImpl : public Runnable {
+   public:
+    RunnableImpl(UserThreadFunc* func, T param) : func_(func), param_(param) {}
+    virtual ~RunnableImpl() {}
+    virtual void Run() { func_(param_); }
+
+   private:
+    UserThreadFunc* const func_;
+    const T param_;
+
+    RunnableImpl(const RunnableImpl&) = delete;
+    RunnableImpl& operator=(const RunnableImpl&) = delete;
+  };
+
+  ThreadWithParam(const ThreadWithParam&) = delete;
+  ThreadWithParam& operator=(const ThreadWithParam&) = delete;
+};
+
+// Implements thread-local storage on Windows systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// The users of a TheadLocal instance have to make sure that all but one
+// threads (including the main one) using that instance have exited before
+// destroying it. Otherwise, the per-thread objects managed for them by the
+// ThreadLocal instance are not guaranteed to be destroyed on all platforms.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal : public ThreadLocalBase {
+ public:
+  ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
+  explicit ThreadLocal(const T& value)
+      : default_factory_(new InstanceValueHolderFactory(value)) {}
+
+  ~ThreadLocal() override { ThreadLocalRegistry::OnThreadLocalDestroyed(this); }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of T.  Can be deleted via its base class without the caller
+  // knowing the type of T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    ValueHolder() : value_() {}
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    ValueHolder(const ValueHolder&) = delete;
+    ValueHolder& operator=(const ValueHolder&) = delete;
+  };
+
+  T* GetOrCreateValue() const {
+    return static_cast<ValueHolder*>(
+               ThreadLocalRegistry::GetValueOnCurrentThread(this))
+        ->pointer();
+  }
+
+  ThreadLocalValueHolderBase* NewValueForCurrentThread() const override {
+    return default_factory_->MakeNewHolder();
+  }
+
+  class ValueHolderFactory {
+   public:
+    ValueHolderFactory() {}
+    virtual ~ValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const = 0;
+
+   private:
+    ValueHolderFactory(const ValueHolderFactory&) = delete;
+    ValueHolderFactory& operator=(const ValueHolderFactory&) = delete;
+  };
+
+  class DefaultValueHolderFactory : public ValueHolderFactory {
+   public:
+    DefaultValueHolderFactory() {}
+    ValueHolder* MakeNewHolder() const override { return new ValueHolder(); }
+
+   private:
+    DefaultValueHolderFactory(const DefaultValueHolderFactory&) = delete;
+    DefaultValueHolderFactory& operator=(const DefaultValueHolderFactory&) =
+        delete;
+  };
+
+  class InstanceValueHolderFactory : public ValueHolderFactory {
+   public:
+    explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
+    ValueHolder* MakeNewHolder() const override {
+      return new ValueHolder(value_);
+    }
+
+   private:
+    const T value_;  // The value for each thread.
+
+    InstanceValueHolderFactory(const InstanceValueHolderFactory&) = delete;
+    InstanceValueHolderFactory& operator=(const InstanceValueHolderFactory&) =
+        delete;
+  };
+
+  std::unique_ptr<ValueHolderFactory> default_factory_;
+
+  ThreadLocal(const ThreadLocal&) = delete;
+  ThreadLocal& operator=(const ThreadLocal&) = delete;
+};
+
+#elif GTEST_HAS_PTHREAD
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+    has_owner_ = true;
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // Since the lock is being released the owner_ field should no longer be
+    // considered valid. We don't protect writing to has_owner_ here, as it's
+    // the caller's responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    has_owner_ = false;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  // has_owner_ indicates whether the owner_ field below contains a valid thread
+  // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
+  // accesses to the owner_ field should be protected by a check of this field.
+  // An alternative might be to memset() owner_ to all zeros, but there's no
+  // guarantee that a zero'd pthread_t is necessarily invalid or even different
+  // from pthread_self().
+  bool has_owner_;
+  pthread_t owner_;  // The thread holding the mutex.
+};
+
+// Forward-declares a static mutex.
+#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+// The initialization list here does not explicitly initialize each field,
+// instead relying on default initialization for the unspecified fields. In
+// particular, the owner_ field (a pthread_t) is not explicitly initialized.
+// This allows initialization to work whether pthread_t is a scalar or struct.
+// The flag -Wmissing-field-initializers must not be specified for this to work.
+#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+  ::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, 0}
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
+    has_owner_ = false;
+  }
+  ~Mutex() { GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); }
+
+ private:
+  Mutex(const Mutex&) = delete;
+  Mutex& operator=(const Mutex&) = delete;
+};
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex) : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTestMutexLock(const GTestMutexLock&) = delete;
+  GTestMutexLock& operator=(const GTestMutexLock&) = delete;
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class GTEST_API_ ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() = default;
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+template <typename T>
+class GTEST_API_ ThreadLocal {
+ public:
+  ThreadLocal()
+      : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
+  explicit ThreadLocal(const T& value)
+      : key_(CreateKey()),
+        default_factory_(new InstanceValueHolderFactory(value)) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    ValueHolder() : value_() {}
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    ValueHolder(const ValueHolder&) = delete;
+    ValueHolder& operator=(const ValueHolder&) = delete;
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != nullptr) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = default_factory_->MakeNewHolder();
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  class ValueHolderFactory {
+   public:
+    ValueHolderFactory() = default;
+    virtual ~ValueHolderFactory() = default;
+    virtual ValueHolder* MakeNewHolder() const = 0;
+
+   private:
+    ValueHolderFactory(const ValueHolderFactory&) = delete;
+    ValueHolderFactory& operator=(const ValueHolderFactory&) = delete;
+  };
+
+  class DefaultValueHolderFactory : public ValueHolderFactory {
+   public:
+    DefaultValueHolderFactory() = default;
+    ValueHolder* MakeNewHolder() const override { return new ValueHolder(); }
+
+   private:
+    DefaultValueHolderFactory(const DefaultValueHolderFactory&) = delete;
+    DefaultValueHolderFactory& operator=(const DefaultValueHolderFactory&) =
+        delete;
+  };
+
+  class InstanceValueHolderFactory : public ValueHolderFactory {
+   public:
+    explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
+    ValueHolder* MakeNewHolder() const override {
+      return new ValueHolder(value_);
+    }
+
+   private:
+    const T value_;  // The value for each thread.
+
+    InstanceValueHolderFactory(const InstanceValueHolderFactory&) = delete;
+    InstanceValueHolderFactory& operator=(const InstanceValueHolderFactory&) =
+        delete;
+  };
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  std::unique_ptr<ValueHolderFactory> default_factory_;
+
+  ThreadLocal(const ThreadLocal&) = delete;
+  ThreadLocal& operator=(const ThreadLocal&) = delete;
+};
+
+#endif  // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+
+#else  // GTEST_IS_THREADSAFE
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void Lock() {}
+  void Unlock() {}
+  void AssertHeld() const {}
+};
+
+#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class GTEST_API_ ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+
+ private:
+  T value_;
+};
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+#ifdef GTEST_OS_WINDOWS
+#define GTEST_PATH_SEP_ "\\"
+#define GTEST_HAS_ALT_PATH_SEP_ 1
+#else
+#define GTEST_PATH_SEP_ "/"
+#define GTEST_HAS_ALT_PATH_SEP_ 0
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+#ifdef __cpp_lib_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;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+inline std::string StripTrailingSpaces(std::string str) {
+  std::string::iterator it = str.end();
+  while (it != str.begin() && IsSpace(*--it)) it = str.erase(it);
+  return str;
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// File system porting.
+// Note: Not every I/O-related function is related to file systems, so don't
+// just disable all of them here. For example, fileno() and isatty(), etc. must
+// always be available in order to detect if a pipe points to a terminal.
+#ifdef GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+#else
+inline int FileNo(FILE* file) { return _fileno(file); }
+#if GTEST_HAS_FILE_SYSTEM
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return (_S_IFDIR & st.st_mode) != 0; }
+#endif
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#elif defined(GTEST_OS_ESP8266)
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+#if GTEST_HAS_FILE_SYSTEM
+inline int Stat(const char* path, StatStruct* buf) {
+  // stat function not implemented on ESP8266
+  return 0;
+}
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+#endif
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+#if GTEST_HAS_FILE_SYSTEM
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+#ifdef GTEST_OS_QURT
+// QuRT doesn't support any directory functions, including rmdir
+inline int RmDir(const char*) { return 0; }
+#else
+inline int RmDir(const char* dir) { return rmdir(dir); }
+#endif
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+#endif
+
+#endif  // GTEST_OS_WINDOWS
+
+// Other functions with a different name on Windows.
+
+#ifdef GTEST_OS_WINDOWS
+
+#ifdef __BORLANDC__
+inline int DoIsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+#else  // !__BORLANDC__
+#if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_ZOS) || \
+    defined(GTEST_OS_IOS) || defined(GTEST_OS_WINDOWS_PHONE) ||  \
+    defined(GTEST_OS_WINDOWS_RT) || defined(ESP_PLATFORM)
+inline int DoIsATTY(int /* fd */) { return 0; }
+#else
+inline int DoIsATTY(int fd) { return _isatty(fd); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+#endif  // __BORLANDC__
+
+#else
+
+inline int DoIsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+inline int IsATTY(int fd) {
+  // DoIsATTY might change errno (for example ENOTTY in case you redirect stdout
+  // to a file on Linux), which is unexpected, so save the previous value, and
+  // restore it after the call.
+  int savedErrno = errno;
+  int isAttyValue = DoIsATTY(fd);
+  errno = savedErrno;
+
+  return isAttyValue;
+}
+
+// Functions deprecated by MSVC 8.0.
+
+GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+#if GTEST_HAS_FILE_SYSTEM
+#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_GAMES) &&     \
+    !defined(GTEST_OS_ESP8266) && !defined(GTEST_OS_XTENSA) &&               \
+    !defined(GTEST_OS_QURT)
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
+  struct wchar_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t> {};
+  std::wstring_convert<wchar_codecvt> converter;
+  std::wstring wide_path = converter.from_bytes(path);
+  std::wstring wide_mode = converter.from_bytes(mode);
+  return _wfopen(wide_path.c_str(), wide_mode.c_str());
+#else   // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+  return fopen(path, mode);
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+}
+#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_QURT)
+inline FILE* FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_QURT
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_QURT)
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+#endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_QURT
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_QURT)
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_QURT
+
+inline const char* GetEnv(const char* name) {
+#if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_PHONE) || \
+    defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) ||               \
+    defined(GTEST_OS_QURT)
+  // We are on an embedded platform, which has no environment variables.
+  static_cast<void>(name);  // To prevent 'unused argument' warning.
+  return nullptr;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != nullptr && env[0] != '\0') ? env : nullptr;
+#else
+  return getenv(name);
+#endif
+}
+
+GTEST_DISABLE_MSC_DEPRECATED_POP_()
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+[[noreturn]] void Abort();
+#else
+[[noreturn]] inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// MSVC "deprecates" snprintf and issues warnings wherever it is used.  In
+// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
+// MSVC-based platforms.  We map the GTEST_SNPRINTF_ macro to the appropriate
+// function in order to achieve that.  We use macro definition here because
+// snprintf is a variadic function.
+#if defined(_MSC_VER) && !defined(GTEST_OS_WINDOWS_MOBILE)
+// MSVC 2005 and above support variadic macros.
+#define GTEST_SNPRINTF_(buffer, size, format, ...) \
+  _snprintf_s(buffer, size, size, format, __VA_ARGS__)
+#elif defined(_MSC_VER)
+// Windows CE does not define _snprintf_s
+#define GTEST_SNPRINTF_ _snprintf
+#else
+#define GTEST_SNPRINTF_ snprintf
+#endif
+
+// The biggest signed integer type the compiler supports.
+//
+// long long is guaranteed to be at least 64-bits in C++11.
+using BiggestInt = long long;  // NOLINT
+
+// The maximum number a BiggestInt can represent.
+constexpr BiggestInt kMaxBiggestInt = (std::numeric_limits<BiggestInt>::max)();
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  using UInt = void;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  using Int = std::int32_t;
+  using UInt = std::uint32_t;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+  using Int = std::int64_t;
+  using UInt = std::uint64_t;
+};
+
+// Integer types of known sizes.
+using TimeInMillis = int64_t;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#if !defined(GTEST_FLAG)
+#define GTEST_FLAG_NAME_(name) gtest_##name
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+#endif  // !defined(GTEST_FLAG)
+
+// Pick a command line flags implementation.
+#ifdef GTEST_INTERNAL_HAS_ABSL_FLAGS
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+  ABSL_FLAG(bool, GTEST_FLAG_NAME_(name), default_val, doc)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+  ABSL_FLAG(int32_t, GTEST_FLAG_NAME_(name), default_val, doc)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+  ABSL_FLAG(std::string, GTEST_FLAG_NAME_(name), default_val, doc)
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) \
+  ABSL_DECLARE_FLAG(bool, GTEST_FLAG_NAME_(name))
+#define GTEST_DECLARE_int32_(name) \
+  ABSL_DECLARE_FLAG(int32_t, GTEST_FLAG_NAME_(name))
+#define GTEST_DECLARE_string_(name) \
+  ABSL_DECLARE_FLAG(std::string, GTEST_FLAG_NAME_(name))
+
+#define GTEST_FLAG_SAVER_ ::absl::FlagSaver
+
+#define GTEST_FLAG_GET(name) ::absl::GetFlag(GTEST_FLAG(name))
+#define GTEST_FLAG_SET(name, value) \
+  (void)(::absl::SetFlag(&GTEST_FLAG(name), value))
+#define GTEST_USE_OWN_FLAGFILE_FLAG_ 0
+
+#undef GTEST_INTERNAL_HAS_ABSL_FLAGS
+#else  // ndef GTEST_INTERNAL_HAS_ABSL_FLAGS
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc)  \
+  namespace testing {                               \
+  GTEST_API_ bool GTEST_FLAG(name) = (default_val); \
+  }                                                 \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GTEST_DEFINE_int32_(name, default_val, doc)         \
+  namespace testing {                                       \
+  GTEST_API_ std::int32_t GTEST_FLAG(name) = (default_val); \
+  }                                                         \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GTEST_DEFINE_string_(name, default_val, doc)         \
+  namespace testing {                                        \
+  GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val); \
+  }                                                          \
+  static_assert(true, "no-op to require trailing semicolon")
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name)          \
+  namespace testing {                      \
+  GTEST_API_ extern bool GTEST_FLAG(name); \
+  }                                        \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GTEST_DECLARE_int32_(name)                 \
+  namespace testing {                              \
+  GTEST_API_ extern std::int32_t GTEST_FLAG(name); \
+  }                                                \
+  static_assert(true, "no-op to require trailing semicolon")
+#define GTEST_DECLARE_string_(name)                 \
+  namespace testing {                               \
+  GTEST_API_ extern ::std::string GTEST_FLAG(name); \
+  }                                                 \
+  static_assert(true, "no-op to require trailing semicolon")
+
+#define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver
+
+#define GTEST_FLAG_GET(name) ::testing::GTEST_FLAG(name)
+#define GTEST_FLAG_SET(name, value) (void)(::testing::GTEST_FLAG(name) = value)
+#define GTEST_USE_OWN_FLAGFILE_FLAG_ 1
+
+#endif  // GTEST_INTERNAL_HAS_ABSL_FLAGS
+
+// Thread annotations
+#if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
+#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+#define GTEST_LOCK_EXCLUDED_(locks)
+#endif  // !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+GTEST_API_ bool ParseInt32(const Message& src_text, const char* str,
+                           int32_t* value);
+
+// Parses a bool/int32_t/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ int32_t Int32FromGTestEnv(const char* flag, int32_t default_val);
+std::string OutputFlagAlsoCheckEnvVar();
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#if !defined(GTEST_INTERNAL_DEPRECATED)
+
+// Internal Macro to mark an API deprecated, for googletest usage only
+// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
+// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
+// a deprecated entity will trigger a warning when compiled with
+// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
+// For msvc /W3 option will need to be used
+// Note that for 'other' compilers this macro evaluates to nothing to prevent
+// compilations errors.
+#if defined(_MSC_VER)
+#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
+#elif defined(__GNUC__)
+#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
+#else
+#define GTEST_INTERNAL_DEPRECATED(message)
+#endif
+
+#endif  // !defined(GTEST_INTERNAL_DEPRECATED)
+
+#ifdef GTEST_HAS_ABSL
+// Always use absl::any for UniversalPrinter<> specializations if googletest
+// is built with absl support.
+#define GTEST_INTERNAL_HAS_ANY 1
+#include "absl/types/any.h"
+namespace testing {
+namespace internal {
+using Any = ::absl::any;
+}  // namespace internal
+}  // namespace testing
+#else
+#if defined(__cpp_lib_any) || (GTEST_INTERNAL_HAS_INCLUDE(<any>) &&        \
+                               GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
+                               (!defined(_MSC_VER) || GTEST_HAS_RTTI))
+// Otherwise for C++17 and higher use std::any for UniversalPrinter<>
+// specializations.
+#define GTEST_INTERNAL_HAS_ANY 1
+#include <any>
+namespace testing {
+namespace internal {
+using Any = ::std::any;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::any is not
+// supported.
+#endif  // __cpp_lib_any
+#endif  // GTEST_HAS_ABSL
+
+#ifndef GTEST_INTERNAL_HAS_ANY
+#define GTEST_INTERNAL_HAS_ANY 0
+#endif
+
+#ifdef GTEST_HAS_ABSL
+// Always use absl::optional for UniversalPrinter<> specializations if
+// googletest is built with absl support.
+#define GTEST_INTERNAL_HAS_OPTIONAL 1
+#include "absl/types/optional.h"
+namespace testing {
+namespace internal {
+template <typename T>
+using Optional = ::absl::optional<T>;
+inline ::absl::nullopt_t Nullopt() { return ::absl::nullopt; }
+}  // namespace internal
+}  // namespace testing
+#else
+#if defined(__cpp_lib_optional) || (GTEST_INTERNAL_HAS_INCLUDE(<optional>) && \
+                                    GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
+// Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
+// specializations.
+#define GTEST_INTERNAL_HAS_OPTIONAL 1
+#include <optional>
+namespace testing {
+namespace internal {
+template <typename T>
+using Optional = ::std::optional<T>;
+inline ::std::nullopt_t Nullopt() { return ::std::nullopt; }
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::optional is not
+// supported.
+#endif  // __cpp_lib_optional
+#endif  // GTEST_HAS_ABSL
+
+#ifndef GTEST_INTERNAL_HAS_OPTIONAL
+#define GTEST_INTERNAL_HAS_OPTIONAL 0
+#endif
+
+#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
+                                GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L)
+#define GTEST_INTERNAL_HAS_STD_SPAN 1
+#endif  // __cpp_lib_span
+
+#ifndef GTEST_INTERNAL_HAS_STD_SPAN
+#define GTEST_INTERNAL_HAS_STD_SPAN 0
+#endif
+
+#ifdef GTEST_HAS_ABSL
+// Always use absl::string_view for Matcher<> specializations if googletest
+// is built with absl support.
+#define GTEST_INTERNAL_HAS_STRING_VIEW 1
+#include "absl/strings/string_view.h"
+namespace testing {
+namespace internal {
+using StringView = ::absl::string_view;
+}  // namespace internal
+}  // namespace testing
+#else
+#if defined(__cpp_lib_string_view) ||             \
+    (GTEST_INTERNAL_HAS_INCLUDE(<string_view>) && \
+     GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
+// Otherwise for C++17 and higher use std::string_view for Matcher<>
+// specializations.
+#define GTEST_INTERNAL_HAS_STRING_VIEW 1
+#include <string_view>
+namespace testing {
+namespace internal {
+using StringView = ::std::string_view;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::string_view is not
+// supported.
+#endif  // __cpp_lib_string_view
+#endif  // GTEST_HAS_ABSL
+
+#ifndef GTEST_INTERNAL_HAS_STRING_VIEW
+#define GTEST_INTERNAL_HAS_STRING_VIEW 0
+#endif
+
+#ifdef GTEST_HAS_ABSL
+// Always use absl::variant for UniversalPrinter<> specializations if googletest
+// is built with absl support.
+#define GTEST_INTERNAL_HAS_VARIANT 1
+#include "absl/types/variant.h"
+namespace testing {
+namespace internal {
+template <typename... T>
+using Variant = ::absl::variant<T...>;
+}  // namespace internal
+}  // namespace testing
+#else
+#if defined(__cpp_lib_variant) || (GTEST_INTERNAL_HAS_INCLUDE(<variant>) && \
+                                   GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
+// Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
+// specializations.
+#define GTEST_INTERNAL_HAS_VARIANT 1
+#include <variant>
+namespace testing {
+namespace internal {
+template <typename... T>
+using Variant = ::std::variant<T...>;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::variant is not supported.
+#endif  // __cpp_lib_variant
+#endif  // GTEST_HAS_ABSL
+
+#ifndef GTEST_INTERNAL_HAS_VARIANT
+#define GTEST_INTERNAL_HAS_VARIANT 0
+#endif
+
+#if (defined(__cpp_constexpr) && !defined(__cpp_inline_variables)) || \
+    (defined(GTEST_INTERNAL_CPLUSPLUS_LANG) &&                        \
+     GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L)
+#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
+#endif
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-string.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-string.h
new file mode 100644
index 0000000..7c05b58
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-string.h
@@ -0,0 +1,178 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by gtest-internal.h.
+// It should not be #included by other files.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+#include <mem.h>
+#endif
+
+#include <string.h>
+
+#include <cstdint>
+#include <sstream>
+#include <string>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// String - an abstract class holding static string utilities.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true if and only if they have the same
+  // content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static std::string ShowWideCString(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true if and only if they have the
+  // same content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true if and only if
+  // they have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true if and only if
+  // they have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Returns true if and only if the given string ends with the given suffix,
+  // ignoring case. Any string is considered to end with an empty suffix.
+  static bool EndsWithCaseInsensitive(const std::string& str,
+                                      const std::string& suffix);
+
+  // Formats an int value as "%02d".
+  static std::string FormatIntWidth2(int value);  // "%02d" for width == 2
+
+  // Formats an int value to given width with leading zeros.
+  static std::string FormatIntWidthN(int value, int width);
+
+  // Formats an int value as "%X".
+  static std::string FormatHexInt(int value);
+
+  // Formats an int value as "%X".
+  static std::string FormatHexUInt32(uint32_t value);
+
+  // Formats a byte as "%02X".
+  static std::string FormatByte(unsigned char value);
+
+ private:
+  String();  // Not meant to be instantiated.
+};           // class String
+
+// Gets the content of the stringstream's buffer as an std::string.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/3rd-party/googletest/googletest/include/gtest/internal/gtest-type-util.h b/3rd-party/googletest/googletest/include/gtest/internal/gtest-type-util.h
new file mode 100644
index 0000000..78da053
--- /dev/null
+++ b/3rd-party/googletest/googletest/include/gtest/internal/gtest-type-util.h
@@ -0,0 +1,220 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.
+
+// IWYU pragma: private, include "gtest/gtest.h"
+// IWYU pragma: friend gtest/.*
+// IWYU pragma: friend gmock/.*
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include <string>
+#include <type_traits>
+#include <typeinfo>
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+#if GTEST_HAS_CXXABI_H_
+#include <cxxabi.h>
+#elif defined(__HP_aCC)
+#include <acxx_demangle.h>
+#endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// Canonicalizes a given name with respect to the Standard C++ Library.
+// This handles removing the inline namespace within `std` that is
+// used by various standard libraries (e.g., `std::__1`).  Names outside
+// of namespace std are returned unmodified.
+inline std::string CanonicalizeForStdLibVersioning(std::string s) {
+  static const char prefix[] = "std::__";
+  if (s.compare(0, strlen(prefix), prefix) == 0) {
+    std::string::size_type end = s.find("::", strlen(prefix));
+    if (end != s.npos) {
+      // Erase everything between the initial `std` and the second `::`.
+      s.erase(strlen("std"), end - strlen("std"));
+    }
+  }
+
+  // Strip redundant spaces in typename to match MSVC
+  // For example, std::pair<int, bool> -> std::pair<int,bool>
+  static const char to_search[] = ", ";
+  const char replace_char = ',';
+  size_t pos = 0;
+  while (true) {
+    // Get the next occurrence from the current position
+    pos = s.find(to_search, pos);
+    if (pos == std::string::npos) {
+      break;
+    }
+    // Replace this occurrence of substring
+    s.replace(pos, strlen(to_search), 1, replace_char);
+    ++pos;
+  }
+  return s;
+}
+
+#if GTEST_HAS_RTTI
+// GetTypeName(const std::type_info&) returns a human-readable name of type T.
+inline std::string GetTypeName(const std::type_info& type) {
+  const char* const name = type.name();
+#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return CanonicalizeForStdLibVersioning(name_str);
+#elif defined(_MSC_VER)
+  // Strip struct and class due to differences between
+  // MSVC and other compilers. std::pair<int,bool> is printed as
+  // "struct std::pair<int,bool>" when using MSVC vs "std::pair<int, bool>" with
+  // other compilers.
+  std::string s = name;
+  // Only strip the leading "struct " and "class ", so uses rfind == 0 to
+  // ensure that
+  if (s.rfind("struct ", 0) == 0) {
+    s = s.substr(strlen("struct "));
+  } else if (s.rfind("class ", 0) == 0) {
+    s = s.substr(strlen("class "));
+  }
+  return s;
+#else
+  return name;
+#endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+}
+#endif  // GTEST_HAS_RTTI
+
+// GetTypeName<T>() returns a human-readable name of type T if and only if
+// RTTI is enabled, otherwise it returns a dummy type name.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+#if GTEST_HAS_RTTI
+  return GetTypeName(typeid(T));
+#else
+  return "<type>";
+#endif  // GTEST_HAS_RTTI
+}
+
+// A unique type indicating an empty node
+struct None {};
+
+#define GTEST_TEMPLATE_ \
+  template <typename T> \
+  class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+#define GTEST_BIND_(TmplSel, T) TmplSel::template Bind<T>::type
+
+template <GTEST_TEMPLATE_ Head_, GTEST_TEMPLATE_... Tail_>
+struct Templates {
+  using Head = TemplateSel<Head_>;
+  using Tail = Templates<Tail_...>;
+};
+
+template <GTEST_TEMPLATE_ Head_>
+struct Templates<Head_> {
+  using Head = TemplateSel<Head_>;
+  using Tail = None;
+};
+
+// Tuple-like type lists
+template <typename Head_, typename... Tail_>
+struct Types {
+  using Head = Head_;
+  using Tail = Types<Tail_...>;
+};
+
+template <typename Head_>
+struct Types<Head_> {
+  using Head = Head_;
+  using Tail = None;
+};
+
+// Helper metafunctions to tell apart a single type from types
+// generated by ::testing::Types
+template <typename... Ts>
+struct ProxyTypeList {
+  using type = Types<Ts...>;
+};
+
+template <typename>
+struct is_proxy_type_list : std::false_type {};
+
+template <typename... Ts>
+struct is_proxy_type_list<ProxyTypeList<Ts...>> : std::true_type {};
+
+// Generator which conditionally creates type lists.
+// It recognizes if a requested type list should be created
+// and prevents creating a new type list nested within another one.
+template <typename T>
+struct GenerateTypeList {
+ private:
+  using proxy = typename std::conditional<is_proxy_type_list<T>::value, T,
+                                          ProxyTypeList<T>>::type;
+
+ public:
+  using type = typename proxy::type;
+};
+
+}  // namespace internal
+
+template <typename... Ts>
+using Types = internal::ProxyTypeList<Ts...>;
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/3rd-party/googletest/googletest/samples/prime_tables.h b/3rd-party/googletest/googletest/samples/prime_tables.h
new file mode 100644
index 0000000..14c016a
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/prime_tables.h
@@ -0,0 +1,125 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This provides interface PrimeTable that determines whether a number is a
+// prime and determines a next prime number. This interface is used
+// in Google Test samples demonstrating use of parameterized tests.
+
+#ifndef GOOGLETEST_SAMPLES_PRIME_TABLES_H_
+#define GOOGLETEST_SAMPLES_PRIME_TABLES_H_
+
+#include <algorithm>
+
+// The prime table interface.
+class PrimeTable {
+ public:
+  virtual ~PrimeTable() = default;
+
+  // Returns true if and only if n is a prime number.
+  virtual bool IsPrime(int n) const = 0;
+
+  // Returns the smallest prime number greater than p; or returns -1
+  // if the next prime is beyond the capacity of the table.
+  virtual int GetNextPrime(int p) const = 0;
+};
+
+// Implementation #1 calculates the primes on-the-fly.
+class OnTheFlyPrimeTable : public PrimeTable {
+ public:
+  bool IsPrime(int n) const override {
+    if (n <= 1) return false;
+
+    for (int i = 2; i * i <= n; i++) {
+      // n is divisible by an integer other than 1 and itself.
+      if ((n % i) == 0) return false;
+    }
+
+    return true;
+  }
+
+  int GetNextPrime(int p) const override {
+    if (p < 0) return -1;
+
+    for (int n = p + 1;; n++) {
+      if (IsPrime(n)) return n;
+    }
+  }
+};
+
+// Implementation #2 pre-calculates the primes and stores the result
+// in an array.
+class PreCalculatedPrimeTable : public PrimeTable {
+ public:
+  // 'max' specifies the maximum number the prime table holds.
+  explicit PreCalculatedPrimeTable(int max)
+      : is_prime_size_(std::max(1, max + 1)),
+        is_prime_(new bool[static_cast<size_t>(is_prime_size_)]) {
+    CalculatePrimesUpTo(is_prime_size_ - 1);
+  }
+  ~PreCalculatedPrimeTable() override { delete[] is_prime_; }
+
+  bool IsPrime(int n) const override {
+    return 0 <= n && n < is_prime_size_ && is_prime_[n];
+  }
+
+  int GetNextPrime(int p) const override {
+    for (int n = p + 1; n < is_prime_size_; n++) {
+      if (is_prime_[n]) return n;
+    }
+
+    return -1;
+  }
+
+ private:
+  void CalculatePrimesUpTo(int max) {
+    ::std::fill(is_prime_, is_prime_ + is_prime_size_, true);
+    is_prime_[0] = is_prime_[1] = false;
+
+    // Checks every candidate for prime number (we know that 2 is the only even
+    // prime).
+    for (int i = 2; i * i <= max; i += i % 2 + 1) {
+      if (!is_prime_[i]) continue;
+
+      // Marks all multiples of i (except i itself) as non-prime.
+      // We are starting here from i-th multiplier, because all smaller
+      // complex numbers were already marked.
+      for (int j = i * i; j <= max; j += i) {
+        is_prime_[j] = false;
+      }
+    }
+  }
+
+  const int is_prime_size_;
+  bool* const is_prime_;
+
+  // Disables compiler warning "assignment operator could not be generated."
+  void operator=(const PreCalculatedPrimeTable& rhs);
+};
+
+#endif  // GOOGLETEST_SAMPLES_PRIME_TABLES_H_
diff --git a/3rd-party/googletest/googletest/samples/sample1.cc b/3rd-party/googletest/googletest/samples/sample1.cc
new file mode 100644
index 0000000..80b69f4
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample1.cc
@@ -0,0 +1,66 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+#include "sample1.h"
+
+// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
+int Factorial(int n) {
+  int result = 1;
+  for (int i = 1; i <= n; i++) {
+    result *= i;
+  }
+
+  return result;
+}
+
+// Returns true if and only if n is a prime number.
+bool IsPrime(int n) {
+  // Trivial case 1: small numbers
+  if (n <= 1) return false;
+
+  // Trivial case 2: even numbers
+  if (n % 2 == 0) return n == 2;
+
+  // Now, we have that n is odd and n >= 3.
+
+  // Try to divide n by every odd number i, starting from 3
+  for (int i = 3;; i += 2) {
+    // We only have to try i up to the square root of n
+    if (i > n / i) break;
+
+    // Now, we have i <= n/i < n.
+    // If n is divisible by i, n is not prime.
+    if (n % i == 0) return false;
+  }
+
+  // n has no integer factor in the range (1, n), and thus is prime.
+  return true;
+}
diff --git a/3rd-party/googletest/googletest/samples/sample1.h b/3rd-party/googletest/googletest/samples/sample1.h
new file mode 100644
index 0000000..ba392cf
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample1.h
@@ -0,0 +1,41 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+#ifndef GOOGLETEST_SAMPLES_SAMPLE1_H_
+#define GOOGLETEST_SAMPLES_SAMPLE1_H_
+
+// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
+int Factorial(int n);
+
+// Returns true if and only if n is a prime number.
+bool IsPrime(int n);
+
+#endif  // GOOGLETEST_SAMPLES_SAMPLE1_H_
diff --git a/3rd-party/googletest/googletest/samples/sample10_unittest.cc b/3rd-party/googletest/googletest/samples/sample10_unittest.cc
new file mode 100644
index 0000000..2107954
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample10_unittest.cc
@@ -0,0 +1,138 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This sample shows how to use Google Test listener API to implement
+// a primitive leak checker.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::UnitTest;
+
+namespace {
+// We will track memory used by this class.
+class Water {
+ public:
+  // Normal Water declarations go here.
+
+  // operator new and operator delete help us control water allocation.
+  void* operator new(size_t allocation_size) {
+    allocated_++;
+    return malloc(allocation_size);
+  }
+
+  void operator delete(void* block, size_t /* allocation_size */) {
+    allocated_--;
+    free(block);
+  }
+
+  static int allocated() { return allocated_; }
+
+ private:
+  static int allocated_;
+};
+
+int Water::allocated_ = 0;
+
+// This event listener monitors how many Water objects are created and
+// destroyed by each test, and reports a failure if a test leaks some Water
+// objects. It does this by comparing the number of live Water objects at
+// the beginning of a test and at the end of a test.
+class LeakChecker : public EmptyTestEventListener {
+ private:
+  // Called before a test starts.
+  void OnTestStart(const TestInfo& /* test_info */) override {
+    initially_allocated_ = Water::allocated();
+  }
+
+  // Called after a test ends.
+  void OnTestEnd(const TestInfo& /* test_info */) override {
+    int difference = Water::allocated() - initially_allocated_;
+
+    // You can generate a failure in any event handler except
+    // OnTestPartResult. Just use an appropriate Google Test assertion to do
+    // it.
+    EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!";
+  }
+
+  int initially_allocated_;
+};
+
+TEST(ListenersTest, DoesNotLeak) {
+  Water* water = new Water;
+  delete water;
+}
+
+// This should fail when the --check_for_leaks command line flag is
+// specified.
+TEST(ListenersTest, LeaksWater) {
+  Water* water = new Water;
+  EXPECT_TRUE(water != nullptr);
+}
+}  // namespace
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  bool check_for_leaks = false;
+  if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0)
+    check_for_leaks = true;
+  else
+    printf("%s\n",
+           "Run this program with --check_for_leaks to enable "
+           "custom leak checking in the tests.");
+
+  // If we are given the --check_for_leaks command line flag, installs the
+  // leak checker.
+  if (check_for_leaks) {
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+
+    // Adds the leak checker to the end of the test event listener list,
+    // after the default text output printer and the default XML report
+    // generator.
+    //
+    // The order is important - it ensures that failures generated in the
+    // leak checker's OnTestEnd() method are processed by the text and XML
+    // printers *before* their OnTestEnd() methods are called, such that
+    // they are attributed to the right test. Remember that a listener
+    // receives an OnXyzStart event *after* listeners preceding it in the
+    // list received that event, and receives an OnXyzEnd event *before*
+    // listeners preceding it.
+    //
+    // We don't need to worry about deleting the new listener later, as
+    // Google Test will do it.
+    listeners.Append(new LeakChecker);
+  }
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/samples/sample1_unittest.cc b/3rd-party/googletest/googletest/samples/sample1_unittest.cc
new file mode 100644
index 0000000..60f2770
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample1_unittest.cc
@@ -0,0 +1,148 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+// This sample shows how to write a simple unit test for a function,
+// using Google C++ testing framework.
+//
+// Writing a unit test using Google C++ testing framework is easy as 1-2-3:
+
+// Step 1. Include necessary header files such that the stuff your
+// test logic needs is declared.
+//
+// Don't forget gtest.h, which declares the testing framework.
+
+#include "sample1.h"
+
+#include <limits.h>
+
+#include "gtest/gtest.h"
+namespace {
+
+// Step 2. Use the TEST macro to define your tests.
+//
+// TEST has two parameters: the test case name and the test name.
+// After using the macro, you should define your test logic between a
+// pair of braces.  You can use a bunch of macros to indicate the
+// success or failure of a test.  EXPECT_TRUE and EXPECT_EQ are
+// examples of such macros.  For a complete list, see gtest.h.
+//
+// <TechnicalDetails>
+//
+// In Google Test, tests are grouped into test cases.  This is how we
+// keep test code organized.  You should put logically related tests
+// into the same test case.
+//
+// The test case name and the test name should both be valid C++
+// identifiers.  And you should not use underscore (_) in the names.
+//
+// Google Test guarantees that each test you define is run exactly
+// once, but it makes no guarantee on the order the tests are
+// executed.  Therefore, you should write your tests in such a way
+// that their results don't depend on their order.
+//
+// </TechnicalDetails>
+
+// Tests Factorial().
+
+// Tests factorial of negative numbers.
+TEST(FactorialTest, Negative) {
+  // This test is named "Negative", and belongs to the "FactorialTest"
+  // test case.
+  EXPECT_EQ(1, Factorial(-5));
+  EXPECT_EQ(1, Factorial(-1));
+  EXPECT_GT(Factorial(-10), 0);
+
+  // <TechnicalDetails>
+  //
+  // EXPECT_EQ(expected, actual) is the same as
+  //
+  //   EXPECT_TRUE((expected) == (actual))
+  //
+  // except that it will print both the expected value and the actual
+  // value when the assertion fails.  This is very helpful for
+  // debugging.  Therefore in this case EXPECT_EQ is preferred.
+  //
+  // On the other hand, EXPECT_TRUE accepts any Boolean expression,
+  // and is thus more general.
+  //
+  // </TechnicalDetails>
+}
+
+// Tests factorial of 0.
+TEST(FactorialTest, Zero) { EXPECT_EQ(1, Factorial(0)); }
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, Positive) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+
+// Tests IsPrime()
+
+// Tests negative input.
+TEST(IsPrimeTest, Negative) {
+  // This test belongs to the IsPrimeTest test case.
+
+  EXPECT_FALSE(IsPrime(-1));
+  EXPECT_FALSE(IsPrime(-2));
+  EXPECT_FALSE(IsPrime(INT_MIN));
+}
+
+// Tests some trivial cases.
+TEST(IsPrimeTest, Trivial) {
+  EXPECT_FALSE(IsPrime(0));
+  EXPECT_FALSE(IsPrime(1));
+  EXPECT_TRUE(IsPrime(2));
+  EXPECT_TRUE(IsPrime(3));
+}
+
+// Tests positive input.
+TEST(IsPrimeTest, Positive) {
+  EXPECT_FALSE(IsPrime(4));
+  EXPECT_TRUE(IsPrime(5));
+  EXPECT_FALSE(IsPrime(6));
+  EXPECT_TRUE(IsPrime(23));
+}
+}  // namespace
+
+// Step 3. Call RUN_ALL_TESTS() in main().
+//
+// We do this by linking in src/gtest_main.cc file, which consists of
+// a main() function which calls RUN_ALL_TESTS() for us.
+//
+// This runs all the tests you've defined, prints the result, and
+// returns 0 if successful, or 1 otherwise.
+//
+// Did you notice that we didn't register the tests?  The
+// RUN_ALL_TESTS() macro magically knows about all the tests we
+// defined.  Isn't this convenient?
diff --git a/3rd-party/googletest/googletest/samples/sample2.cc b/3rd-party/googletest/googletest/samples/sample2.cc
new file mode 100644
index 0000000..be7c4c9
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample2.cc
@@ -0,0 +1,54 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+#include "sample2.h"
+
+#include <string.h>
+
+// Clones a 0-terminated C string, allocating memory using new.
+const char* MyString::CloneCString(const char* a_c_string) {
+  if (a_c_string == nullptr) return nullptr;
+
+  const size_t len = strlen(a_c_string);
+  char* const clone = new char[len + 1];
+  memcpy(clone, a_c_string, len + 1);
+
+  return clone;
+}
+
+// Sets the 0-terminated C string this MyString object
+// represents.
+void MyString::Set(const char* a_c_string) {
+  // Makes sure this works when c_string == c_string_
+  const char* const temp = MyString::CloneCString(a_c_string);
+  delete[] c_string_;
+  c_string_ = temp;
+}
diff --git a/3rd-party/googletest/googletest/samples/sample2.h b/3rd-party/googletest/googletest/samples/sample2.h
new file mode 100644
index 0000000..15a1ce7
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample2.h
@@ -0,0 +1,79 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+#ifndef GOOGLETEST_SAMPLES_SAMPLE2_H_
+#define GOOGLETEST_SAMPLES_SAMPLE2_H_
+
+#include <string.h>
+
+// A simple string class.
+class MyString {
+ private:
+  const char* c_string_;
+  const MyString& operator=(const MyString& rhs);
+
+ public:
+  // Clones a 0-terminated C string, allocating memory using new.
+  static const char* CloneCString(const char* a_c_string);
+
+  ////////////////////////////////////////////////////////////
+  //
+  // C'tors
+
+  // The default c'tor constructs a NULL string.
+  MyString() : c_string_(nullptr) {}
+
+  // Constructs a MyString by cloning a 0-terminated C string.
+  explicit MyString(const char* a_c_string) : c_string_(nullptr) {
+    Set(a_c_string);
+  }
+
+  // Copy c'tor
+  MyString(const MyString& string) : c_string_(nullptr) {
+    Set(string.c_string_);
+  }
+
+  ////////////////////////////////////////////////////////////
+  //
+  // D'tor.  MyString is intended to be a final class, so the d'tor
+  // doesn't need to be virtual.
+  ~MyString() { delete[] c_string_; }
+
+  // Gets the 0-terminated C string this MyString object represents.
+  const char* c_string() const { return c_string_; }
+
+  size_t Length() const { return c_string_ == nullptr ? 0 : strlen(c_string_); }
+
+  // Sets the 0-terminated C string this MyString object represents.
+  void Set(const char* c_string);
+};
+
+#endif  // GOOGLETEST_SAMPLES_SAMPLE2_H_
diff --git a/3rd-party/googletest/googletest/samples/sample2_unittest.cc b/3rd-party/googletest/googletest/samples/sample2_unittest.cc
new file mode 100644
index 0000000..cd734f9
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample2_unittest.cc
@@ -0,0 +1,107 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+// This sample shows how to write a more complex unit test for a class
+// that has multiple member functions.
+//
+// Usually, it's a good idea to have one test for each method in your
+// class.  You don't have to do that exactly, but it helps to keep
+// your tests organized.  You may also throw in additional tests as
+// needed.
+
+#include "sample2.h"
+
+#include "gtest/gtest.h"
+namespace {
+// In this example, we test the MyString class (a simple string).
+
+// Tests the default c'tor.
+TEST(MyString, DefaultConstructor) {
+  const MyString s;
+
+  // Asserts that s.c_string() returns NULL.
+  //
+  // <TechnicalDetails>
+  //
+  // If we write NULL instead of
+  //
+  //   static_cast<const char *>(NULL)
+  //
+  // in this assertion, it will generate a warning on gcc 3.4.  The
+  // reason is that EXPECT_EQ needs to know the types of its
+  // arguments in order to print them when it fails.  Since NULL is
+  // #defined as 0, the compiler will use the formatter function for
+  // int to print it.  However, gcc thinks that NULL should be used as
+  // a pointer, not an int, and therefore complains.
+  //
+  // The root of the problem is C++'s lack of distinction between the
+  // integer number 0 and the null pointer constant.  Unfortunately,
+  // we have to live with this fact.
+  //
+  // </TechnicalDetails>
+  EXPECT_STREQ(nullptr, s.c_string());
+
+  EXPECT_EQ(0u, s.Length());
+}
+
+const char kHelloString[] = "Hello, world!";
+
+// Tests the c'tor that accepts a C string.
+TEST(MyString, ConstructorFromCString) {
+  const MyString s(kHelloString);
+  EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
+  EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());
+}
+
+// Tests the copy c'tor.
+TEST(MyString, CopyConstructor) {
+  const MyString s1(kHelloString);
+  const MyString s2 = s1;
+  EXPECT_EQ(0, strcmp(s2.c_string(), kHelloString));
+}
+
+// Tests the Set method.
+TEST(MyString, Set) {
+  MyString s;
+
+  s.Set(kHelloString);
+  EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
+
+  // Set should work when the input pointer is the same as the one
+  // already in the MyString object.
+  s.Set(s.c_string());
+  EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
+
+  // Can we set the MyString to NULL?
+  s.Set(nullptr);
+  EXPECT_STREQ(nullptr, s.c_string());
+}
+}  // namespace
diff --git a/3rd-party/googletest/googletest/samples/sample3-inl.h b/3rd-party/googletest/googletest/samples/sample3-inl.h
new file mode 100644
index 0000000..bc3ffb9
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample3-inl.h
@@ -0,0 +1,171 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+#ifndef GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
+#define GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
+
+#include <stddef.h>
+
+// Queue is a simple queue implemented as a singled-linked list.
+//
+// The element type must support copy constructor.
+template <typename E>  // E is the element type
+class Queue;
+
+// QueueNode is a node in a Queue, which consists of an element of
+// type E and a pointer to the next node.
+template <typename E>  // E is the element type
+class QueueNode {
+  friend class Queue<E>;
+
+ public:
+  // Gets the element in this node.
+  const E& element() const { return element_; }
+
+  // Gets the next node in the queue.
+  QueueNode* next() { return next_; }
+  const QueueNode* next() const { return next_; }
+
+ private:
+  // Creates a node with a given element value.  The next pointer is
+  // set to NULL.
+  explicit QueueNode(const E& an_element)
+      : element_(an_element), next_(nullptr) {}
+
+  // We disable the default assignment operator and copy c'tor.
+  const QueueNode& operator=(const QueueNode&);
+  QueueNode(const QueueNode&);
+
+  E element_;
+  QueueNode* next_;
+};
+
+template <typename E>  // E is the element type.
+class Queue {
+ public:
+  // Creates an empty queue.
+  Queue() : head_(nullptr), last_(nullptr), size_(0) {}
+
+  // D'tor.  Clears the queue.
+  ~Queue() { Clear(); }
+
+  // Clears the queue.
+  void Clear() {
+    if (size_ > 0) {
+      // 1. Deletes every node.
+      QueueNode<E>* node = head_;
+      QueueNode<E>* next = node->next();
+      for (;;) {
+        delete node;
+        node = next;
+        if (node == nullptr) break;
+        next = node->next();
+      }
+
+      // 2. Resets the member variables.
+      head_ = last_ = nullptr;
+      size_ = 0;
+    }
+  }
+
+  // Gets the number of elements.
+  size_t Size() const { return size_; }
+
+  // Gets the first element of the queue, or NULL if the queue is empty.
+  QueueNode<E>* Head() { return head_; }
+  const QueueNode<E>* Head() const { return head_; }
+
+  // Gets the last element of the queue, or NULL if the queue is empty.
+  QueueNode<E>* Last() { return last_; }
+  const QueueNode<E>* Last() const { return last_; }
+
+  // Adds an element to the end of the queue.  A copy of the element is
+  // created using the copy constructor, and then stored in the queue.
+  // Changes made to the element in the queue doesn't affect the source
+  // object, and vice versa.
+  void Enqueue(const E& element) {
+    QueueNode<E>* new_node = new QueueNode<E>(element);
+
+    if (size_ == 0) {
+      head_ = last_ = new_node;
+      size_ = 1;
+    } else {
+      last_->next_ = new_node;
+      last_ = new_node;
+      size_++;
+    }
+  }
+
+  // Removes the head of the queue and returns it.  Returns NULL if
+  // the queue is empty.
+  E* Dequeue() {
+    if (size_ == 0) {
+      return nullptr;
+    }
+
+    const QueueNode<E>* const old_head = head_;
+    head_ = head_->next_;
+    size_--;
+    if (size_ == 0) {
+      last_ = nullptr;
+    }
+
+    E* element = new E(old_head->element());
+    delete old_head;
+
+    return element;
+  }
+
+  // Applies a function/functor on each element of the queue, and
+  // returns the result in a new queue.  The original queue is not
+  // affected.
+  template <typename F>
+  Queue* Map(F function) const {
+    Queue* new_queue = new Queue();
+    for (const QueueNode<E>* node = head_; node != nullptr;
+         node = node->next_) {
+      new_queue->Enqueue(function(node->element()));
+    }
+
+    return new_queue;
+  }
+
+ private:
+  QueueNode<E>* head_;  // The first node of the queue.
+  QueueNode<E>* last_;  // The last node of the queue.
+  size_t size_;         // The number of elements in the queue.
+
+  // We disallow copying a queue.
+  Queue(const Queue&);
+  const Queue& operator=(const Queue&);
+};
+
+#endif  // GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
diff --git a/3rd-party/googletest/googletest/samples/sample3_unittest.cc b/3rd-party/googletest/googletest/samples/sample3_unittest.cc
new file mode 100644
index 0000000..71609c6
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample3_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+// In this example, we use a more advanced feature of Google Test called
+// test fixture.
+//
+// A test fixture is a place to hold objects and functions shared by
+// all tests in a test case.  Using a test fixture avoids duplicating
+// the test code necessary to initialize and cleanup those common
+// objects for each test.  It is also useful for defining sub-routines
+// that your tests need to invoke a lot.
+//
+// <TechnicalDetails>
+//
+// The tests share the test fixture in the sense of code sharing, not
+// data sharing.  Each test is given its own fresh copy of the
+// fixture.  You cannot expect the data modified by one test to be
+// passed on to another test, which is a bad idea.
+//
+// The reason for this design is that tests should be independent and
+// repeatable.  In particular, a test should not fail as the result of
+// another test's failure.  If one test depends on info produced by
+// another test, then the two tests should really be one big test.
+//
+// The macros for indicating the success/failure of a test
+// (EXPECT_TRUE, FAIL, etc) need to know what the current test is
+// (when Google Test prints the test result, it tells you which test
+// each failure belongs to).  Technically, these macros invoke a
+// member function of the Test class.  Therefore, you cannot use them
+// in a global function.  That's why you should put test sub-routines
+// in a test fixture.
+//
+// </TechnicalDetails>
+
+#include "sample3-inl.h"
+#include "gtest/gtest.h"
+namespace {
+// To use a test fixture, derive a class from testing::Test.
+class QueueTestSmpl3 : public testing::Test {
+ protected:  // You should make the members protected s.t. they can be
+             // accessed from sub-classes.
+  // virtual void SetUp() will be called before each test is run.  You
+  // should define it if you need to initialize the variables.
+  // Otherwise, this can be skipped.
+  void SetUp() override {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() will be called after each test is run.
+  // You should define it if there is cleanup work to do.  Otherwise,
+  // you don't have to provide it.
+  //
+  // virtual void TearDown() {
+  // }
+
+  // A helper function that some test uses.
+  static int Double(int n) { return 2 * n; }
+
+  // A helper function for testing Queue::Map().
+  void MapTester(const Queue<int>* q) {
+    // Creates a new queue, where each element is twice as big as the
+    // corresponding one in q.
+    const Queue<int>* const new_q = q->Map(Double);
+
+    // Verifies that the new queue has the same size as q.
+    ASSERT_EQ(q->Size(), new_q->Size());
+
+    // Verifies the relationship between the elements of the two queues.
+    for (const QueueNode<int>*n1 = q->Head(), *n2 = new_q->Head();
+         n1 != nullptr; n1 = n1->next(), n2 = n2->next()) {
+      EXPECT_EQ(2 * n1->element(), n2->element());
+    }
+
+    delete new_q;
+  }
+
+  // Declares the variables your tests want to use.
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+
+// When you have a test fixture, you define a test using TEST_F
+// instead of TEST.
+
+// Tests the default c'tor.
+TEST_F(QueueTestSmpl3, DefaultConstructor) {
+  // You can access data in the test fixture here.
+  EXPECT_EQ(0u, q0_.Size());
+}
+
+// Tests Dequeue().
+TEST_F(QueueTestSmpl3, Dequeue) {
+  int* n = q0_.Dequeue();
+  EXPECT_TRUE(n == nullptr);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != nullptr);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0u, q1_.Size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != nullptr);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1u, q2_.Size());
+  delete n;
+}
+
+// Tests the Queue::Map() function.
+TEST_F(QueueTestSmpl3, Map) {
+  MapTester(&q0_);
+  MapTester(&q1_);
+  MapTester(&q2_);
+}
+}  // namespace
diff --git a/3rd-party/googletest/googletest/samples/sample4.cc b/3rd-party/googletest/googletest/samples/sample4.cc
new file mode 100644
index 0000000..489c89b
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample4.cc
@@ -0,0 +1,50 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+
+#include "sample4.h"
+
+#include <stdio.h>
+
+// Returns the current counter value, and increments it.
+int Counter::Increment() { return counter_++; }
+
+// Returns the current counter value, and decrements it.
+// counter can not be less than 0, return 0 in this case
+int Counter::Decrement() {
+  if (counter_ == 0) {
+    return counter_;
+  } else {
+    return counter_--;
+  }
+}
+
+// Prints the current counter value to STDOUT.
+void Counter::Print() const { printf("%d", counter_); }
diff --git a/3rd-party/googletest/googletest/samples/sample4.h b/3rd-party/googletest/googletest/samples/sample4.h
new file mode 100644
index 0000000..0c4ed92
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample4.h
@@ -0,0 +1,53 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+#ifndef GOOGLETEST_SAMPLES_SAMPLE4_H_
+#define GOOGLETEST_SAMPLES_SAMPLE4_H_
+
+// A simple monotonic counter.
+class Counter {
+ private:
+  int counter_;
+
+ public:
+  // Creates a counter that starts at 0.
+  Counter() : counter_(0) {}
+
+  // Returns the current counter value, and increments it.
+  int Increment();
+
+  // Returns the current counter value, and decrements it.
+  int Decrement();
+
+  // Prints the current counter value to STDOUT.
+  void Print() const;
+};
+
+#endif  // GOOGLETEST_SAMPLES_SAMPLE4_H_
diff --git a/3rd-party/googletest/googletest/samples/sample4_unittest.cc b/3rd-party/googletest/googletest/samples/sample4_unittest.cc
new file mode 100644
index 0000000..fb9973f
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample4_unittest.cc
@@ -0,0 +1,53 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "sample4.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+// Tests the Increment() method.
+
+TEST(Counter, Increment) {
+  Counter c;
+
+  // Test that counter 0 returns 0
+  EXPECT_EQ(0, c.Decrement());
+
+  // EXPECT_EQ() evaluates its arguments exactly once, so they
+  // can have side effects.
+
+  EXPECT_EQ(0, c.Increment());
+  EXPECT_EQ(1, c.Increment());
+  EXPECT_EQ(2, c.Increment());
+
+  EXPECT_EQ(3, c.Decrement());
+}
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/samples/sample5_unittest.cc b/3rd-party/googletest/googletest/samples/sample5_unittest.cc
new file mode 100644
index 0000000..cc8c0f0
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample5_unittest.cc
@@ -0,0 +1,189 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This sample teaches how to reuse a test fixture in multiple test
+// cases by deriving sub-fixtures from it.
+//
+// When you define a test fixture, you specify the name of the test
+// case that will use this fixture.  Therefore, a test fixture can
+// be used by only one test case.
+//
+// Sometimes, more than one test cases may want to use the same or
+// slightly different test fixtures.  For example, you may want to
+// make sure that all tests for a GUI library don't leak important
+// system resources like fonts and brushes.  In Google Test, you do
+// this by putting the shared logic in a super (as in "super class")
+// test fixture, and then have each test case use a fixture derived
+// from this super fixture.
+
+#include <limits.h>
+#include <time.h>
+
+#include "sample1.h"
+#include "sample3-inl.h"
+#include "gtest/gtest.h"
+namespace {
+// In this sample, we want to ensure that every test finishes within
+// ~5 seconds.  If a test takes longer to run, we consider it a
+// failure.
+//
+// We put the code for timing a test in a test fixture called
+// "QuickTest".  QuickTest is intended to be the super fixture that
+// other fixtures derive from, therefore there is no test case with
+// the name "QuickTest".  This is OK.
+//
+// Later, we will derive multiple test fixtures from QuickTest.
+class QuickTest : public testing::Test {
+ protected:
+  // Remember that SetUp() is run immediately before a test starts.
+  // This is a good place to record the start time.
+  void SetUp() override { start_time_ = time(nullptr); }
+
+  // TearDown() is invoked immediately after a test finishes.  Here we
+  // check if the test was too slow.
+  void TearDown() override {
+    // Gets the time when the test finishes
+    const time_t end_time = time(nullptr);
+
+    // Asserts that the test took no more than ~5 seconds.  Did you
+    // know that you can use assertions in SetUp() and TearDown() as
+    // well?
+    EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
+  }
+
+  // The UTC time (in seconds) when the test starts
+  time_t start_time_;
+};
+
+// We derive a fixture named IntegerFunctionTest from the QuickTest
+// fixture.  All tests using this fixture will be automatically
+// required to be quick.
+class IntegerFunctionTest : public QuickTest {
+  // We don't need any more logic than already in the QuickTest fixture.
+  // Therefore the body is empty.
+};
+
+// Now we can write tests in the IntegerFunctionTest test case.
+
+// Tests Factorial()
+TEST_F(IntegerFunctionTest, Factorial) {
+  // Tests factorial of negative numbers.
+  EXPECT_EQ(1, Factorial(-5));
+  EXPECT_EQ(1, Factorial(-1));
+  EXPECT_GT(Factorial(-10), 0);
+
+  // Tests factorial of 0.
+  EXPECT_EQ(1, Factorial(0));
+
+  // Tests factorial of positive numbers.
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+
+// Tests IsPrime()
+TEST_F(IntegerFunctionTest, IsPrime) {
+  // Tests negative input.
+  EXPECT_FALSE(IsPrime(-1));
+  EXPECT_FALSE(IsPrime(-2));
+  EXPECT_FALSE(IsPrime(INT_MIN));
+
+  // Tests some trivial cases.
+  EXPECT_FALSE(IsPrime(0));
+  EXPECT_FALSE(IsPrime(1));
+  EXPECT_TRUE(IsPrime(2));
+  EXPECT_TRUE(IsPrime(3));
+
+  // Tests positive input.
+  EXPECT_FALSE(IsPrime(4));
+  EXPECT_TRUE(IsPrime(5));
+  EXPECT_FALSE(IsPrime(6));
+  EXPECT_TRUE(IsPrime(23));
+}
+
+// The next test case (named "QueueTest") also needs to be quick, so
+// we derive another fixture from QuickTest.
+//
+// The QueueTest test fixture has some logic and shared objects in
+// addition to what's in QuickTest already.  We define the additional
+// stuff inside the body of the test fixture, as usual.
+class QueueTest : public QuickTest {
+ protected:
+  void SetUp() override {
+    // First, we need to set up the super fixture (QuickTest).
+    QuickTest::SetUp();
+
+    // Second, some additional setup for this fixture.
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // By default, TearDown() inherits the behavior of
+  // QuickTest::TearDown().  As we have no additional cleaning work
+  // for QueueTest, we omit it here.
+  //
+  // virtual void TearDown() {
+  //   QuickTest::TearDown();
+  // }
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+
+// Now, let's write tests using the QueueTest fixture.
+
+// Tests the default constructor.
+TEST_F(QueueTest, DefaultConstructor) { EXPECT_EQ(0u, q0_.Size()); }
+
+// Tests Dequeue().
+TEST_F(QueueTest, Dequeue) {
+  int* n = q0_.Dequeue();
+  EXPECT_TRUE(n == nullptr);
+
+  n = q1_.Dequeue();
+  EXPECT_TRUE(n != nullptr);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0u, q1_.Size());
+  delete n;
+
+  n = q2_.Dequeue();
+  EXPECT_TRUE(n != nullptr);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1u, q2_.Size());
+  delete n;
+}
+}  // namespace
+// If necessary, you can derive further test fixtures from a derived
+// fixture itself.  For example, you can derive another fixture from
+// QueueTest.  Google Test imposes no limit on how deep the hierarchy
+// can be.  In practice, however, you probably don't want it to be too
+// deep as to be confusing.
diff --git a/3rd-party/googletest/googletest/samples/sample6_unittest.cc b/3rd-party/googletest/googletest/samples/sample6_unittest.cc
new file mode 100644
index 0000000..cf576f0
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample6_unittest.cc
@@ -0,0 +1,214 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This sample shows how to test common properties of multiple
+// implementations of the same interface (aka interface tests).
+
+// The interface and its implementations are in this header.
+#include "prime_tables.h"
+#include "gtest/gtest.h"
+namespace {
+// First, we define some factory functions for creating instances of
+// the implementations.  You may be able to skip this step if all your
+// implementations can be constructed the same way.
+
+template <class T>
+PrimeTable* CreatePrimeTable();
+
+template <>
+PrimeTable* CreatePrimeTable<OnTheFlyPrimeTable>() {
+  return new OnTheFlyPrimeTable;
+}
+
+template <>
+PrimeTable* CreatePrimeTable<PreCalculatedPrimeTable>() {
+  return new PreCalculatedPrimeTable(10000);
+}
+
+// Then we define a test fixture class template.
+template <class T>
+class PrimeTableTest : public testing::Test {
+ protected:
+  // The ctor calls the factory function to create a prime table
+  // implemented by T.
+  PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
+
+  ~PrimeTableTest() override { delete table_; }
+
+  // Note that we test an implementation via the base interface
+  // instead of the actual implementation class.  This is important
+  // for keeping the tests close to the real world scenario, where the
+  // implementation is invoked via the base interface.  It avoids
+  // got-yas where the implementation class has a method that shadows
+  // a method with the same name (but slightly different argument
+  // types) in the base interface, for example.
+  PrimeTable* const table_;
+};
+
+using testing::Types;
+
+// Google Test offers two ways for reusing tests for different types.
+// The first is called "typed tests".  You should use it if you
+// already know *all* the types you are gonna exercise when you write
+// the tests.
+
+// To write a typed test case, first use
+//
+//   TYPED_TEST_SUITE(TestCaseName, TypeList);
+//
+// to declare it and specify the type parameters.  As with TEST_F,
+// TestCaseName must match the test fixture name.
+
+// The list of types we want to test.
+typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
+
+TYPED_TEST_SUITE(PrimeTableTest, Implementations);
+
+// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
+// similar to TEST_F.
+TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  // Inside the test body, you can refer to the type parameter by
+  // TypeParam, and refer to the fixture class by TestFixture.  We
+  // don't need them in this example.
+
+  // Since we are in the template world, C++ requires explicitly
+  // writing 'this->' when referring to members of the fixture class.
+  // This is something you have to learn to live with.
+  EXPECT_FALSE(this->table_->IsPrime(-5));
+  EXPECT_FALSE(this->table_->IsPrime(0));
+  EXPECT_FALSE(this->table_->IsPrime(1));
+  EXPECT_FALSE(this->table_->IsPrime(4));
+  EXPECT_FALSE(this->table_->IsPrime(6));
+  EXPECT_FALSE(this->table_->IsPrime(100));
+}
+
+TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(this->table_->IsPrime(2));
+  EXPECT_TRUE(this->table_->IsPrime(3));
+  EXPECT_TRUE(this->table_->IsPrime(5));
+  EXPECT_TRUE(this->table_->IsPrime(7));
+  EXPECT_TRUE(this->table_->IsPrime(11));
+  EXPECT_TRUE(this->table_->IsPrime(131));
+}
+
+TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, this->table_->GetNextPrime(0));
+  EXPECT_EQ(3, this->table_->GetNextPrime(2));
+  EXPECT_EQ(5, this->table_->GetNextPrime(3));
+  EXPECT_EQ(7, this->table_->GetNextPrime(5));
+  EXPECT_EQ(11, this->table_->GetNextPrime(7));
+  EXPECT_EQ(131, this->table_->GetNextPrime(128));
+}
+
+// That's it!  Google Test will repeat each TYPED_TEST for each type
+// in the type list specified in TYPED_TEST_SUITE.  Sit back and be
+// happy that you don't have to define them multiple times.
+
+using testing::Types;
+
+// Sometimes, however, you don't yet know all the types that you want
+// to test when you write the tests.  For example, if you are the
+// author of an interface and expect other people to implement it, you
+// might want to write a set of tests to make sure each implementation
+// conforms to some basic requirements, but you don't know what
+// implementations will be written in the future.
+//
+// How can you write the tests without committing to the type
+// parameters?  That's what "type-parameterized tests" can do for you.
+// It is a bit more involved than typed tests, but in return you get a
+// test pattern that can be reused in many contexts, which is a big
+// win.  Here's how you do it:
+
+// First, define a test fixture class template.  Here we just reuse
+// the PrimeTableTest fixture defined earlier:
+
+template <class T>
+class PrimeTableTest2 : public PrimeTableTest<T> {};
+
+// Then, declare the test case.  The argument is the name of the test
+// fixture, and also the name of the test case (as usual).  The _P
+// suffix is for "parameterized" or "pattern".
+TYPED_TEST_SUITE_P(PrimeTableTest2);
+
+// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
+// similar to what you do with TEST_F.
+TYPED_TEST_P(PrimeTableTest2, ReturnsFalseForNonPrimes) {
+  EXPECT_FALSE(this->table_->IsPrime(-5));
+  EXPECT_FALSE(this->table_->IsPrime(0));
+  EXPECT_FALSE(this->table_->IsPrime(1));
+  EXPECT_FALSE(this->table_->IsPrime(4));
+  EXPECT_FALSE(this->table_->IsPrime(6));
+  EXPECT_FALSE(this->table_->IsPrime(100));
+}
+
+TYPED_TEST_P(PrimeTableTest2, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(this->table_->IsPrime(2));
+  EXPECT_TRUE(this->table_->IsPrime(3));
+  EXPECT_TRUE(this->table_->IsPrime(5));
+  EXPECT_TRUE(this->table_->IsPrime(7));
+  EXPECT_TRUE(this->table_->IsPrime(11));
+  EXPECT_TRUE(this->table_->IsPrime(131));
+}
+
+TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) {
+  EXPECT_EQ(2, this->table_->GetNextPrime(0));
+  EXPECT_EQ(3, this->table_->GetNextPrime(2));
+  EXPECT_EQ(5, this->table_->GetNextPrime(3));
+  EXPECT_EQ(7, this->table_->GetNextPrime(5));
+  EXPECT_EQ(11, this->table_->GetNextPrime(7));
+  EXPECT_EQ(131, this->table_->GetNextPrime(128));
+}
+
+// Type-parameterized tests involve one extra step: you have to
+// enumerate the tests you defined:
+REGISTER_TYPED_TEST_SUITE_P(
+    PrimeTableTest2,  // The first argument is the test case name.
+    // The rest of the arguments are the test names.
+    ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
+
+// At this point the test pattern is done.  However, you don't have
+// any real test yet as you haven't said which types you want to run
+// the tests with.
+
+// To turn the abstract test pattern into real tests, you instantiate
+// it with a list of types.  Usually the test pattern will be defined
+// in a .h file, and anyone can #include and instantiate it.  You can
+// even instantiate it more than once in the same program.  To tell
+// different instances apart, you give each of them a name, which will
+// become part of the test case name and can be used in test filters.
+
+// The list of types we want to test.  Note that it doesn't have to be
+// defined at the time we write the TYPED_TEST_P()s.
+typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
+    PrimeTableImplementations;
+INSTANTIATE_TYPED_TEST_SUITE_P(OnTheFlyAndPreCalculated,    // Instance name
+                               PrimeTableTest2,             // Test case name
+                               PrimeTableImplementations);  // Type list
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/samples/sample7_unittest.cc b/3rd-party/googletest/googletest/samples/sample7_unittest.cc
new file mode 100644
index 0000000..3ad22ca
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample7_unittest.cc
@@ -0,0 +1,113 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This sample shows how to test common properties of multiple
+// implementations of an interface (aka interface tests) using
+// value-parameterized tests. Each test in the test case has
+// a parameter that is an interface pointer to an implementation
+// tested.
+
+// The interface and its implementations are in this header.
+#include "prime_tables.h"
+#include "gtest/gtest.h"
+namespace {
+
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+// As a general rule, to prevent a test from affecting the tests that come
+// after it, you should create and destroy the tested objects for each test
+// instead of reusing them.  In this sample we will define a simple factory
+// function for PrimeTable objects.  We will instantiate objects in test's
+// SetUp() method and delete them in TearDown() method.
+typedef PrimeTable* CreatePrimeTableFunc();
+
+PrimeTable* CreateOnTheFlyPrimeTable() { return new OnTheFlyPrimeTable(); }
+
+template <size_t max_precalculated>
+PrimeTable* CreatePreCalculatedPrimeTable() {
+  return new PreCalculatedPrimeTable(max_precalculated);
+}
+
+// Inside the test body, fixture constructor, SetUp(), and TearDown() you
+// can refer to the test parameter by GetParam().  In this case, the test
+// parameter is a factory function which we call in fixture's SetUp() to
+// create and store an instance of PrimeTable.
+class PrimeTableTestSmpl7 : public TestWithParam<CreatePrimeTableFunc*> {
+ public:
+  ~PrimeTableTestSmpl7() override { delete table_; }
+  void SetUp() override { table_ = (*GetParam())(); }
+  void TearDown() override {
+    delete table_;
+    table_ = nullptr;
+  }
+
+ protected:
+  PrimeTable* table_;
+};
+
+TEST_P(PrimeTableTestSmpl7, ReturnsFalseForNonPrimes) {
+  EXPECT_FALSE(table_->IsPrime(-5));
+  EXPECT_FALSE(table_->IsPrime(0));
+  EXPECT_FALSE(table_->IsPrime(1));
+  EXPECT_FALSE(table_->IsPrime(4));
+  EXPECT_FALSE(table_->IsPrime(6));
+  EXPECT_FALSE(table_->IsPrime(100));
+}
+
+TEST_P(PrimeTableTestSmpl7, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(table_->IsPrime(2));
+  EXPECT_TRUE(table_->IsPrime(3));
+  EXPECT_TRUE(table_->IsPrime(5));
+  EXPECT_TRUE(table_->IsPrime(7));
+  EXPECT_TRUE(table_->IsPrime(11));
+  EXPECT_TRUE(table_->IsPrime(131));
+}
+
+TEST_P(PrimeTableTestSmpl7, CanGetNextPrime) {
+  EXPECT_EQ(2, table_->GetNextPrime(0));
+  EXPECT_EQ(3, table_->GetNextPrime(2));
+  EXPECT_EQ(5, table_->GetNextPrime(3));
+  EXPECT_EQ(7, table_->GetNextPrime(5));
+  EXPECT_EQ(11, table_->GetNextPrime(7));
+  EXPECT_EQ(131, table_->GetNextPrime(128));
+}
+
+// In order to run value-parameterized tests, you need to instantiate them,
+// or bind them to a list of values which will be used as test parameters.
+// You can instantiate them in a different translation module, or even
+// instantiate them several times.
+//
+// Here, we instantiate our tests with a list of two PrimeTable object
+// factory functions:
+INSTANTIATE_TEST_SUITE_P(OnTheFlyAndPreCalculated, PrimeTableTestSmpl7,
+                         Values(&CreateOnTheFlyPrimeTable,
+                                &CreatePreCalculatedPrimeTable<1000>));
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/samples/sample8_unittest.cc b/3rd-party/googletest/googletest/samples/sample8_unittest.cc
new file mode 100644
index 0000000..4df81df
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample8_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This sample shows how to test code relying on some global flag variables.
+// Combine() helps with generating all possible combinations of such flags,
+// and each test is given one combination as a parameter.
+
+// Use class definitions to test from this header.
+#include <tuple>
+
+#include "prime_tables.h"
+#include "gtest/gtest.h"
+namespace {
+
+// Suppose we want to introduce a new, improved implementation of PrimeTable
+// which combines speed of PrecalcPrimeTable and versatility of
+// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
+// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
+// appropriate under the circumstances. But in low memory conditions, it can be
+// told to instantiate without PrecalcPrimeTable instance at all and use only
+// OnTheFlyPrimeTable.
+class HybridPrimeTable : public PrimeTable {
+ public:
+  HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
+      : on_the_fly_impl_(new OnTheFlyPrimeTable),
+        precalc_impl_(force_on_the_fly
+                          ? nullptr
+                          : new PreCalculatedPrimeTable(max_precalculated)),
+        max_precalculated_(max_precalculated) {}
+  ~HybridPrimeTable() override {
+    delete on_the_fly_impl_;
+    delete precalc_impl_;
+  }
+
+  bool IsPrime(int n) const override {
+    if (precalc_impl_ != nullptr && n < max_precalculated_)
+      return precalc_impl_->IsPrime(n);
+    else
+      return on_the_fly_impl_->IsPrime(n);
+  }
+
+  int GetNextPrime(int p) const override {
+    int next_prime = -1;
+    if (precalc_impl_ != nullptr && p < max_precalculated_)
+      next_prime = precalc_impl_->GetNextPrime(p);
+
+    return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
+  }
+
+ private:
+  OnTheFlyPrimeTable* on_the_fly_impl_;
+  PreCalculatedPrimeTable* precalc_impl_;
+  int max_precalculated_;
+};
+
+using ::testing::Bool;
+using ::testing::Combine;
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+// To test all code paths for HybridPrimeTable we must test it with numbers
+// both within and outside PreCalculatedPrimeTable's capacity and also with
+// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
+// accept different combinations of parameters for instantiating a
+// HybridPrimeTable instance.
+class PrimeTableTest : public TestWithParam< ::std::tuple<bool, int> > {
+ protected:
+  void SetUp() override {
+    bool force_on_the_fly;
+    int max_precalculated;
+    std::tie(force_on_the_fly, max_precalculated) = GetParam();
+    table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
+  }
+  void TearDown() override {
+    delete table_;
+    table_ = nullptr;
+  }
+  HybridPrimeTable* table_;
+};
+
+TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  // Inside the test body, you can refer to the test parameter by GetParam().
+  // In this case, the test parameter is a PrimeTable interface pointer which
+  // we can use directly.
+  // Please note that you can also save it in the fixture's SetUp() method
+  // or constructor and use saved copy in the tests.
+
+  EXPECT_FALSE(table_->IsPrime(-5));
+  EXPECT_FALSE(table_->IsPrime(0));
+  EXPECT_FALSE(table_->IsPrime(1));
+  EXPECT_FALSE(table_->IsPrime(4));
+  EXPECT_FALSE(table_->IsPrime(6));
+  EXPECT_FALSE(table_->IsPrime(100));
+}
+
+TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(table_->IsPrime(2));
+  EXPECT_TRUE(table_->IsPrime(3));
+  EXPECT_TRUE(table_->IsPrime(5));
+  EXPECT_TRUE(table_->IsPrime(7));
+  EXPECT_TRUE(table_->IsPrime(11));
+  EXPECT_TRUE(table_->IsPrime(131));
+}
+
+TEST_P(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, table_->GetNextPrime(0));
+  EXPECT_EQ(3, table_->GetNextPrime(2));
+  EXPECT_EQ(5, table_->GetNextPrime(3));
+  EXPECT_EQ(7, table_->GetNextPrime(5));
+  EXPECT_EQ(11, table_->GetNextPrime(7));
+  EXPECT_EQ(131, table_->GetNextPrime(128));
+}
+
+// In order to run value-parameterized tests, you need to instantiate them,
+// or bind them to a list of values which will be used as test parameters.
+// You can instantiate them in a different translation module, or even
+// instantiate them several times.
+//
+// Here, we instantiate our tests with a list of parameters. We must combine
+// all variations of the boolean flag suppressing PrecalcPrimeTable and some
+// meaningful values for tests. We choose a small value (1), and a value that
+// will put some of the tested numbers beyond the capability of the
+// PrecalcPrimeTable instance and some inside it (10). Combine will produce all
+// possible combinations.
+INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, PrimeTableTest,
+                         Combine(Bool(), Values(1, 10)));
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/samples/sample9_unittest.cc b/3rd-party/googletest/googletest/samples/sample9_unittest.cc
new file mode 100644
index 0000000..0a2f097
--- /dev/null
+++ b/3rd-party/googletest/googletest/samples/sample9_unittest.cc
@@ -0,0 +1,148 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This sample shows how to use Google Test listener API to implement
+// an alternative console output and how to use the UnitTest reflection API
+// to enumerate test suites and tests and to inspect their results.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+namespace {
+// Provides alternative output mode which produces minimal amount of
+// information about tests.
+class TersePrinter : public EmptyTestEventListener {
+ private:
+  // Called before any test activity starts.
+  void OnTestProgramStart(const UnitTest& /* unit_test */) override {}
+
+  // Called after all test activities have ended.
+  void OnTestProgramEnd(const UnitTest& unit_test) override {
+    fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED");
+    fflush(stdout);
+  }
+
+  // Called before a test starts.
+  void OnTestStart(const TestInfo& test_info) override {
+    fprintf(stdout, "*** Test %s.%s starting.\n", test_info.test_suite_name(),
+            test_info.name());
+    fflush(stdout);
+  }
+
+  // Called after a failed assertion or a SUCCEED() invocation.
+  void OnTestPartResult(const TestPartResult& test_part_result) override {
+    fprintf(stdout, "%s in %s:%d\n%s\n",
+            test_part_result.failed() ? "*** Failure" : "Success",
+            test_part_result.file_name(), test_part_result.line_number(),
+            test_part_result.summary());
+    fflush(stdout);
+  }
+
+  // Called after a test ends.
+  void OnTestEnd(const TestInfo& test_info) override {
+    fprintf(stdout, "*** Test %s.%s ending.\n", test_info.test_suite_name(),
+            test_info.name());
+    fflush(stdout);
+  }
+};  // class TersePrinter
+
+TEST(CustomOutputTest, PrintsMessage) {
+  printf("Printing something from the test body...\n");
+}
+
+TEST(CustomOutputTest, Succeeds) {
+  SUCCEED() << "SUCCEED() has been invoked from here";
+}
+
+TEST(CustomOutputTest, Fails) {
+  EXPECT_EQ(1, 2)
+      << "This test fails in order to demonstrate alternative failure messages";
+}
+}  // namespace
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  bool terse_output = false;
+  if (argc > 1 && strcmp(argv[1], "--terse_output") == 0)
+    terse_output = true;
+  else
+    printf("%s\n",
+           "Run this program with --terse_output to change the way "
+           "it prints its output.");
+
+  UnitTest& unit_test = *UnitTest::GetInstance();
+
+  // If we are given the --terse_output command line flag, suppresses the
+  // standard output and attaches own result printer.
+  if (terse_output) {
+    TestEventListeners& listeners = unit_test.listeners();
+
+    // Removes the default console output listener from the list so it will
+    // not receive events from Google Test and won't print any output. Since
+    // this operation transfers ownership of the listener to the caller we
+    // have to delete it as well.
+    delete listeners.Release(listeners.default_result_printer());
+
+    // Adds the custom output listener to the list. It will now receive
+    // events from Google Test and print the alternative output. We don't
+    // have to worry about deleting it since Google Test assumes ownership
+    // over it after adding it to the list.
+    listeners.Append(new TersePrinter);
+  }
+  int ret_val = RUN_ALL_TESTS();
+
+  // This is an example of using the UnitTest reflection API to inspect test
+  // results. Here we discount failures from the tests we expected to fail.
+  int unexpectedly_failed_tests = 0;
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const testing::TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    for (int j = 0; j < test_suite.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_suite.GetTestInfo(j);
+      // Counts failed tests that were not meant to fail (those without
+      // 'Fails' in the name).
+      if (test_info.result()->Failed() &&
+          strcmp(test_info.name(), "Fails") != 0) {
+        unexpectedly_failed_tests++;
+      }
+    }
+  }
+
+  // Test that were meant to fail should not affect the test program outcome.
+  if (unexpectedly_failed_tests == 0) ret_val = 0;
+
+  return ret_val;
+}
diff --git a/3rd-party/googletest/googletest/src/gtest-all.cc b/3rd-party/googletest/googletest/src/gtest-all.cc
new file mode 100644
index 0000000..2a70ed8
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-all.cc
@@ -0,0 +1,49 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Google C++ Testing and Mocking Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest-assertion-result.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-matchers.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
+#include "src/gtest.cc"
diff --git a/3rd-party/googletest/googletest/src/gtest-assertion-result.cc b/3rd-party/googletest/googletest/src/gtest-assertion-result.cc
new file mode 100644
index 0000000..3998921
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-assertion-result.cc
@@ -0,0 +1,77 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file defines the AssertionResult type.
+
+#include "gtest/gtest-assertion-result.h"
+
+#include <string>
+#include <utility>
+
+#include "gtest/gtest-message.h"
+
+namespace testing {
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_ != nullptr
+                   ? new ::std::string(*other.message_)
+                   : static_cast< ::std::string*>(nullptr)) {}
+
+// Swaps two AssertionResults.
+void AssertionResult::swap(AssertionResult& other) {
+  using std::swap;
+  swap(success_, other.success_);
+  swap(message_, other.message_);
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_ != nullptr) negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() { return AssertionResult(true); }
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() { return AssertionResult(false); }
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest-death-test.cc b/3rd-party/googletest/googletest/src/gtest-death-test.cc
new file mode 100644
index 0000000..15472f1
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-death-test.cc
@@ -0,0 +1,1587 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+
+#include <stdlib.h>
+
+#include <functional>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gtest/internal/custom/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+#ifdef GTEST_OS_MAC
+#include <crt_externs.h>
+#endif  // GTEST_OS_MAC
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#ifdef GTEST_OS_LINUX
+#include <signal.h>
+#endif  // GTEST_OS_LINUX
+
+#include <stdarg.h>
+
+#ifdef GTEST_OS_WINDOWS
+#include <windows.h>
+#else
+#include <sys/mman.h>
+#include <sys/wait.h>
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef GTEST_OS_QNX
+#include <spawn.h>
+#endif  // GTEST_OS_QNX
+
+#ifdef GTEST_OS_FUCHSIA
+#include <lib/fdio/fd.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
+#include <lib/zx/channel.h>
+#include <lib/zx/port.h>
+#include <lib/zx/process.h>
+#include <lib/zx/socket.h>
+#include <zircon/processargs.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/policy.h>
+#include <zircon/syscalls/port.h>
+#endif  // GTEST_OS_FUCHSIA
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+#include "src/gtest-internal-inl.h"
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+//
+// This is defined in internal/gtest-port.h as "fast", but can be overridden by
+// a definition in internal/custom/gtest-port.h. The recommended value, which is
+// used internally at Google, is "threadsafe".
+static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
+
+}  // namespace testing
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    testing::internal::StringFromGTestEnv("death_test_style",
+                                          testing::kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    testing::internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_Exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "the '|' characters.  This flag is specified if and only if the "
+    "current process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+
+namespace testing {
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Valid only for fast death tests. Indicates the code is running in the
+// child process of a fast style death test.
+#if !defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_FUCHSIA)
+static bool g_in_fast_death_test_child = false;
+#endif
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+bool InDeathTestChild() {
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_FUCHSIA)
+
+  // On Windows and Fuchsia, death tests are thread-safe regardless of the value
+  // of the death_test_style flag.
+  return !GTEST_FLAG_GET(internal_run_death_test).empty();
+
+#else
+
+  if (GTEST_FLAG_GET(death_test_style) == "threadsafe")
+    return !GTEST_FLAG_GET(internal_run_death_test).empty();
+  else
+    return g_in_fast_death_test_child;
+#endif
+}
+
+}  // namespace internal
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_FUCHSIA)
+
+  return exit_status == exit_code_;
+
+#else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+#endif  // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+}
+
+#if !defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_FUCHSIA)
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+#if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
+  {
+    bool result;
+    if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
+      return result;
+    }
+  }
+#endif  // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+#endif  // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static std::string ExitSummary(int exit_code) {
+  Message m;
+
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_FUCHSIA)
+
+  m << "Exited with exit status " << exit_code;
+
+#else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#endif
+#endif  // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+#if !defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_FUCHSIA)
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static std::string DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0) {
+    msg << "couldn't detect the number of threads.";
+  } else {
+    msg << "detected " << thread_count << " threads.";
+  }
+  msg << " See "
+         "https://github.com/google/googletest/blob/main/docs/"
+         "advanced.md#death-tests-and-threads"
+      << " for more explanation and suggested solutions, especially if"
+      << " this is the last message you see before your test times out.";
+  return msg.GetString();
+}
+#endif  // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+#ifdef GTEST_OS_FUCHSIA
+
+// File descriptor used for the pipe in the child process.
+static const int kFuchsiaReadPipeFd = 3;
+
+#endif
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+[[noreturn]] static void DeathTestAbort(const std::string& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != nullptr) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _Exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+#define GTEST_DEATH_TEST_CHECK_(expression)                              \
+  do {                                                                   \
+    if (!::testing::internal::IsTrue(expression)) {                      \
+      DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ +   \
+                     ", line " +                                         \
+                     ::testing::internal::StreamableToString(__LINE__) + \
+                     ": " + #expression);                                \
+    }                                                                    \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression)                      \
+  do {                                                                   \
+    int gtest_retval;                                                    \
+    do {                                                                 \
+      gtest_retval = (expression);                                       \
+    } while (gtest_retval == -1 && errno == EINTR);                      \
+    if (gtest_retval == -1) {                                            \
+      DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ +   \
+                     ", line " +                                         \
+                     ::testing::internal::StreamableToString(__LINE__) + \
+                     ": " + #expression + " != -1");                     \
+    }                                                                    \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+std::string GetLastErrnoDescription() {
+  return errno == 0 ? "" : posix::StrError(errno);
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == nullptr) {
+    DeathTestAbort(
+        "Cannot run a death test outside of a TEST or "
+        "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement,
+                       Matcher<const std::string&> matcher, const char* file,
+                       int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, std::move(matcher), file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const std::string& message) {
+  last_death_test_message_ = message;
+}
+
+std::string DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
+      : statement_(a_statement),
+        matcher_(std::move(matcher)),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason) override;
+  bool Passed(bool status_ok) override;
+
+  const char* statement() const { return statement_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+  // Returns stderr output from the child process.
+  virtual std::string GetErrorLogs();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // A matcher that's expected to match the stderr output by the child process.
+  Matcher<const std::string&> matcher_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+std::string DeathTestImpl::GetErrorLogs() { return GetCapturedStderr(); }
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _Exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch = reason == TEST_DID_NOT_DIE       ? kDeathTestLived
+                         : reason == TEST_THREW_EXCEPTION ? kDeathTestThrew
+                                                          : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _Exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _Exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0;;) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   matcher_: A matcher that's expected to match the stderr output by the child
+//             process.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true if and only if all of the above conditions are met.  Otherwise,
+// the first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned()) return false;
+
+  const std::string error_message = GetErrorLogs();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n"
+             << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n"
+             << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n"
+             << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        if (matcher_.Matches(error_message)) {
+          success = true;
+        } else {
+          std::ostringstream stream;
+          matcher_.DescribeTo(&stream);
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << stream.str() << "\n"
+                 << "Actual msg:\n"
+                 << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n"
+               << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+#ifndef GTEST_OS_WINDOWS
+// Note: The return value points into args, so the return value's lifetime is
+// bound to that of args.
+static std::vector<char*> CreateArgvFromArgs(std::vector<std::string>& args) {
+  std::vector<char*> result;
+  result.reserve(args.size() + 1);
+  for (auto& arg : args) {
+    result.push_back(&arg[0]);
+  }
+  result.push_back(nullptr);  // Extra null terminator.
+  return result;
+}
+#endif
+
+#ifdef GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
+                   const char* file, int line)
+      : DeathTestImpl(a_statement, std::move(matcher)),
+        file_(file),
+        line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned()) return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = {child_handle_.Get(), event_handle_.Get()};
+  switch (::WaitForMultipleObjects(2, wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(WAIT_OBJECT_0 ==
+                          ::WaitForSingleObject(child_handle_.Get(), INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != nullptr) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
+                                                 nullptr, TRUE};
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(::CreatePipe(&read_handle, &write_handle,
+                                       &handles_are_inheritable,
+                                       0)  // Default buffer size.
+                          != FALSE);
+  set_read_fd(
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,       // The event will automatically reset to non-signaled state.
+      FALSE,      // The initial state is non-signalled.
+      nullptr));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
+  const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                  "filter=" + info->test_suite_name() + "." +
+                                  info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ +
+      "internal_run_death_test=" + file_ + "|" + StreamableToString(line_) +
+      "|" + StreamableToString(death_test_index) + "|" +
+      StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
+      // size_t has the same width as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" +
+      StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
+                                                                executable_path,
+                                                                _MAX_PATH));
+
+  std::string command_line = std::string(::GetCommandLineA()) + " " +
+                             filter_flag + " \"" + internal_flag + "\"";
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreateProcessA(
+          executable_path, const_cast<char*>(command_line.c_str()),
+          nullptr,  // Returned process handle is not inheritable.
+          nullptr,  // Returned thread handle is not inheritable.
+          TRUE,  // Child inherits all inheritable handles (for write_handle_).
+          0x0,   // Default creation flags.
+          nullptr,  // Inherit the parent's environment.
+          UnitTest::GetInstance()->original_working_dir(), &startup_info,
+          &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+#elif defined(GTEST_OS_FUCHSIA)
+
+class FuchsiaDeathTest : public DeathTestImpl {
+ public:
+  FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
+                   const char* file, int line)
+      : DeathTestImpl(a_statement, std::move(matcher)),
+        file_(file),
+        line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  int Wait() override;
+  TestRole AssumeRole() override;
+  std::string GetErrorLogs() override;
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // The stderr data captured by the child process.
+  std::string captured_stderr_;
+
+  zx::process child_process_;
+  zx::channel exception_channel_;
+  zx::socket stderr_socket_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int FuchsiaDeathTest::Wait() {
+  const int kProcessKey = 0;
+  const int kSocketKey = 1;
+  const int kExceptionKey = 2;
+
+  if (!spawned()) return 0;
+
+  // Create a port to wait for socket/task/exception events.
+  zx_status_t status_zx;
+  zx::port port;
+  status_zx = zx::port::create(0, &port);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  // Register to wait for the child process to terminate.
+  status_zx =
+      child_process_.wait_async(port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  // Register to wait for the socket to be readable or closed.
+  status_zx = stderr_socket_.wait_async(
+      port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  // Register to wait for an exception.
+  status_zx = exception_channel_.wait_async(port, kExceptionKey,
+                                            ZX_CHANNEL_READABLE, 0);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  bool process_terminated = false;
+  bool socket_closed = false;
+  do {
+    zx_port_packet_t packet = {};
+    status_zx = port.wait(zx::time::infinite(), &packet);
+    GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+    if (packet.key == kExceptionKey) {
+      // Process encountered an exception. Kill it directly rather than
+      // letting other handlers process the event. We will get a kProcessKey
+      // event when the process actually terminates.
+      status_zx = child_process_.kill();
+      GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+    } else if (packet.key == kProcessKey) {
+      // Process terminated.
+      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
+      GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
+      process_terminated = true;
+    } else if (packet.key == kSocketKey) {
+      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
+      if (packet.signal.observed & ZX_SOCKET_READABLE) {
+        // Read data from the socket.
+        constexpr size_t kBufferSize = 1024;
+        do {
+          size_t old_length = captured_stderr_.length();
+          size_t bytes_read = 0;
+          captured_stderr_.resize(old_length + kBufferSize);
+          status_zx =
+              stderr_socket_.read(0, &captured_stderr_.front() + old_length,
+                                  kBufferSize, &bytes_read);
+          captured_stderr_.resize(old_length + bytes_read);
+        } while (status_zx == ZX_OK);
+        if (status_zx == ZX_ERR_PEER_CLOSED) {
+          socket_closed = true;
+        } else {
+          GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
+          status_zx = stderr_socket_.wait_async(
+              port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
+          GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+        }
+      } else {
+        GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
+        socket_closed = true;
+      }
+    }
+  } while (!process_terminated && !socket_closed);
+
+  ReadAndInterpretStatusByte();
+
+  zx_info_process_t buffer;
+  status_zx = child_process_.get_info(ZX_INFO_PROCESS, &buffer, sizeof(buffer),
+                                      nullptr, nullptr);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  GTEST_DEATH_TEST_CHECK_(buffer.flags & ZX_INFO_PROCESS_FLAG_EXITED);
+  set_status(static_cast<int>(buffer.return_code));
+  return status();
+}
+
+// The AssumeRole process for a Fuchsia death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != nullptr) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(kFuchsiaReadPipeFd);
+    return EXECUTE_TEST;
+  }
+
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // Build the child process command line.
+  const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                  "filter=" + info->test_suite_name() + "." +
+                                  info->name();
+  const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                    kInternalRunDeathTestFlag + "=" + file_ +
+                                    "|" + StreamableToString(line_) + "|" +
+                                    StreamableToString(death_test_index);
+
+  std::vector<std::string> args = GetInjectableArgvs();
+  args.push_back(filter_flag);
+  args.push_back(internal_flag);
+
+  // Build the pipe for communication with the child.
+  zx_status_t status;
+  zx_handle_t child_pipe_handle;
+  int child_pipe_fd;
+  status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+  set_read_fd(child_pipe_fd);
+
+  // Set the pipe handle for the child.
+  fdio_spawn_action_t spawn_actions[2] = {};
+  fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
+  add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
+  add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
+  add_handle_action->h.handle = child_pipe_handle;
+
+  // Create a socket pair will be used to receive the child process' stderr.
+  zx::socket stderr_producer_socket;
+  status = zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
+  GTEST_DEATH_TEST_CHECK_(status >= 0);
+  int stderr_producer_fd = -1;
+  status =
+      fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
+  GTEST_DEATH_TEST_CHECK_(status >= 0);
+
+  // Make the stderr socket nonblocking.
+  GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
+
+  fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
+  add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
+  add_stderr_action->fd.local_fd = stderr_producer_fd;
+  add_stderr_action->fd.target_fd = STDERR_FILENO;
+
+  // Create a child job.
+  zx_handle_t child_job = ZX_HANDLE_INVALID;
+  status = zx_job_create(zx_job_default(), 0, &child_job);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+  zx_policy_basic_t policy;
+  policy.condition = ZX_POL_NEW_ANY;
+  policy.policy = ZX_POL_ACTION_ALLOW;
+  status = zx_job_set_policy(child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC,
+                             &policy, 1);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+
+  // Create an exception channel attached to the |child_job|, to allow
+  // us to suppress the system default exception handler from firing.
+  status = zx_task_create_exception_channel(
+      child_job, 0, exception_channel_.reset_and_get_address());
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+
+  // Spawn the child process.
+  // Note: The test component must have `fuchsia.process.Launcher` declared
+  // in its manifest. (Fuchsia integration tests require creating a
+  // "Fuchsia Test Component" which contains a "Fuchsia Component Manifest")
+  // Launching processes is a privileged operation in Fuchsia, and the
+  // declaration indicates that the ability is required for the component.
+  std::vector<char*> argv = CreateArgvFromArgs(args);
+  status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.data(),
+                          nullptr, 2, spawn_actions,
+                          child_process_.reset_and_get_address(), nullptr);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+std::string FuchsiaDeathTest::GetErrorLogs() { return captured_stderr_; }
+
+#else  // We are neither on Windows, nor on Fuchsia.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
+
+  // All of these virtual functions are inherited from DeathTest.
+  int Wait() override;
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement,
+                                   Matcher<const std::string&> matcher)
+    : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned()) return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
+      : ForkingDeathTest(a_statement, std::move(matcher)) {}
+  TestRole AssumeRole() override;
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding(true);
+    g_in_fast_death_test_child = true;
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
+                const char* file, int line)
+      : ForkingDeathTest(a_statement, std::move(matcher)),
+        file_(file),
+        line_(line) {}
+  TestRole AssumeRole() override;
+
+ private:
+  static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
+    ::std::vector<std::string> args = GetInjectableArgvs();
+#if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
+    ::std::vector<std::string> extra_args =
+        GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
+    args.insert(args.end(), extra_args.begin(), extra_args.end());
+#endif  // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
+    return args;
+  }
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#ifdef GTEST_OS_QNX
+extern "C" char** environ;
+#else   // GTEST_OS_QNX
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir +
+                   "\") failed: " + GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execv() as it's almost a direct system call. We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execv() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execv(args->argv[0], args->argv);
+  DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
+                 original_dir + " failed: " + GetLastErrnoDescription());
+  return EXIT_FAILURE;
+}
+#endif  // GTEST_OS_QNX
+
+#if GTEST_HAS_CLONE
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+static void StackLowerThanAddress(const void* ptr,
+                                  bool* result) GTEST_NO_INLINE_;
+// Make sure sanitizers do not tamper with the stack here.
+// Ideally, we want to use `__builtin_frame_address` instead of a local variable
+// address with sanitizer disabled, but it does not work when the
+// compiler optimizes the stack frame out, which happens on PowerPC targets.
+// HWAddressSanitizer add a random tag to the MSB of the local variable address,
+// making comparison result unpredictable.
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+static void StackLowerThanAddress(const void* ptr, bool* result) {
+  int dummy = 0;
+  *result = std::less<const void*>()(&dummy, ptr);
+}
+
+// Make sure AddressSanitizer does not tamper with the stack here.
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+static bool StackGrowsDown() {
+  int dummy = 0;
+  bool result;
+  StackLowerThanAddress(&dummy, &result);
+  return result;
+}
+#endif  // GTEST_HAS_CLONE
+
+// Spawns a child process with the same executable as the current process in
+// a thread-safe manner and instructs it to run the death test.  The
+// implementation uses fork(2) + exec.  On systems where clone(2) is
+// available, it is used instead, being slightly more thread-safe.  On QNX,
+// fork supports only single-threaded environments, so this function uses
+// spawn(2) there instead.  The function dies with an error message if
+// anything goes wrong.
+static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = {argv, close_fd};
+  pid_t child_pid = -1;
+
+#ifdef GTEST_OS_QNX
+  // Obtains the current directory and sets it to be closed in the child
+  // process.
+  const int cwd_fd = open(".", O_RDONLY);
+  GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir +
+                   "\") failed: " + GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  int fd_flags;
+  // Set close_fd to be closed after spawn.
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      fcntl(close_fd, F_SETFD, fd_flags | FD_CLOEXEC));
+  struct inheritance inherit = {0};
+  // spawn is a system call.
+  child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
+  // Restores the current working directory.
+  GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+
+#else  // GTEST_OS_QNX
+#ifdef GTEST_OS_LINUX
+  // When a SIGPROF signal is received while fork() or clone() are executing,
+  // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
+  // it after the call to fork()/clone() is complete.
+  struct sigaction saved_sigprof_action;
+  struct sigaction ignore_sigprof_action;
+  memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
+  sigemptyset(&ignore_sigprof_action.sa_mask);
+  ignore_sigprof_action.sa_handler = SIG_IGN;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      sigaction(SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG_GET(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const auto stack_size = static_cast<size_t>(getpagesize() * 2);
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+
+    // Maximum stack alignment in bytes:  For a downward-growing stack, this
+    // amount is subtracted from size of the stack space to get an address
+    // that is within the stack space and is aligned on all systems we care
+    // about.  As far as I know there is no ABI with stack alignment greater
+    // than 64.  We assume stack and stack_size already have alignment of
+    // kMaxStackAlignment.
+    const size_t kMaxStackAlignment = 64;
+    void* const stack_top =
+        static_cast<char*>(stack) +
+        (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
+    GTEST_DEATH_TEST_CHECK_(
+        static_cast<size_t>(stack_size) > kMaxStackAlignment &&
+        reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#else
+  const bool use_fork = true;
+#endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+    _Exit(ExecDeathTestChildMain(&args));
+  }
+#endif  // GTEST_OS_QNX
+#ifdef GTEST_OS_LINUX
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      sigaction(SIGPROF, &saved_sigprof_action, nullptr));
+#endif  // GTEST_OS_LINUX
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != nullptr) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                  "filter=" + info->test_suite_name() + "." +
+                                  info->name();
+  const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                    "internal_run_death_test=" + file_ + "|" +
+                                    StreamableToString(line_) + "|" +
+                                    StreamableToString(death_test_index) + "|" +
+                                    StreamableToString(pipe_fd[1]);
+  std::vector<std::string> args = GetArgvsForDeathTestChildProcess();
+  args.push_back(filter_flag);
+  args.push_back(internal_flag);
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  std::vector<char*> argv = CreateArgvFromArgs(args);
+  const pid_t child_pid = ExecDeathTestSpawnChild(argv.data(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+#endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement,
+                                     Matcher<const std::string&> matcher,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index =
+      impl->current_test_info()->increment_death_test_count();
+
+  if (flag != nullptr) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(
+          "Death test count (" + StreamableToString(death_test_index) +
+          ") somehow exceeded expected maximum (" +
+          StreamableToString(flag->index()) + ")");
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = nullptr;
+      return true;
+    }
+  }
+
+#ifdef GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG_GET(death_test_style) == "threadsafe" ||
+      GTEST_FLAG_GET(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, std::move(matcher), file, line);
+  }
+
+#elif defined(GTEST_OS_FUCHSIA)
+
+  if (GTEST_FLAG_GET(death_test_style) == "threadsafe" ||
+      GTEST_FLAG_GET(death_test_style) == "fast") {
+    *test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
+  }
+
+#else
+
+  if (GTEST_FLAG_GET(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, std::move(matcher), file, line);
+  } else if (GTEST_FLAG_GET(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, std::move(matcher));
+  }
+
+#endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message("Unknown death test style \"" +
+                                           GTEST_FLAG_GET(death_test_style) +
+                                           "\" encountered");
+    return false;
+  }
+
+  return true;
+}
+
+#ifdef GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+static int GetStatusFileDescriptor(unsigned int parent_process_id,
+                                   size_t write_handle_as_size_t,
+                                   size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                 FALSE,  // Non-inheritable.
+                                                 parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort("Unable to open parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle = reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle, 0x0, FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the event handle " +
+                   StreamableToString(event_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort("Unable to convert pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " to a file descriptor");
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+#endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG_GET(internal_run_death_test).empty()) return nullptr;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG_GET(internal_run_death_test), '|', &fields);
+  int write_fd = -1;
+
+#ifdef GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6 || !ParseNaturalNumber(fields[1], &line) ||
+      !ParseNaturalNumber(fields[2], &index) ||
+      !ParseNaturalNumber(fields[3], &parent_process_id) ||
+      !ParseNaturalNumber(fields[4], &write_handle_as_size_t) ||
+      !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG_GET(internal_run_death_test));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t,
+                                     event_handle_as_size_t);
+
+#elif defined(GTEST_OS_FUCHSIA)
+
+  if (fields.size() != 3 || !ParseNaturalNumber(fields[1], &line) ||
+      !ParseNaturalNumber(fields[2], &index)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG_GET(internal_run_death_test));
+  }
+
+#else
+
+  if (fields.size() != 4 || !ParseNaturalNumber(fields[1], &line) ||
+      !ParseNaturalNumber(fields[2], &index) ||
+      !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG_GET(internal_run_death_test));
+  }
+
+#endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest-filepath.cc b/3rd-party/googletest/googletest/src/gtest-filepath.cc
new file mode 100644
index 0000000..902d8c7
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-filepath.cc
@@ -0,0 +1,414 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/internal/gtest-filepath.h"
+
+#include <stdlib.h>
+
+#include <iterator>
+#include <string>
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+#include <windows.h>
+#elif defined(GTEST_OS_WINDOWS)
+#include <direct.h>
+#include <io.h>
+#else
+#include <limits.h>
+
+#include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif              // GTEST_OS_WINDOWS_MOBILE
+
+#include "gtest/internal/gtest-string.h"
+
+#ifdef GTEST_OS_WINDOWS
+#define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+#define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_HAS_FILE_SYSTEM
+
+namespace testing {
+namespace internal {
+
+#ifdef GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kAlternatePathSeparatorString[] = "/";
+#ifdef GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+#else
+const char kCurrentDirectoryString[] = ".\\";
+#endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_PHONE) || \
+    defined(GTEST_OS_WINDOWS_RT) || defined(GTEST_OS_ESP8266) ||           \
+    defined(GTEST_OS_ESP32) || defined(GTEST_OS_XTENSA) ||                 \
+    defined(GTEST_OS_QURT) || defined(GTEST_OS_NXP_QN9090) ||              \
+    defined(GTEST_OS_NRF52)
+  // These platforms do not have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif defined(GTEST_OS_WINDOWS)
+  char cwd[GTEST_PATH_MAX_ + 1] = {'\0'};
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = {'\0'};
+  char* result = getcwd(cwd, sizeof(cwd));
+#ifdef GTEST_OS_NACL
+  // getcwd will likely fail in NaCl due to the sandbox, so return something
+  // reasonable. The user may have provided a shim implementation for getcwd,
+  // however, so fallback only when failure is detected.
+  return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
+#endif  // GTEST_OS_NACL
+  return FilePath(result == nullptr ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  const std::string dot_extension = std::string(".") + extension;
+  if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
+    return FilePath(
+        pathname_.substr(0, pathname_.length() - dot_extension.length()));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurrence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != nullptr &&
+      (last_sep == nullptr || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+size_t FilePath::CalculateRootLength() const {
+  const auto& path = pathname_;
+  auto s = path.begin();
+  auto end = path.end();
+#ifdef GTEST_OS_WINDOWS
+  if (end - s >= 2 && s[1] == ':' && (end - s == 2 || IsPathSeparator(s[2])) &&
+      (('A' <= s[0] && s[0] <= 'Z') || ('a' <= s[0] && s[0] <= 'z'))) {
+    // A typical absolute path like "C:\Windows" or "D:"
+    s += 2;
+    if (s != end) {
+      ++s;
+    }
+  } else if (end - s >= 3 && IsPathSeparator(*s) && IsPathSeparator(*(s + 1)) &&
+             !IsPathSeparator(*(s + 2))) {
+    // Move past the "\\" prefix in a UNC path like "\\Server\Share\Folder"
+    s += 2;
+    // Skip 2 components and their following separators ("Server\" and "Share\")
+    for (int i = 0; i < 2; ++i) {
+      while (s != end) {
+        bool stop = IsPathSeparator(*s);
+        ++s;
+        if (stop) {
+          break;
+        }
+      }
+    }
+  } else if (s != end && IsPathSeparator(*s)) {
+    // A drive-rooted path like "\Windows"
+    ++s;
+  }
+#else
+  if (s != end && IsPathSeparator(*s)) {
+    ++s;
+  }
+#endif
+  return static_cast<size_t>(s - path.begin());
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(last_sep + 1) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  std::string dir;
+  if (last_sep) {
+    dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name, int number,
+                                const char* extension) {
+  std::string file;
+  if (number == 0) {
+    file = base_name.string() + "." + extension;
+  } else {
+    file =
+        base_name.string() + "_" + StreamableToString(number) + "." + extension;
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty()) return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(dir.string() + kPathSeparator + relative_path.string());
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#ifdef GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete[] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat{};
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#ifdef GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this
+                                         : RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete[] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat{};
+  result =
+      posix::Stat(path.c_str(), &file_stat) == 0 && posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive. UNC share roots are also included.)
+bool FilePath::IsRootDirectory() const {
+  size_t root_length = CalculateRootLength();
+  return root_length > 0 && root_length == pathname_.size() &&
+         IsPathSeparator(pathname_[root_length - 1]);
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const { return CalculateRootLength() > 0; }
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.empty() || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#ifdef GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
+  delete[] unicode;
+#elif defined(GTEST_OS_WINDOWS)
+  int result = _mkdir(pathname_.c_str());
+#elif defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) || \
+    defined(GTEST_OS_QURT) || defined(GTEST_OS_NXP_QN9090) ||  \
+    defined(GTEST_OS_NRF52)
+  // do nothing
+  int result = 0;
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory() ? FilePath(pathname_.substr(0, pathname_.length() - 1))
+                       : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// Note that "\\Host\Share" does not contain a redundancy on Windows!
+void FilePath::Normalize() {
+  auto out = pathname_.begin();
+
+  auto i = pathname_.cbegin();
+#ifdef GTEST_OS_WINDOWS
+  // UNC paths are treated specially
+  if (pathname_.end() - i >= 3 && IsPathSeparator(*i) &&
+      IsPathSeparator(*(i + 1)) && !IsPathSeparator(*(i + 2))) {
+    *(out++) = kPathSeparator;
+    *(out++) = kPathSeparator;
+  }
+#endif
+  while (i != pathname_.end()) {
+    const char character = *i;
+    if (!IsPathSeparator(character)) {
+      *(out++) = character;
+    } else if (out == pathname_.begin() || *std::prev(out) != kPathSeparator) {
+      *(out++) = kPathSeparator;
+    }
+    ++i;
+  }
+
+  pathname_.erase(out, pathname_.end());
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_HAS_FILE_SYSTEM
diff --git a/3rd-party/googletest/googletest/src/gtest-internal-inl.h b/3rd-party/googletest/googletest/src/gtest-internal-inl.h
new file mode 100644
index 0000000..cc6f004
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-internal-inl.h
@@ -0,0 +1,1230 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
+#define GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
+
+#ifndef _WIN32_WCE
+#include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_CAN_STREAM_RESULTS_
+#include <arpa/inet.h>  // NOLINT
+#include <netdb.h>      // NOLINT
+#endif
+
+#ifdef GTEST_OS_WINDOWS
+#include <windows.h>  // NOLINT
+#endif                // GTEST_OS_WINDOWS
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace testing {
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true if and only if the --help flag or an equivalent form
+// is specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true if and only if Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds. If the input is an exact N
+// seconds, the output has a trailing decimal point (e.g., "N." instead of "N").
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information.  N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe.  Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseFlag(const char* str, const char* flag, int32_t* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(int32_t random_seed_flag) {
+  const unsigned int raw_seed =
+      (random_seed_flag == 0) ? static_cast<unsigned int>(GetTimeInMillis())
+                              : static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) +
+      1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG_GET(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG_GET(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG_GET(catch_exceptions);
+    color_ = GTEST_FLAG_GET(color);
+    death_test_style_ = GTEST_FLAG_GET(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG_GET(death_test_use_fork);
+    fail_fast_ = GTEST_FLAG_GET(fail_fast);
+    filter_ = GTEST_FLAG_GET(filter);
+    internal_run_death_test_ = GTEST_FLAG_GET(internal_run_death_test);
+    list_tests_ = GTEST_FLAG_GET(list_tests);
+    output_ = GTEST_FLAG_GET(output);
+    brief_ = GTEST_FLAG_GET(brief);
+    print_time_ = GTEST_FLAG_GET(print_time);
+    print_utf8_ = GTEST_FLAG_GET(print_utf8);
+    random_seed_ = GTEST_FLAG_GET(random_seed);
+    repeat_ = GTEST_FLAG_GET(repeat);
+    recreate_environments_when_repeating_ =
+        GTEST_FLAG_GET(recreate_environments_when_repeating);
+    shuffle_ = GTEST_FLAG_GET(shuffle);
+    stack_trace_depth_ = GTEST_FLAG_GET(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG_GET(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG_GET(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG_SET(also_run_disabled_tests, also_run_disabled_tests_);
+    GTEST_FLAG_SET(break_on_failure, break_on_failure_);
+    GTEST_FLAG_SET(catch_exceptions, catch_exceptions_);
+    GTEST_FLAG_SET(color, color_);
+    GTEST_FLAG_SET(death_test_style, death_test_style_);
+    GTEST_FLAG_SET(death_test_use_fork, death_test_use_fork_);
+    GTEST_FLAG_SET(filter, filter_);
+    GTEST_FLAG_SET(fail_fast, fail_fast_);
+    GTEST_FLAG_SET(internal_run_death_test, internal_run_death_test_);
+    GTEST_FLAG_SET(list_tests, list_tests_);
+    GTEST_FLAG_SET(output, output_);
+    GTEST_FLAG_SET(brief, brief_);
+    GTEST_FLAG_SET(print_time, print_time_);
+    GTEST_FLAG_SET(print_utf8, print_utf8_);
+    GTEST_FLAG_SET(random_seed, random_seed_);
+    GTEST_FLAG_SET(repeat, repeat_);
+    GTEST_FLAG_SET(recreate_environments_when_repeating,
+                   recreate_environments_when_repeating_);
+    GTEST_FLAG_SET(shuffle, shuffle_);
+    GTEST_FLAG_SET(stack_trace_depth, stack_trace_depth_);
+    GTEST_FLAG_SET(stream_result_to, stream_result_to_);
+    GTEST_FLAG_SET(throw_on_failure, throw_on_failure_);
+  }
+
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  std::string color_;
+  std::string death_test_style_;
+  bool death_test_use_fork_;
+  bool fail_fast_;
+  std::string filter_;
+  std::string internal_run_death_test_;
+  bool list_tests_;
+  std::string output_;
+  bool brief_;
+  bool print_time_;
+  bool print_utf8_;
+  int32_t random_seed_;
+  int32_t repeat_;
+  bool recreate_environments_when_repeating_;
+  bool shuffle_;
+  int32_t stack_trace_depth_;
+  std::string stream_result_to_;
+  bool throw_on_failure_;
+};
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+GTEST_API_ std::string CodePointToUtf8(uint32_t code_point);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as a 32-bit integer. If it is unset,
+// returns default_val. If it is not a 32-bit integer, prints an error and
+// and aborts.
+GTEST_API_ int32_t Int32FromEnvOrDie(const char* env_var, int32_t default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true if and only if the test should be run on this shard. The test id
+// is some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(int total_shards, int shard_index,
+                                     int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (auto it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it)) ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value
+                                                    : v[static_cast<size_t>(i)];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // https://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected =
+        begin +
+        static_cast<int>(random->Generate(static_cast<uint32_t>(range_width)));
+    std::swap((*v)[static_cast<size_t>(selected)],
+              (*v)[static_cast<size_t>(last_in_range)]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
+
+  // Returns true if and only if the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return test_property.key() == key_;
+  }
+
+ private:
+  std::string key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static std::string GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static std::string GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true if and only if the user-specified filter matches the test
+  // suite name and the test name.
+  static bool FilterMatchesTest(const std::string& test_suite_name,
+                                const std::string& test_name);
+
+#ifdef GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if given SEH exception was handled, or
+  // EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestProcessSEH(DWORD seh_code, const char* location);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const std::string& name, const char* filter);
+};
+
+#if GTEST_HAS_FILE_SYSTEM
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() = default;
+  virtual ~OsStackTraceGetterInterface() = default;
+
+  // Returns the current OS stack trace as an std::string.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  OsStackTraceGetterInterface(const OsStackTraceGetterInterface&) = delete;
+  OsStackTraceGetterInterface& operator=(const OsStackTraceGetterInterface&) =
+      delete;
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() = default;
+
+  std::string CurrentStackTrace(int max_depth, int skip_count) override;
+  void UponLeavingGTest() override;
+
+ private:
+#ifdef GTEST_HAS_ABSL
+  Mutex mutex_;  // Protects all internal state.
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to the stack trace code from within the user code.
+  void* caller_frame_ = nullptr;
+#endif  // GTEST_HAS_ABSL
+
+  OsStackTraceGetter(const OsStackTraceGetter&) = delete;
+  OsStackTraceGetter& operator=(const OsStackTraceGetter&) = delete;
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  std::string message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  void ReportTestPartResult(const TestPartResult& result) override;
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  DefaultGlobalTestPartResultReporter(
+      const DefaultGlobalTestPartResultReporter&) = delete;
+  DefaultGlobalTestPartResultReporter& operator=(
+      const DefaultGlobalTestPartResultReporter&) = delete;
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  void ReportTestPartResult(const TestPartResult& result) override;
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  DefaultPerThreadTestPartResultReporter(
+      const DefaultPerThreadTestPartResultReporter&) = delete;
+  DefaultPerThreadTestPartResultReporter& operator=(
+      const DefaultPerThreadTestPartResultReporter&) = delete;
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own reporter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result reporter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test suites.
+  int successful_test_suite_count() const;
+
+  // Gets the number of failed test suites.
+  int failed_test_suite_count() const;
+
+  // Gets the number of all test suites.
+  int total_test_suite_count() const;
+
+  // Gets the number of all test suites that contain at least one test
+  // that should run.
+  int test_suite_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of skipped tests.
+  int skipped_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true if and only if the unit test passed (i.e. all test suites
+  // passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true if and only if the unit test failed (i.e. some test suite
+  // failed or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  const TestSuite* GetTestSuite(int i) const {
+    const int index = GetElementOr(test_suite_indices_, i, -1);
+    return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
+  }
+
+  //  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  TestSuite* GetMutableSuiteCase(int i) {
+    const int index = GetElementOr(test_suite_indices_, i, -1);
+    return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as an std::string.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  std::string CurrentOsStackTraceExceptTop(int skip_count)
+      GTEST_NO_INLINE_ GTEST_NO_TAIL_CALL_;
+
+  // Finds and returns a TestSuite with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_suite_name: name of the test suite
+  //   type_param:      the name of the test's type parameter, or NULL if
+  //                    this is not a typed or a type-parameterized test.
+  //   set_up_tc:       pointer to the function that sets up the test suite
+  //   tear_down_tc:    pointer to the function that tears down the test suite
+  TestSuite* GetTestSuite(const std::string& test_suite_name,
+                          const char* type_param,
+                          internal::SetUpTestSuiteFunc set_up_tc,
+                          internal::TearDownTestSuiteFunc tear_down_tc);
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  TestCase* GetTestCase(const std::string& test_case_name,
+                        const char* type_param,
+                        internal::SetUpTestSuiteFunc set_up_tc,
+                        internal::TearDownTestSuiteFunc tear_down_tc) {
+    return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
+  }
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test suite
+  //   tear_down_tc: pointer to the function that tears down the test suite
+  //   test_info:    the TestInfo object
+  void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
+                   internal::TearDownTestSuiteFunc tear_down_tc,
+                   TestInfo* test_info) {
+#if GTEST_HAS_FILE_SYSTEM
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_ = FilePath::GetCurrentDir();
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+    GetTestSuite(test_info->test_suite_name_, test_info->type_param(),
+                 set_up_tc, tear_down_tc)
+        ->AddTestInfo(test_info);
+  }
+
+  // Returns ParameterizedTestSuiteRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+
+  std::set<std::string>* ignored_parameterized_test_suites() {
+    return &ignored_parameterized_test_suites_;
+  }
+
+  // Returns TypeParameterizedTestSuiteRegistry object used to keep track of
+  // type-parameterized tests and instantiations of them.
+  internal::TypeParameterizedTestSuiteRegistry&
+  type_parameterized_test_registry() {
+    return type_parameterized_test_registry_;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_suites_, TestSuite::ClearTestSuiteResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() { ad_hoc_test_result_.Clear(); }
+
+  // Adds a TestProperty to the current TestResult object when invoked in a
+  // context of a test or a test suite, or to the global property set. If the
+  // result already contains a property with the same key, the value will be
+  // updated.
+  void RecordProperty(const TestProperty& test_property);
+
+  enum ReactionToSharding { HONOR_SHARDING_PROTOCOL, IGNORE_SHARDING_PROTOCOL };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestSuite and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestSuite* current_test_suite() const { return current_test_suite_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#ifdef GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test suites, and the tests within each test suite,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test suites and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  struct CompareTestSuitesByPointer {
+    bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
+      return lhs->name_ < rhs->name_;
+    }
+  };
+
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // Sets the TestSuite object for the test that's currently running.
+  void set_current_test_suite(TestSuite* a_current_test_suite) {
+    current_test_suite_ = a_current_test_suite;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+#if GTEST_HAS_FILE_SYSTEM
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_reporter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestSuites in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestSuite*> test_suites_;
+
+  // The set of TestSuites by name.
+  std::unordered_map<std::string, TestSuite*> test_suites_by_name_;
+
+  // Provides a level of indirection for the test suite list to allow
+  // easy shuffling and restoring the test suite order.  The i-th
+  // element of this vector is the index of the i-th test suite in the
+  // shuffled order.
+  std::vector<int> test_suite_indices_;
+
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
+  internal::TypeParameterizedTestSuiteRegistry
+      type_parameterized_test_registry_;
+
+  // The set holding the name of parameterized
+  // test suites that may go uninstantiated.
+  std::set<std::string> ignored_parameterized_test_suites_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+
+  // Index of the last death test suite registered.  Initially -1.
+  int last_death_test_suite_;
+
+  // This points to the TestSuite for the currently running test.  It
+  // changes as Google Test goes through one test suite after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestSuite* current_test_suite_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True if and only if PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // The time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#ifdef GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  std::unique_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  std::unique_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  UnitTestImpl(const UnitTestImpl&) = delete;
+  UnitTestImpl& operator=(const UnitTestImpl&) = delete;
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#ifdef GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(bool escaped, char ch,
+                                              char repeat, const char* regex,
+                                              const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ std::string GetLastErrnoDescription();
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+  using BiggestConvertible = unsigned long long;  // NOLINT
+
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);  // NOLINT
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const std::string& xml_element,
+                             const TestProperty& property) {
+    test_result->RecordProperty(xml_element, property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Abstract base class for writing strings to a socket.
+  class AbstractSocketWriter {
+   public:
+    virtual ~AbstractSocketWriter() = default;
+
+    // Sends a string to the socket.
+    virtual void Send(const std::string& message) = 0;
+
+    // Closes the socket.
+    virtual void CloseConnection() {}
+
+    // Sends a string and a newline to the socket.
+    void SendLn(const std::string& message) { Send(message + "\n"); }
+  };
+
+  // Concrete class for actually writing strings to a socket.
+  class SocketWriter : public AbstractSocketWriter {
+   public:
+    SocketWriter(const std::string& host, const std::string& port)
+        : sockfd_(-1), host_name_(host), port_num_(port) {
+      MakeConnection();
+    }
+
+    ~SocketWriter() override {
+      if (sockfd_ != -1) CloseConnection();
+    }
+
+    // Sends a string to the socket.
+    void Send(const std::string& message) override {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "Send() can be called only when there is a connection.";
+
+      const auto len = static_cast<size_t>(message.length());
+      if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
+        GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to "
+                            << host_name_ << ":" << port_num_;
+      }
+    }
+
+   private:
+    // Creates a client socket and connects to the server.
+    void MakeConnection();
+
+    // Closes the socket.
+    void CloseConnection() override {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "CloseConnection() can be called only when there is a connection.";
+
+      close(sockfd_);
+      sockfd_ = -1;
+    }
+
+    int sockfd_;  // socket file descriptor
+    const std::string host_name_;
+    const std::string port_num_;
+
+    SocketWriter(const SocketWriter&) = delete;
+    SocketWriter& operator=(const SocketWriter&) = delete;
+  };  // class SocketWriter
+
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static std::string UrlEncode(const char* str);
+
+  StreamingListener(const std::string& host, const std::string& port)
+      : socket_writer_(new SocketWriter(host, port)) {
+    Start();
+  }
+
+  explicit StreamingListener(AbstractSocketWriter* socket_writer)
+      : socket_writer_(socket_writer) {
+    Start();
+  }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) override {
+    SendLn("event=TestProgramStart");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) override {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    socket_writer_->CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */,
+                            int iteration) override {
+    SendLn("event=TestIterationStart&iteration=" +
+           StreamableToString(iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test,
+                          int /* iteration */) override {
+    SendLn("event=TestIterationEnd&passed=" + FormatBool(unit_test.Passed()) +
+           "&elapsed_time=" + StreamableToString(unit_test.elapsed_time()) +
+           "ms");
+  }
+
+  // Note that "event=TestCaseStart" is a wire format and has to remain
+  // "case" for compatibility
+  void OnTestSuiteStart(const TestSuite& test_suite) override {
+    SendLn(std::string("event=TestCaseStart&name=") + test_suite.name());
+  }
+
+  // Note that "event=TestCaseEnd" is a wire format and has to remain
+  // "case" for compatibility
+  void OnTestSuiteEnd(const TestSuite& test_suite) override {
+    SendLn("event=TestCaseEnd&passed=" + FormatBool(test_suite.Passed()) +
+           "&elapsed_time=" + StreamableToString(test_suite.elapsed_time()) +
+           "ms");
+  }
+
+  void OnTestStart(const TestInfo& test_info) override {
+    SendLn(std::string("event=TestStart&name=") + test_info.name());
+  }
+
+  void OnTestEnd(const TestInfo& test_info) override {
+    SendLn("event=TestEnd&passed=" +
+           FormatBool((test_info.result())->Passed()) + "&elapsed_time=" +
+           StreamableToString((test_info.result())->elapsed_time()) + "ms");
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) override {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == nullptr) file_name = "";
+    SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
+           "&line=" + StreamableToString(test_part_result.line_number()) +
+           "&message=" + UrlEncode(test_part_result.message()));
+  }
+
+ private:
+  // Sends the given message and a newline to the socket.
+  void SendLn(const std::string& message) { socket_writer_->SendLn(message); }
+
+  // Called at the start of streaming to notify the receiver what
+  // protocol we are using.
+  void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
+
+  std::string FormatBool(bool value) { return value ? "1" : "0"; }
+
+  const std::unique_ptr<AbstractSocketWriter> socket_writer_;
+
+  StreamingListener(const StreamingListener&) = delete;
+  StreamingListener& operator=(const StreamingListener&) = delete;
+};  // class StreamingListener
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+}  // namespace internal
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/3rd-party/googletest/googletest/src/gtest-matchers.cc b/3rd-party/googletest/googletest/src/gtest-matchers.cc
new file mode 100644
index 0000000..7e3bcc0
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-matchers.cc
@@ -0,0 +1,98 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file implements just enough of the matcher interface to allow
+// EXPECT_DEATH and friends to accept a matcher argument.
+
+#include "gtest/gtest-matchers.h"
+
+#include <string>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+// Constructs a matcher that matches a const std::string& whose value is
+// equal to s.
+Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a const std::string& whose value is
+// equal to s.
+Matcher<const std::string&>::Matcher(const char* s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a std::string whose value is equal to
+// s.
+Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a std::string whose value is equal to
+// s.
+Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// Constructs a matcher that matches a const StringView& whose value is
+// equal to s.
+Matcher<const internal::StringView&>::Matcher(const std::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a const StringView& whose value is
+// equal to s.
+Matcher<const internal::StringView&>::Matcher(const char* s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a const StringView& whose value is
+// equal to s.
+Matcher<const internal::StringView&>::Matcher(internal::StringView s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a StringView whose value is equal to
+// s.
+Matcher<internal::StringView>::Matcher(const std::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a StringView whose value is equal to
+// s.
+Matcher<internal::StringView>::Matcher(const char* s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a StringView whose value is equal to
+// s.
+Matcher<internal::StringView>::Matcher(internal::StringView s) {
+  *this = Eq(std::string(s));
+}
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest-port.cc b/3rd-party/googletest/googletest/src/gtest-port.cc
new file mode 100644
index 0000000..1038ad7
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-port.cc
@@ -0,0 +1,1434 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cstdint>
+#include <fstream>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#ifdef GTEST_OS_WINDOWS
+#include <io.h>
+#include <sys/stat.h>
+#include <windows.h>
+
+#include <map>  // Used in ThreadLocal.
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif  // _MSC_VER
+#else
+#include <unistd.h>
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef GTEST_OS_MAC
+#include <mach/mach_init.h>
+#include <mach/task.h>
+#include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#if defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) ||   \
+    defined(GTEST_OS_GNU_KFREEBSD) || defined(GTEST_OS_NETBSD) || \
+    defined(GTEST_OS_OPENBSD)
+#include <sys/sysctl.h>
+#if defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \
+    defined(GTEST_OS_GNU_KFREEBSD)
+#include <sys/user.h>
+#endif
+#endif
+
+#ifdef GTEST_OS_QNX
+#include <devctl.h>
+#include <fcntl.h>
+#include <sys/procfs.h>
+#endif  // GTEST_OS_QNX
+
+#ifdef GTEST_OS_AIX
+#include <procinfo.h>
+#include <sys/types.h>
+#endif  // GTEST_OS_AIX
+
+#ifdef GTEST_OS_FUCHSIA
+#include <zircon/process.h>
+#include <zircon/syscalls.h>
+#endif  // GTEST_OS_FUCHSIA
+
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "src/gtest-internal-inl.h"
+
+namespace testing {
+namespace internal {
+
+#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_GNU_HURD)
+
+namespace {
+template <typename T>
+T ReadProcFileField(const std::string& filename, int field) {
+  std::string dummy;
+  std::ifstream file(filename.c_str());
+  while (field-- > 0) {
+    file >> dummy;
+  }
+  T output = 0;
+  file >> output;
+  return output;
+}
+}  // namespace
+
+// Returns the number of active threads, or 0 when there is an error.
+size_t GetThreadCount() {
+  const std::string filename =
+      (Message() << "/proc/" << getpid() << "/stat").GetString();
+  return ReadProcFileField<size_t>(filename, 19);
+}
+
+#elif defined(GTEST_OS_MAC)
+
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task, reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#elif defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \
+    defined(GTEST_OS_GNU_KFREEBSD) || defined(GTEST_OS_NETBSD)
+
+#ifdef GTEST_OS_NETBSD
+#undef KERN_PROC
+#define KERN_PROC KERN_PROC2
+#define kinfo_proc kinfo_proc2
+#endif
+
+#ifdef GTEST_OS_DRAGONFLY
+#define KP_NLWP(kp) (kp.kp_nthreads)
+#elif defined(GTEST_OS_FREEBSD) || defined(GTEST_OS_GNU_KFREEBSD)
+#define KP_NLWP(kp) (kp.ki_numthreads)
+#elif defined(GTEST_OS_NETBSD)
+#define KP_NLWP(kp) (kp.p_nlwps)
+#endif
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  int mib[] = {
+      CTL_KERN,
+      KERN_PROC,
+      KERN_PROC_PID,
+      getpid(),
+#ifdef GTEST_OS_NETBSD
+      sizeof(struct kinfo_proc),
+      1,
+#endif
+  };
+  u_int miblen = sizeof(mib) / sizeof(mib[0]);
+  struct kinfo_proc info;
+  size_t size = sizeof(info);
+  if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
+    return 0;
+  }
+  return static_cast<size_t>(KP_NLWP(info));
+}
+#elif defined(GTEST_OS_OPENBSD)
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  int mib[] = {
+      CTL_KERN,
+      KERN_PROC,
+      KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
+      getpid(),
+      sizeof(struct kinfo_proc),
+      0,
+  };
+  u_int miblen = sizeof(mib) / sizeof(mib[0]);
+
+  // get number of structs
+  size_t size;
+  if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
+    return 0;
+  }
+
+  mib[5] = static_cast<int>(size / static_cast<size_t>(mib[4]));
+
+  // populate array of structs
+  std::vector<struct kinfo_proc> info(mib[5]);
+  if (sysctl(mib, miblen, info.data(), &size, NULL, 0)) {
+    return 0;
+  }
+
+  // exclude empty members
+  size_t nthreads = 0;
+  for (size_t i = 0; i < size / static_cast<size_t>(mib[4]); i++) {
+    if (info[i].p_tid != -1) nthreads++;
+  }
+  return nthreads;
+}
+
+#elif defined(GTEST_OS_QNX)
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const int fd = open("/proc/self/as", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+  procfs_info process_info;
+  const int status =
+      devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr);
+  close(fd);
+  if (status == EOK) {
+    return static_cast<size_t>(process_info.num_threads);
+  } else {
+    return 0;
+  }
+}
+
+#elif defined(GTEST_OS_AIX)
+
+size_t GetThreadCount() {
+  struct procentry64 entry;
+  pid_t pid = getpid();
+  int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1);
+  if (status == 1) {
+    return entry.pi_thcount;
+  } else {
+    return 0;
+  }
+}
+
+#elif defined(GTEST_OS_FUCHSIA)
+
+size_t GetThreadCount() {
+  int dummy_buffer;
+  size_t avail;
+  zx_status_t status =
+      zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS_THREADS,
+                         &dummy_buffer, 0, nullptr, &avail);
+  if (status == ZX_OK) {
+    return avail;
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_LINUX
+
+#if defined(GTEST_IS_THREADSAFE) && defined(GTEST_OS_WINDOWS)
+
+AutoHandle::AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+
+AutoHandle::AutoHandle(Handle handle) : handle_(handle) {}
+
+AutoHandle::~AutoHandle() { Reset(); }
+
+AutoHandle::Handle AutoHandle::Get() const { return handle_; }
+
+void AutoHandle::Reset() { Reset(INVALID_HANDLE_VALUE); }
+
+void AutoHandle::Reset(HANDLE handle) {
+  // Resetting with the same handle we already own is invalid.
+  if (handle_ != handle) {
+    if (IsCloseable()) {
+      ::CloseHandle(handle_);
+    }
+    handle_ = handle;
+  } else {
+    GTEST_CHECK_(!IsCloseable())
+        << "Resetting a valid handle to itself is likely a programmer error "
+           "and thus not allowed.";
+  }
+}
+
+bool AutoHandle::IsCloseable() const {
+  // Different Windows APIs may use either of these values to represent an
+  // invalid handle.
+  return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
+}
+
+Mutex::Mutex()
+    : owner_thread_id_(0),
+      type_(kDynamic),
+      critical_section_init_phase_(0),
+      critical_section_(new CRITICAL_SECTION) {
+  ::InitializeCriticalSection(critical_section_);
+}
+
+Mutex::~Mutex() {
+  // Static mutexes are leaked intentionally. It is not thread-safe to try
+  // to clean them up.
+  if (type_ == kDynamic) {
+    ::DeleteCriticalSection(critical_section_);
+    delete critical_section_;
+    critical_section_ = nullptr;
+  }
+}
+
+void Mutex::Lock() {
+  ThreadSafeLazyInit();
+  ::EnterCriticalSection(critical_section_);
+  owner_thread_id_ = ::GetCurrentThreadId();
+}
+
+void Mutex::Unlock() {
+  ThreadSafeLazyInit();
+  // We don't protect writing to owner_thread_id_ here, as it's the
+  // caller's responsibility to ensure that the current thread holds the
+  // mutex when this is called.
+  owner_thread_id_ = 0;
+  ::LeaveCriticalSection(critical_section_);
+}
+
+// Does nothing if the current thread holds the mutex. Otherwise, crashes
+// with high probability.
+void Mutex::AssertHeld() {
+  ThreadSafeLazyInit();
+  GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
+      << "The current thread is not holding the mutex @" << this;
+}
+
+namespace {
+
+#ifdef _MSC_VER
+// Use the RAII idiom to flag mem allocs that are intentionally never
+// deallocated. The motivation is to silence the false positive mem leaks
+// that are reported by the debug version of MS's CRT which can only detect
+// if an alloc is missing a matching deallocation.
+// Example:
+//    MemoryIsNotDeallocated memory_is_not_deallocated;
+//    critical_section_ = new CRITICAL_SECTION;
+//
+class MemoryIsNotDeallocated {
+ public:
+  MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
+    old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+    // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
+    // doesn't report mem leak if there's no matching deallocation.
+    (void)_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
+  }
+
+  ~MemoryIsNotDeallocated() {
+    // Restore the original _CRTDBG_ALLOC_MEM_DF flag
+    (void)_CrtSetDbgFlag(old_crtdbg_flag_);
+  }
+
+ private:
+  int old_crtdbg_flag_;
+
+  MemoryIsNotDeallocated(const MemoryIsNotDeallocated&) = delete;
+  MemoryIsNotDeallocated& operator=(const MemoryIsNotDeallocated&) = delete;
+};
+#endif  // _MSC_VER
+
+}  // namespace
+
+// Initializes owner_thread_id_ and critical_section_ in static mutexes.
+void Mutex::ThreadSafeLazyInit() {
+  // Dynamic mutexes are initialized in the constructor.
+  if (type_ == kStatic) {
+    switch (
+        ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
+      case 0:
+        // If critical_section_init_phase_ was 0 before the exchange, we
+        // are the first to test it and need to perform the initialization.
+        owner_thread_id_ = 0;
+        {
+          // Use RAII to flag that following mem alloc is never deallocated.
+#ifdef _MSC_VER
+          MemoryIsNotDeallocated memory_is_not_deallocated;
+#endif  // _MSC_VER
+          critical_section_ = new CRITICAL_SECTION;
+        }
+        ::InitializeCriticalSection(critical_section_);
+        // Updates the critical_section_init_phase_ to 2 to signal
+        // initialization complete.
+        GTEST_CHECK_(::InterlockedCompareExchange(&critical_section_init_phase_,
+                                                  2L, 1L) == 1L);
+        break;
+      case 1:
+        // Somebody else is already initializing the mutex; spin until they
+        // are done.
+        while (::InterlockedCompareExchange(&critical_section_init_phase_, 2L,
+                                            2L) != 2L) {
+          // Possibly yields the rest of the thread's time slice to other
+          // threads.
+          ::Sleep(0);
+        }
+        break;
+
+      case 2:
+        break;  // The mutex is already initialized and ready for use.
+
+      default:
+        GTEST_CHECK_(false)
+            << "Unexpected value of critical_section_init_phase_ "
+            << "while initializing a static mutex.";
+    }
+  }
+}
+
+namespace {
+
+class ThreadWithParamSupport : public ThreadWithParamBase {
+ public:
+  static HANDLE CreateThread(Runnable* runnable,
+                             Notification* thread_can_start) {
+    ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
+    DWORD thread_id;
+    HANDLE thread_handle = ::CreateThread(
+        nullptr,  // Default security.
+        0,        // Default stack size.
+        &ThreadWithParamSupport::ThreadMain,
+        param,        // Parameter to ThreadMainStatic
+        0x0,          // Default creation flags.
+        &thread_id);  // Need a valid pointer for the call to work under Win98.
+    GTEST_CHECK_(thread_handle != nullptr)
+        << "CreateThread failed with error " << ::GetLastError() << ".";
+    if (thread_handle == nullptr) {
+      delete param;
+    }
+    return thread_handle;
+  }
+
+ private:
+  struct ThreadMainParam {
+    ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
+        : runnable_(runnable), thread_can_start_(thread_can_start) {}
+    std::unique_ptr<Runnable> runnable_;
+    // Does not own.
+    Notification* thread_can_start_;
+  };
+
+  static DWORD WINAPI ThreadMain(void* ptr) {
+    // Transfers ownership.
+    std::unique_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
+    if (param->thread_can_start_ != nullptr)
+      param->thread_can_start_->WaitForNotification();
+    param->runnable_->Run();
+    return 0;
+  }
+
+  // Prohibit instantiation.
+  ThreadWithParamSupport();
+
+  ThreadWithParamSupport(const ThreadWithParamSupport&) = delete;
+  ThreadWithParamSupport& operator=(const ThreadWithParamSupport&) = delete;
+};
+
+}  // namespace
+
+ThreadWithParamBase::ThreadWithParamBase(Runnable* runnable,
+                                         Notification* thread_can_start)
+    : thread_(
+          ThreadWithParamSupport::CreateThread(runnable, thread_can_start)) {}
+
+ThreadWithParamBase::~ThreadWithParamBase() { Join(); }
+
+void ThreadWithParamBase::Join() {
+  GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
+      << "Failed to join the thread with error " << ::GetLastError() << ".";
+}
+
+// Maps a thread to a set of ThreadIdToThreadLocals that have values
+// instantiated on that thread and notifies them when the thread exits.  A
+// ThreadLocal instance is expected to persist until all threads it has
+// values on have terminated.
+class ThreadLocalRegistryImpl {
+ public:
+  // Registers thread_local_instance as having value on the current thread.
+  // Returns a value that can be used to identify the thread from other threads.
+  static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance) {
+#ifdef _MSC_VER
+    MemoryIsNotDeallocated memory_is_not_deallocated;
+#endif  // _MSC_VER
+    DWORD current_thread = ::GetCurrentThreadId();
+    MutexLock lock(&mutex_);
+    ThreadIdToThreadLocals* const thread_to_thread_locals =
+        GetThreadLocalsMapLocked();
+    ThreadIdToThreadLocals::iterator thread_local_pos =
+        thread_to_thread_locals->find(current_thread);
+    if (thread_local_pos == thread_to_thread_locals->end()) {
+      thread_local_pos =
+          thread_to_thread_locals
+              ->insert(std::make_pair(current_thread, ThreadLocalValues()))
+              .first;
+      StartWatcherThreadFor(current_thread);
+    }
+    ThreadLocalValues& thread_local_values = thread_local_pos->second;
+    ThreadLocalValues::iterator value_pos =
+        thread_local_values.find(thread_local_instance);
+    if (value_pos == thread_local_values.end()) {
+      value_pos =
+          thread_local_values
+              .insert(std::make_pair(
+                  thread_local_instance,
+                  std::shared_ptr<ThreadLocalValueHolderBase>(
+                      thread_local_instance->NewValueForCurrentThread())))
+              .first;
+    }
+    return value_pos->second.get();
+  }
+
+  static void OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance) {
+    std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
+    // Clean up the ThreadLocalValues data structure while holding the lock, but
+    // defer the destruction of the ThreadLocalValueHolderBases.
+    {
+      MutexLock lock(&mutex_);
+      ThreadIdToThreadLocals* const thread_to_thread_locals =
+          GetThreadLocalsMapLocked();
+      for (ThreadIdToThreadLocals::iterator it =
+               thread_to_thread_locals->begin();
+           it != thread_to_thread_locals->end(); ++it) {
+        ThreadLocalValues& thread_local_values = it->second;
+        ThreadLocalValues::iterator value_pos =
+            thread_local_values.find(thread_local_instance);
+        if (value_pos != thread_local_values.end()) {
+          value_holders.push_back(value_pos->second);
+          thread_local_values.erase(value_pos);
+          // This 'if' can only be successful at most once, so theoretically we
+          // could break out of the loop here, but we don't bother doing so.
+        }
+      }
+    }
+    // Outside the lock, let the destructor for 'value_holders' deallocate the
+    // ThreadLocalValueHolderBases.
+  }
+
+  static void OnThreadExit(DWORD thread_id) {
+    GTEST_CHECK_(thread_id != 0) << ::GetLastError();
+    std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
+    // Clean up the ThreadIdToThreadLocals data structure while holding the
+    // lock, but defer the destruction of the ThreadLocalValueHolderBases.
+    {
+      MutexLock lock(&mutex_);
+      ThreadIdToThreadLocals* const thread_to_thread_locals =
+          GetThreadLocalsMapLocked();
+      ThreadIdToThreadLocals::iterator thread_local_pos =
+          thread_to_thread_locals->find(thread_id);
+      if (thread_local_pos != thread_to_thread_locals->end()) {
+        ThreadLocalValues& thread_local_values = thread_local_pos->second;
+        for (ThreadLocalValues::iterator value_pos =
+                 thread_local_values.begin();
+             value_pos != thread_local_values.end(); ++value_pos) {
+          value_holders.push_back(value_pos->second);
+        }
+        thread_to_thread_locals->erase(thread_local_pos);
+      }
+    }
+    // Outside the lock, let the destructor for 'value_holders' deallocate the
+    // ThreadLocalValueHolderBases.
+  }
+
+ private:
+  // In a particular thread, maps a ThreadLocal object to its value.
+  typedef std::map<const ThreadLocalBase*,
+                   std::shared_ptr<ThreadLocalValueHolderBase> >
+      ThreadLocalValues;
+  // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
+  // thread's ID.
+  typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
+
+  struct WatcherThreadParams {
+    DWORD thread_id;
+    HANDLE handle;
+    Notification has_initialized;
+  };
+
+  static void StartWatcherThreadFor(DWORD thread_id) {
+    // The returned handle will be kept in thread_map and closed by
+    // watcher_thread in WatcherThreadFunc.
+    HANDLE thread =
+        ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
+    GTEST_CHECK_(thread != nullptr);
+
+    WatcherThreadParams* watcher_thread_params = new WatcherThreadParams;
+    watcher_thread_params->thread_id = thread_id;
+    watcher_thread_params->handle = thread;
+
+    // We need to pass a valid thread ID pointer into CreateThread for it
+    // to work correctly under Win98.
+    DWORD watcher_thread_id;
+    HANDLE watcher_thread =
+        ::CreateThread(nullptr,  // Default security.
+                       0,        // Default stack size
+                       &ThreadLocalRegistryImpl::WatcherThreadFunc,
+                       reinterpret_cast<LPVOID>(watcher_thread_params),
+                       CREATE_SUSPENDED, &watcher_thread_id);
+    GTEST_CHECK_(watcher_thread != nullptr)
+        << "CreateThread failed with error " << ::GetLastError() << ".";
+    // Give the watcher thread the same priority as ours to avoid being
+    // blocked by it.
+    ::SetThreadPriority(watcher_thread,
+                        ::GetThreadPriority(::GetCurrentThread()));
+    ::ResumeThread(watcher_thread);
+    ::CloseHandle(watcher_thread);
+
+    // Wait for the watcher thread to start to avoid race conditions.
+    // One specific race condition that can happen is that we have returned
+    // from main and have started to tear down, the newly spawned watcher
+    // thread may access already-freed variables, like global shared_ptrs.
+    watcher_thread_params->has_initialized.WaitForNotification();
+  }
+
+  // Monitors exit from a given thread and notifies those
+  // ThreadIdToThreadLocals about thread termination.
+  static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
+    WatcherThreadParams* watcher_thread_params =
+        reinterpret_cast<WatcherThreadParams*>(param);
+    watcher_thread_params->has_initialized.Notify();
+    GTEST_CHECK_(::WaitForSingleObject(watcher_thread_params->handle,
+                                       INFINITE) == WAIT_OBJECT_0);
+    OnThreadExit(watcher_thread_params->thread_id);
+    ::CloseHandle(watcher_thread_params->handle);
+    delete watcher_thread_params;
+    return 0;
+  }
+
+  // Returns map of thread local instances.
+  static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
+    mutex_.AssertHeld();
+#ifdef _MSC_VER
+    MemoryIsNotDeallocated memory_is_not_deallocated;
+#endif  // _MSC_VER
+    static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
+    return map;
+  }
+
+  // Protects access to GetThreadLocalsMapLocked() and its return value.
+  static Mutex mutex_;
+  // Protects access to GetThreadMapLocked() and its return value.
+  static Mutex thread_map_mutex_;
+};
+
+Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);  // NOLINT
+Mutex ThreadLocalRegistryImpl::thread_map_mutex_(
+    Mutex::kStaticMutex);  // NOLINT
+
+ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
+    const ThreadLocalBase* thread_local_instance) {
+  return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
+      thread_local_instance);
+}
+
+void ThreadLocalRegistry::OnThreadLocalDestroyed(
+    const ThreadLocalBase* thread_local_instance) {
+  ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
+}
+
+#endif  // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
+
+#ifdef GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+}
+
+// Returns true if and only if regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true if and only if regular expression re matches a substring of
+// str (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = regex;
+
+  // NetBSD (and Android, which takes its regex implemntation from NetBSD) does
+  // not include the GNU regex extensions (such as Perl style character classes
+  // like \w) in REG_EXTENDED. REG_EXTENDED is only specified to include the
+  // [[:alpha:]] style character classes. Enable REG_GNU wherever it is defined
+  // so users can use those extensions.
+#if defined(REG_GNU)
+  constexpr int reg_flags = REG_EXTENDED | REG_GNU;
+#else
+  constexpr int reg_flags = REG_EXTENDED;
+#endif
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, reg_flags) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, reg_flags) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif defined(GTEST_USES_SIMPLE_RE)
+
+// Returns true if and only if ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != nullptr;
+}
+
+// Returns true if and only if ch belongs to the given classification.
+// Unlike similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+         ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true if and only if "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true if and only if the given atom (specified by escaped and
+// pattern) matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd':
+        return IsAsciiDigit(ch);
+      case 'D':
+        return !IsAsciiDigit(ch);
+      case 'f':
+        return ch == '\f';
+      case 'n':
+        return ch == '\n';
+      case 'r':
+        return ch == '\r';
+      case 's':
+        return IsAsciiWhiteSpace(ch);
+      case 'S':
+        return !IsAsciiWhiteSpace(ch);
+      case 't':
+        return ch == '\t';
+      case 'v':
+        return ch == '\v';
+      case 'w':
+        return IsAsciiWordChar(ch);
+      case 'W':
+        return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+static std::string FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+                    << " in simple regular expression \"" << regex << "\": ")
+      .GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == nullptr) {
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True if and only if ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch
+                      << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch
+                      << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(bool escaped, char c, char repeat,
+                                   const char* regex, const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 : static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) return false;
+  }
+  return false;
+}
+
+// Returns true if and only if regex matches a prefix of str. regex must
+// be a valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$') return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped) ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(escaped, regex[0], regex[1], regex + 2,
+                                         str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+           MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true if and only if regex matches any substring of str.  regex must
+// be a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == nullptr || str == nullptr) return false;
+
+  if (*regex == '^') return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str)) return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() = default;
+
+// Returns true if and only if regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_.c_str(), str);
+}
+
+// Returns true if and only if regular expression re matches a substring of
+// str (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_.c_str(), str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  full_pattern_.clear();
+  pattern_.clear();
+
+  if (regex != nullptr) {
+    pattern_ = regex;
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^' and append a '$'.
+  full_pattern_.reserve(pattern_.size() + 2);
+
+  if (pattern_.empty() || pattern_.front() != '^') {
+    full_pattern_.push_back('^');  // Makes sure full_pattern_ starts with '^'.
+  }
+
+  full_pattern_.append(pattern_);
+
+  if (pattern_.empty() || pattern_.back() != '$') {
+    full_pattern_.push_back('$');  // Makes sure full_pattern_ ends with '$'.
+  }
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const std::string file_name(file == nullptr ? kUnknownFile : file);
+
+  if (line < 0) {
+    return file_name + ":";
+  }
+#ifdef _MSC_VER
+  return file_name + "(" + StreamableToString(line) + "):";
+#else
+  return file_name + ":" + StreamableToString(line) + ":";
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line) {
+  const std::string file_name(file == nullptr ? kUnknownFile : file);
+
+  if (line < 0)
+    return file_name;
+  else
+    return file_name + ":" + StreamableToString(line);
+}
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker = severity == GTEST_INFO      ? "[  INFO ]"
+                             : severity == GTEST_WARNING ? "[WARNING]"
+                             : severity == GTEST_ERROR   ? "[ ERROR ]"
+                                                         : "[ FATAL ]";
+  GetStream() << ::std::endl
+              << marker << " " << FormatFileLocation(file, line).c_str()
+              << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
+
+namespace {
+
+#if defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_IOS)
+bool EndsWithPathSeparator(const std::string& path) {
+  return !path.empty() && path.back() == GTEST_PATH_SEP_[0];
+}
+#endif
+
+}  // namespace
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+#ifdef GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = {'\0'};   // NOLINT
+    char temp_file_path[MAX_PATH + 1] = {'\0'};  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path, "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1)
+        << "Unable to open temporary file " << temp_file_path;
+    filename_ = temp_file_path;
+#else
+    // There's no guarantee that a test has write access to the current
+    // directory, so we create the temporary file in a temporary directory.
+    std::string name_template;
+
+#ifdef GTEST_OS_LINUX_ANDROID
+    // Note: Android applications are expected to call the framework's
+    // Context.getExternalStorageDirectory() method through JNI to get
+    // the location of the world-writable SD Card directory. However,
+    // this requires a Context handle, which cannot be retrieved
+    // globally from native code. Doing so also precludes running the
+    // code as part of a regular standalone executable, which doesn't
+    // run in a Dalvik process (e.g. when running it through 'adb shell').
+    //
+    // The location /data/local/tmp is directly accessible from native code.
+    // '/sdcard' and other variants cannot be relied on, as they are not
+    // guaranteed to be mounted, or may have a delay in mounting.
+    //
+    // However, prefer using the TMPDIR environment variable if set, as newer
+    // devices may have /data/local/tmp read-only.
+    name_template = TempDir();
+    if (!EndsWithPathSeparator(name_template))
+      name_template.push_back(GTEST_PATH_SEP_[0]);
+
+#elif defined(GTEST_OS_IOS)
+    char user_temp_dir[PATH_MAX + 1];
+
+    // Documented alternative to NSTemporaryDirectory() (for obtaining creating
+    // a temporary directory) at
+    // https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
+    //
+    // _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not
+    // documented in the confstr() man page at
+    // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr
+    // but are still available, according to the WebKit patches at
+    // https://trac.webkit.org/changeset/262004/webkit
+    // https://trac.webkit.org/changeset/263705/webkit
+    //
+    // The confstr() implementation falls back to getenv("TMPDIR"). See
+    // https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html
+    ::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
+
+    name_template = user_temp_dir;
+    if (!EndsWithPathSeparator(name_template))
+      name_template.push_back(GTEST_PATH_SEP_[0]);
+#else
+    name_template = "/tmp/";
+#endif
+    name_template.append("gtest_captured_stream.XXXXXX");
+
+    // mkstemp() modifies the string bytes in place, and does not go beyond the
+    // string's length. This results in well-defined behavior in C++17.
+    //
+    // The const_cast is needed below C++17. The constraints on std::string
+    // implementations in C++11 and above make assumption behind the const_cast
+    // fairly safe.
+    const int captured_fd = ::mkstemp(const_cast<char*>(name_template.data()));
+    if (captured_fd == -1) {
+      GTEST_LOG_(WARNING)
+          << "Failed to create tmp file " << name_template
+          << " for test; does the test have access to the /tmp directory?";
+    }
+    filename_ = std::move(name_template);
+#endif  // GTEST_OS_WINDOWS
+    fflush(nullptr);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() { remove(filename_.c_str()); }
+
+  std::string GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(nullptr);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    if (file == nullptr) {
+      GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_
+                        << " for capturing stream.";
+    }
+    const std::string content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  CapturedStream(const CapturedStream&) = delete;
+  CapturedStream& operator=(const CapturedStream&) = delete;
+};
+
+GTEST_DISABLE_MSC_DEPRECATED_POP_()
+
+static CapturedStream* g_captured_stderr = nullptr;
+static CapturedStream* g_captured_stdout = nullptr;
+
+// Starts capturing an output stream (stdout/stderr).
+static void CaptureStream(int fd, const char* stream_name,
+                          CapturedStream** stream) {
+  if (*stream != nullptr) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+static std::string GetCapturedStream(CapturedStream** captured_stream) {
+  const std::string content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = nullptr;
+
+  return content;
+}
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+std::string GetCapturedStdout() {
+  return GetCapturedStream(&g_captured_stdout);
+}
+
+// Stops capturing stderr and returns the captured string.
+std::string GetCapturedStderr() {
+  return GetCapturedStream(&g_captured_stderr);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+size_t GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+std::string ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read =
+        fread(buffer + bytes_read, 1, file_size - bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const std::string content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+static const std::vector<std::string>* g_injected_test_argvs =
+    nullptr;  // Owned.
+
+std::vector<std::string> GetInjectableArgvs() {
+  if (g_injected_test_argvs != nullptr) {
+    return *g_injected_test_argvs;
+  }
+  return GetArgvs();
+}
+
+void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
+  if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
+  g_injected_test_argvs = new_argvs;
+}
+
+void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
+  SetInjectableArgvs(
+      new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
+}
+
+void ClearInjectableArgvs() {
+  delete g_injected_test_argvs;
+  g_injected_test_argvs = nullptr;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static std::string FlagToEnvVar(const char* flag) {
+  const std::string full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, int32_t* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = nullptr;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an int32_t?
+  const auto result = static_cast<int32_t>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an int32_t.
+  ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually" << " has value "
+        << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true if and only if it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+#if defined(GTEST_GET_BOOL_FROM_ENV_)
+  return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
+#else
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == nullptr ? default_value
+                                 : strcmp(string_value, "0") != 0;
+#endif  // defined(GTEST_GET_BOOL_FROM_ENV_)
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+int32_t Int32FromGTestEnv(const char* flag, int32_t default_value) {
+#if defined(GTEST_GET_INT32_FROM_ENV_)
+  return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
+#else
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == nullptr) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  int32_t result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var, string_value,
+                  &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+#endif  // defined(GTEST_GET_INT32_FROM_ENV_)
+}
+
+// As a special case for the 'output' flag, if GTEST_OUTPUT is not
+// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
+// system.  The value of XML_OUTPUT_FILE is a filename without the
+// "xml:" prefix of GTEST_OUTPUT.
+// Note that this is meant to be called at the call site so it does
+// not check that the flag is 'output'
+// In essence this checks an env variable called XML_OUTPUT_FILE
+// and if it is set we prepend "xml:" to its value, if it not set we return ""
+std::string OutputFlagAlsoCheckEnvVar() {
+  std::string default_value_for_output_flag = "";
+  const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
+  if (nullptr != xml_output_file_env) {
+    default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
+  }
+  return default_value_for_output_flag;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+#if defined(GTEST_GET_STRING_FROM_ENV_)
+  return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
+#else
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == nullptr ? default_value : value;
+#endif  // defined(GTEST_GET_STRING_FROM_ENV_)
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest-printers.cc b/3rd-party/googletest/googletest/src/gtest-printers.cc
new file mode 100644
index 0000000..e3acecb
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-printers.cc
@@ -0,0 +1,555 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Test - The Google C++ Testing and Mocking Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+
+#include <stdio.h>
+
+#include <cctype>
+#include <cstdint>
+#include <cwchar>
+#include <iomanip>
+#include <ios>
+#include <ostream>  // NOLINT
+#include <string>
+#include <type_traits>
+
+#include "gtest/internal/gtest-port.h"
+#include "src/gtest-internal-inl.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+// Prints a segment of bytes in the given object.
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1) / 2 * 2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *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 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexadecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat { kAsIs, kHexEscape, kSpecialEscape };
+
+// 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(char32_t c) { return 0x20 <= c && c <= 0x7E; }
+
+// 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) {
+  const char32_t u_c = ToChar32(c);
+  switch (u_c) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      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>(u_c);
+        os->flags(flags);
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// 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(char32_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      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_lib_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(ToChar32(c), os);
+}
+
+#ifdef __cpp_lib_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 << GetCharWidthPrefix(c) << "'";
+  const CharFormat format = PrintAsCharLiteralTo(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0) return;
+  *os << " (" << static_cast<int>(c);
+
+  // For more convenience, we print c's code again in hexadecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << ", 0x" << String::FormatHexInt(static_cast<int>(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(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);
+}
+
+// gcc/clang __{u,}int128_t
+#if defined(__SIZEOF_INT128__)
+void PrintTo(__uint128_t v, ::std::ostream* os) {
+  if (v == 0) {
+    *os << "0";
+    return;
+  }
+
+  // Buffer large enough for ceil(log10(2^128))==39 and the null terminator
+  char buf[40];
+  char* p = buf + sizeof(buf);
+
+  // Some configurations have a __uint128_t, but no support for built in
+  // division. Do manual long division instead.
+
+  uint64_t high = static_cast<uint64_t>(v >> 64);
+  uint64_t low = static_cast<uint64_t>(v);
+
+  *--p = 0;
+  while (high != 0 || low != 0) {
+    uint64_t high_mod = high % 10;
+    high = high / 10;
+    // This is the long division algorithm specialized for a divisor of 10 and
+    // only two elements.
+    // Notable values:
+    //   2^64 / 10 == 1844674407370955161
+    //   2^64 % 10 == 6
+    const uint64_t carry = 6 * high_mod + low % 10;
+    low = low / 10 + high_mod * 1844674407370955161 + carry / 10;
+
+    char digit = static_cast<char>(carry % 10);
+    *--p = static_cast<char>('0' + digit);
+  }
+  *os << p;
+}
+void PrintTo(__int128_t v, ::std::ostream* os) {
+  __uint128_t uv = static_cast<__uint128_t>(v);
+  if (v < 0) {
+    *os << "-";
+    uv = -uv;
+  }
+  PrintTo(uv, os);
+}
+#endif  // __SIZEOF_INT128__
+
+// Prints the given array of characters to the ostream.  CharType must be either
+// 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>
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+    GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+        GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
+        PrintCharsAsStringTo(const CharType* begin, size_t len, ostream* os) {
+  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) {
+    const CharType cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" " << quote_prefix << "\"";
+    }
+    is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
+    // Remember if any characters required hex escaping.
+    if (is_previous_hex) {
+      print_format = kHexEscape;
+    }
+  }
+  *os << "\"";
+  return print_format;
+}
+
+// Prints a (const) char/wchar_t array of 'len' elements, starting at address
+// 'begin'.  CharType must be either char or wchar_t.
+template <typename CharType>
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+    GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+        GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static void
+        UniversalPrintCharArray(const CharType* begin, size_t len,
+                                ostream* os) {
+  // The code
+  //   const char kFoo[] = "foo";
+  // generates an array of 4, not 3, elements, with the last one being '\0'.
+  //
+  // Therefore when printing a char array, we don't print the last element if
+  // it's '\0', such that the output matches the string literal as it's
+  // written in the source code.
+  if (len > 0 && begin[len - 1] == '\0') {
+    PrintCharsAsStringTo(begin, len - 1, os);
+    return;
+  }
+
+  // If, however, the last element in the array is not '\0', e.g.
+  //    const char kFoo[] = { 'f', 'o', 'o' };
+  // we must print the entire array.  We also print a message to indicate
+  // that the array is not NUL-terminated.
+  PrintCharsAsStringTo(begin, len, os);
+  *os << " (no terminating NUL)";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+#ifdef __cpp_lib_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);
+}
+
+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, std::char_traits<Char>::length(s), os);
+  }
+}
+
+}  // anonymous namespace
+
+void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
+
+#ifdef __cpp_lib_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,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// 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) { PrintCStringTo(s, os); }
+#endif  // wchar_t is native
+
+namespace {
+
+bool ContainsUnprintableControlCodes(const char* str, size_t length) {
+  const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
+
+  for (size_t i = 0; i < length; i++) {
+    unsigned char ch = *s++;
+    if (std::iscntrl(ch)) {
+      switch (ch) {
+        case '\t':
+        case '\n':
+        case '\r':
+          break;
+        default:
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t <= 0xbf; }
+
+bool IsValidUTF8(const char* str, size_t length) {
+  const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
+
+  for (size_t i = 0; i < length;) {
+    unsigned char lead = s[i++];
+
+    if (lead <= 0x7f) {
+      continue;  // single-byte character (ASCII) 0..7F
+    }
+    if (lead < 0xc2) {
+      return false;  // trail byte or non-shortest form
+    } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
+      ++i;  // 2-byte character
+    } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
+               IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
+               // check for non-shortest form and surrogate
+               (lead != 0xe0 || s[i] >= 0xa0) &&
+               (lead != 0xed || s[i] < 0xa0)) {
+      i += 2;  // 3-byte character
+    } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
+               IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
+               IsUTF8TrailByte(s[i + 2]) &&
+               // check for non-shortest form
+               (lead != 0xf0 || s[i] >= 0x90) &&
+               (lead != 0xf4 || s[i] < 0x90)) {
+      i += 3;  // 4-byte character
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
+  if (!ContainsUnprintableControlCodes(str, length) &&
+      IsValidUTF8(str, length)) {
+    *os << "\n    As Text: \"" << str << "\"";
+  }
+}
+
+}  // anonymous namespace
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
+    if (GTEST_FLAG_GET(print_utf8)) {
+      ConditionalPrintAsText(s.data(), s.size(), os);
+    }
+  }
+}
+
+#ifdef __cpp_lib_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);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest-test-part.cc b/3rd-party/googletest/googletest/src/gtest-test-part.cc
new file mode 100644
index 0000000..6f8ddd7
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-test-part.cc
@@ -0,0 +1,106 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+#include <ostream>
+#include <string>
+
+#include "gtest/internal/gtest-port.h"
+#include "src/gtest-internal-inl.h"
+
+namespace testing {
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+std::string TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == nullptr ? message : std::string(message, stack_trace);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os << internal::FormatFileLocation(result.file_name(),
+                                            result.line_number())
+            << " "
+            << (result.type() == TestPartResult::kSuccess ? "Success"
+                : result.type() == TestPartResult::kSkip  ? "Skipped"
+                : result.type() == TestPartResult::kFatalFailure
+                    ? "Fatal failure"
+                    : "Non-fatal failure")
+            << ":\n"
+            << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[static_cast<size_t>(index)];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(
+          GetUnitTestImpl()->GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed()) has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest-typed-test.cc b/3rd-party/googletest/googletest/src/gtest-typed-test.cc
new file mode 100644
index 0000000..b251c09
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest-typed-test.cc
@@ -0,0 +1,108 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest-typed-test.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str)) str++;
+  return str;
+}
+
+static std::vector<std::string> SplitIntoTestNames(const char* src) {
+  std::vector<std::string> name_vec;
+  src = SkipSpaces(src);
+  for (; src != nullptr; src = SkipComma(src)) {
+    name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
+  }
+  return name_vec;
+}
+
+// Verifies that registered_tests match the test names in
+// registered_tests_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestSuitePState::VerifyRegisteredTestNames(
+    const char* test_suite_name, const char* file, int line,
+    const char* registered_tests) {
+  RegisterTypeParameterizedTestSuite(test_suite_name, CodeLocation(file, line));
+
+  typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
+  registered_ = true;
+
+  std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
+
+  Message errors;
+
+  std::set<std::string> tests;
+  for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
+       name_it != name_vec.end(); ++name_it) {
+    const std::string& name = *name_it;
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    if (registered_tests_.count(name) != 0) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test suite.\n";
+    }
+  }
+
+  for (RegisteredTestIter it = registered_tests_.begin();
+       it != registered_tests_.end(); ++it) {
+    if (tests.count(it->first) == 0) {
+      errors << "You forgot to list test " << it->first << ".\n";
+    }
+  }
+
+  const std::string& errors_str = errors.GetString();
+  if (!errors_str.empty()) {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest.cc b/3rd-party/googletest/googletest/src/gtest.cc
new file mode 100644
index 0000000..6662a13
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest.cc
@@ -0,0 +1,6960 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+
+#include "gtest/gtest.h"
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <chrono>  // NOLINT
+#include <cmath>
+#include <csignal>  // NOLINT: raise(3) is used on some platforms
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
+#include <iomanip>
+#include <ios>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <list>
+#include <map>
+#include <ostream>  // NOLINT
+#include <set>
+#include <sstream>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest-assertion-result.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/internal/custom/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_OS_LINUX
+
+#include <fcntl.h>   // NOLINT
+#include <limits.h>  // NOLINT
+#include <sched.h>   // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+#include <strings.h>   // NOLINT
+#include <sys/mman.h>  // NOLINT
+#include <sys/time.h>  // NOLINT
+#include <unistd.h>    // NOLINT
+
+#include <string>
+
+#elif defined(GTEST_OS_ZOS)
+#include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+#include <strings.h>   // NOLINT
+
+#elif defined(GTEST_OS_WINDOWS_MOBILE)  // We are on Windows CE.
+
+#include <windows.h>  // NOLINT
+#undef min
+
+#elif defined(GTEST_OS_WINDOWS)  // We are on Windows proper.
+
+#include <windows.h>  // NOLINT
+#undef min
+
+#ifdef _MSC_VER
+#include <crtdbg.h>  // NOLINT
+#endif
+
+#include <io.h>         // NOLINT
+#include <sys/stat.h>   // NOLINT
+#include <sys/timeb.h>  // NOLINT
+#include <sys/types.h>  // NOLINT
+
+#ifdef GTEST_OS_WINDOWS_MINGW
+#include <sys/time.h>  // NOLINT
+#endif                 // GTEST_OS_WINDOWS_MINGW
+
+#else
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+#include <sys/time.h>  // NOLINT
+#include <unistd.h>    // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+#include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+#include <arpa/inet.h>   // NOLINT
+#include <netdb.h>       // NOLINT
+#include <sys/socket.h>  // NOLINT
+#include <sys/types.h>   // NOLINT
+#endif
+
+#include "src/gtest-internal-inl.h"
+
+#ifdef GTEST_OS_WINDOWS
+#define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef GTEST_OS_MAC
+#ifndef GTEST_OS_IOS
+#include <crt_externs.h>
+#endif
+#endif
+
+#ifdef GTEST_HAS_ABSL
+#include "absl/container/flat_hash_set.h"
+#include "absl/debugging/failure_signal_handler.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/debugging/symbolize.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/usage.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#endif  // GTEST_HAS_ABSL
+
+// Checks builtin compiler feature |x| while avoiding an extra layer of #ifdefs
+// at the callsite.
+#if defined(__has_builtin)
+#define GTEST_HAS_BUILTIN(x) __has_builtin(x)
+#else
+#define GTEST_HAS_BUILTIN(x) 0
+#endif  // defined(__has_builtin)
+
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+#define GTEST_HAS_ABSL_FLAGS
+#endif
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test suite name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test suite whose name matches this filter is considered a death
+// test suite and will be run before test suites whose name doesn't
+// match this filter.
+static const char kDeathTestSuiteFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output format.
+static const char kDefaultOutputFormat[] = "xml";
+// The default output file.
+static const char kDefaultOutputFile[] = "test_detail";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true if and only if the --help flag or an equivalent form
+// is specified on the command line.
+bool g_help_flag = false;
+
+#if GTEST_HAS_FILE_SYSTEM
+// Utility function to Open File for Writing
+static FILE* OpenFileForWriting(const std::string& output_file) {
+  FILE* fileout = nullptr;
+  FilePath output_file_path(output_file);
+  FilePath output_dir(output_file_path.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    fileout = posix::FOpen(output_file.c_str(), "w");
+  }
+  if (fileout == nullptr) {
+    GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\"";
+  }
+  return fileout;
+}
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+}  // namespace internal
+
+// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY
+// environment variable.
+static const char* GetDefaultFilter() {
+  const char* const testbridge_test_only =
+      internal::posix::GetEnv("TESTBRIDGE_TEST_ONLY");
+  if (testbridge_test_only != nullptr) {
+    return testbridge_test_only;
+  }
+  return kUniversalFilter;
+}
+
+// Bazel passes in the argument to '--test_runner_fail_fast' via the
+// TESTBRIDGE_TEST_RUNNER_FAIL_FAST environment variable.
+static bool GetDefaultFailFast() {
+  const char* const testbridge_test_runner_fail_fast =
+      internal::posix::GetEnv("TESTBRIDGE_TEST_RUNNER_FAIL_FAST");
+  if (testbridge_test_runner_fail_fast != nullptr) {
+    return strcmp(testbridge_test_runner_fail_fast, "1") == 0;
+  }
+  return false;
+}
+
+}  // namespace testing
+
+GTEST_DEFINE_bool_(
+    fail_fast,
+    testing::internal::BoolFromGTestEnv("fail_fast",
+                                        testing::GetDefaultFailFast()),
+    "True if and only if a test failure should stop further test execution.");
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    testing::internal::BoolFromGTestEnv("break_on_failure", false),
+    "True if and only if a failed assertion should be a debugger "
+    "break-point.");
+
+GTEST_DEFINE_bool_(catch_exceptions,
+                   testing::internal::BoolFromGTestEnv("catch_exceptions",
+                                                       true),
+                   "True if and only if " GTEST_NAME_
+                   " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color, testing::internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to a terminal type that supports colors.");
+
+GTEST_DEFINE_string_(
+    filter,
+    testing::internal::StringFromGTestEnv("filter",
+                                          testing::GetDefaultFilter()),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(
+    install_failure_signal_handler,
+    testing::internal::BoolFromGTestEnv("install_failure_signal_handler",
+                                        false),
+    "If true and supported on the current platform, " GTEST_NAME_
+    " should "
+    "install a signal handler that dumps debugging information when fatal "
+    "signals are raised.");
+
+GTEST_DEFINE_bool_(list_tests, false, "List all tests without running them.");
+
+// The net priority order after flag processing is thus:
+//   --gtest_output command line flag
+//   GTEST_OUTPUT environment variable
+//   XML_OUTPUT_FILE environment variable
+//   ''
+GTEST_DEFINE_string_(
+    output,
+    testing::internal::StringFromGTestEnv(
+        "output", testing::internal::OutputFlagAlsoCheckEnvVar().c_str()),
+    "A format (defaults to \"xml\" but can be specified to be \"json\"), "
+    "optionally followed by a colon and an output file name or directory. "
+    "A directory is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    brief, testing::internal::BoolFromGTestEnv("brief", false),
+    "True if only test failures should be displayed in text output.");
+
+GTEST_DEFINE_bool_(print_time,
+                   testing::internal::BoolFromGTestEnv("print_time", true),
+                   "True if and only if " GTEST_NAME_
+                   " should display elapsed time in text output.");
+
+GTEST_DEFINE_bool_(print_utf8,
+                   testing::internal::BoolFromGTestEnv("print_utf8", true),
+                   "True if and only if " GTEST_NAME_
+                   " prints UTF8 characters as text.");
+
+GTEST_DEFINE_int32_(
+    random_seed, testing::internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat, testing::internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    recreate_environments_when_repeating,
+    testing::internal::BoolFromGTestEnv("recreate_environments_when_repeating",
+                                        false),
+    "Controls whether global test environments are recreated for each repeat "
+    "of the tests. If set to false the global test environments are only set "
+    "up once, for the first iteration, and only torn down once, for the last. "
+    "Useful for shaking out flaky tests with stable, expensive test "
+    "environments. If --gtest_repeat is set to a negative number, meaning "
+    "there is no last run, the environments will always be recreated to avoid "
+    "leaks.");
+
+GTEST_DEFINE_bool_(show_internal_stack_frames, false,
+                   "True if and only if " GTEST_NAME_
+                   " should include internal stack frames when "
+                   "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(shuffle,
+                   testing::internal::BoolFromGTestEnv("shuffle", false),
+                   "True if and only if " GTEST_NAME_
+                   " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    testing::internal::Int32FromGTestEnv("stack_trace_depth",
+                                         testing::kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    testing::internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux and macOS.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    testing::internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise. For use with an external test framework.");
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+GTEST_DEFINE_string_(
+    flagfile, testing::internal::StringFromGTestEnv("flagfile", ""),
+    "This flag specifies the flagfile to read command-line flags from.");
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+namespace testing {
+namespace internal {
+
+const uint32_t Random::kMaxRange;
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+uint32_t Random::Generate(uint32_t range) {
+  // These constants are the same as are used in glibc's rand(3).
+  // Use wider types than necessary to prevent unsigned overflow diagnostics.
+  state_ = static_cast<uint32_t>(1103515245ULL * state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0) << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true if and only if the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+static bool GTestIsInitialized() { return !GetArgvs().empty(); }
+
+// Iterates over a vector of TestSuites, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestSuiteList(const std::vector<TestSuite*>& case_list,
+                                int (TestSuite::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true if and only if the test suite passed.
+static bool TestSuitePassed(const TestSuite* test_suite) {
+  return test_suite->should_run() && test_suite->Passed();
+}
+
+// Returns true if and only if the test suite failed.
+static bool TestSuiteFailed(const TestSuite* test_suite) {
+  return test_suite->should_run() && test_suite->Failed();
+}
+
+// Returns true if and only if test_suite contains at least one test that
+// should run.
+static bool ShouldRunTestSuite(const TestSuite* test_suite) {
+  return test_suite->should_run();
+}
+
+namespace {
+
+// Returns true if test part results of type `type` should include a stack
+// trace.
+bool ShouldEmitStackTraceForResultType(TestPartResult::Type type) {
+  // Suppress emission of the stack trace for SUCCEED() since it likely never
+  // requires investigation, and GTEST_SKIP() since skipping is an intentional
+  // act by the developer rather than a failure requiring investigation.
+  return type != TestPartResult::kSuccess && type != TestPartResult::kSkip;
+}
+
+}  // namespace
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type, const char* file,
+                           int line, const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {}
+
+AssertHelper::~AssertHelper() { delete data_; }
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->AddTestPartResult(
+      data_->type, data_->file, data_->line,
+      AppendUserMessage(data_->message, message),
+      ShouldEmitStackTraceForResultType(data_->type)
+          ? UnitTest::GetInstance()->impl()->CurrentOsStackTraceExceptTop(1)
+          : ""
+      // Skips the stack frame for this function itself.
+  );  // NOLINT
+}
+
+namespace {
+
+// When TEST_P is found without a matching INSTANTIATE_TEST_SUITE_P
+// to creates test cases for it, a synthetic test case is
+// inserted to report ether an error or a log message.
+//
+// This configuration bit will likely be removed at some point.
+constexpr bool kErrorOnUninstantiatedParameterizedTest = true;
+constexpr bool kErrorOnUninstantiatedTypeParameterizedTest = true;
+
+// A test that fails at a given file/line location with a given message.
+class FailureTest : public Test {
+ public:
+  explicit FailureTest(const CodeLocation& loc, std::string error_message,
+                       bool as_error)
+      : loc_(loc),
+        error_message_(std::move(error_message)),
+        as_error_(as_error) {}
+
+  void TestBody() override {
+    if (as_error_) {
+      AssertHelper(TestPartResult::kNonFatalFailure, loc_.file.c_str(),
+                   loc_.line, "") = Message() << error_message_;
+    } else {
+      std::cout << error_message_ << std::endl;
+    }
+  }
+
+ private:
+  const CodeLocation loc_;
+  const std::string error_message_;
+  const bool as_error_;
+};
+
+}  // namespace
+
+std::set<std::string>* GetIgnoredParameterizedTestSuites() {
+  return UnitTest::GetInstance()->impl()->ignored_parameterized_test_suites();
+}
+
+// Add a given test_suit to the list of them allow to go un-instantiated.
+MarkAsIgnored::MarkAsIgnored(const char* test_suite) {
+  GetIgnoredParameterizedTestSuites()->insert(test_suite);
+}
+
+// If this parameterized test suite has no instantiations (and that
+// has not been marked as okay), emit a test case reporting that.
+void InsertSyntheticTestCase(const std::string& name, CodeLocation location,
+                             bool has_test_p) {
+  const auto& ignored = *GetIgnoredParameterizedTestSuites();
+  if (ignored.find(name) != ignored.end()) return;
+
+  const char kMissingInstantiation[] =  //
+      " is defined via TEST_P, but never instantiated. None of the test "
+      "cases "
+      "will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only "
+      "ones provided expand to nothing."
+      "\n\n"
+      "Ideally, TEST_P definitions should only ever be included as part of "
+      "binaries that intend to use them. (As opposed to, for example, being "
+      "placed in a library that may be linked in to get other utilities.)";
+
+  const char kMissingTestCase[] =  //
+      " is instantiated via INSTANTIATE_TEST_SUITE_P, but no tests are "
+      "defined via TEST_P . No test cases will run."
+      "\n\n"
+      "Ideally, INSTANTIATE_TEST_SUITE_P should only ever be invoked from "
+      "code that always depend on code that provides TEST_P. Failing to do "
+      "so is often an indication of dead code, e.g. the last TEST_P was "
+      "removed but the rest got left behind.";
+
+  std::string message =
+      "Parameterized test suite " + name +
+      (has_test_p ? kMissingInstantiation : kMissingTestCase) +
+      "\n\n"
+      "To suppress this error for this test suite, insert the following line "
+      "(in a non-header) in the namespace it is defined in:"
+      "\n\n"
+      "GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" +
+      name + ");";
+
+  std::string full_name = "UninstantiatedParameterizedTestSuite<" + name + ">";
+  RegisterTest(  //
+      "GoogleTestVerification", full_name.c_str(),
+      nullptr,  // No type parameter.
+      nullptr,  // No value parameter.
+      location.file.c_str(), location.line, [message, location] {
+        return new FailureTest(location, message,
+                               kErrorOnUninstantiatedParameterizedTest);
+      });
+}
+
+void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
+                                        CodeLocation code_location) {
+  GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite(
+      test_suite_name, std::move(code_location));
+}
+
+void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
+  GetUnitTestImpl()->type_parameterized_test_registry().RegisterInstantiation(
+      case_name);
+}
+
+void TypeParameterizedTestSuiteRegistry::RegisterTestSuite(
+    const char* test_suite_name, CodeLocation code_location) {
+  suites_.emplace(std::string(test_suite_name),
+                  TypeParameterizedTestSuiteInfo(std::move(code_location)));
+}
+
+void TypeParameterizedTestSuiteRegistry::RegisterInstantiation(
+    const char* test_suite_name) {
+  auto it = suites_.find(std::string(test_suite_name));
+  if (it != suites_.end()) {
+    it->second.instantiated = true;
+  } else {
+    GTEST_LOG_(ERROR) << "Unknown type parameterized test suit '"
+                      << test_suite_name << "'";
+  }
+}
+
+void TypeParameterizedTestSuiteRegistry::CheckForInstantiations() {
+  const auto& ignored = *GetIgnoredParameterizedTestSuites();
+  for (const auto& testcase : suites_) {
+    if (testcase.second.instantiated) continue;
+    if (ignored.find(testcase.first) != ignored.end()) continue;
+
+    std::string message =
+        "Type parameterized test suite " + testcase.first +
+        " is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated "
+        "via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run."
+        "\n\n"
+        "Ideally, TYPED_TEST_P definitions should only ever be included as "
+        "part of binaries that intend to use them. (As opposed to, for "
+        "example, being placed in a library that may be linked in to get "
+        "other "
+        "utilities.)"
+        "\n\n"
+        "To suppress this error for this test suite, insert the following "
+        "line "
+        "(in a non-header) in the namespace it is defined in:"
+        "\n\n"
+        "GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" +
+        testcase.first + ");";
+
+    std::string full_name =
+        "UninstantiatedTypeParameterizedTestSuite<" + testcase.first + ">";
+    RegisterTest(  //
+        "GoogleTestVerification", full_name.c_str(),
+        nullptr,  // No type parameter.
+        nullptr,  // No value parameter.
+        testcase.second.code_location.file.c_str(),
+        testcase.second.code_location.line, [message, testcase] {
+          return new FailureTest(testcase.second.code_location, message,
+                                 kErrorOnUninstantiatedTypeParameterizedTest);
+        });
+  }
+}
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+static ::std::vector<std::string> g_argvs;
+
+::std::vector<std::string> GetArgvs() {
+#if defined(GTEST_CUSTOM_GET_ARGVS_)
+  // GTEST_CUSTOM_GET_ARGVS_() may return a container of std::string or
+  // ::string. This code converts it to the appropriate type.
+  const auto& custom = GTEST_CUSTOM_GET_ARGVS_();
+  return ::std::vector<std::string>(custom.begin(), custom.end());
+#else   // defined(GTEST_CUSTOM_GET_ARGVS_)
+  return g_argvs;
+#endif  // defined(GTEST_CUSTOM_GET_ARGVS_)
+}
+
+#if GTEST_HAS_FILE_SYSTEM
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+  auto args = GetArgvs();
+  if (!args.empty()) {
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_OS2)
+    result.Set(FilePath(args[0]).RemoveExtension("exe"));
+#else
+    result.Set(FilePath(args[0]));
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return result.RemoveDirectoryName();
+}
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+std::string UnitTestOptions::GetOutputFormat() {
+  std::string s = GTEST_FLAG_GET(output);
+  const char* const gtest_output_flag = s.c_str();
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == nullptr)
+             ? std::string(gtest_output_flag)
+             : std::string(gtest_output_flag,
+                           static_cast<size_t>(colon - gtest_output_flag));
+}
+
+#if GTEST_HAS_FILE_SYSTEM
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
+  std::string s = GTEST_FLAG_GET(output);
+  const char* const gtest_output_flag = s.c_str();
+
+  std::string format = GetOutputFormat();
+  if (format.empty()) format = std::string(kDefaultOutputFormat);
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == nullptr)
+    return internal::FilePath::MakeFileName(
+               internal::FilePath(
+                   UnitTest::GetInstance()->original_working_dir()),
+               internal::FilePath(kDefaultOutputFile), 0, format.c_str())
+        .string();
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory()) return output_name.string();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.string();
+}
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+// Returns true if and only if the wildcard pattern matches the string. Each
+// pattern consists of regular characters, single-character wildcards (?), and
+// multi-character wildcards (*).
+//
+// This function implements a linear-time string globbing algorithm based on
+// https://research.swtch.com/glob.
+static bool PatternMatchesString(const std::string& name_str,
+                                 const char* pattern, const char* pattern_end) {
+  const char* name = name_str.c_str();
+  const char* const name_begin = name;
+  const char* const name_end = name + name_str.size();
+
+  const char* pattern_next = pattern;
+  const char* name_next = name;
+
+  while (pattern < pattern_end || name < name_end) {
+    if (pattern < pattern_end) {
+      switch (*pattern) {
+        default:  // Match an ordinary character.
+          if (name < name_end && *name == *pattern) {
+            ++pattern;
+            ++name;
+            continue;
+          }
+          break;
+        case '?':  // Match any single character.
+          if (name < name_end) {
+            ++pattern;
+            ++name;
+            continue;
+          }
+          break;
+        case '*':
+          // Match zero or more characters. Start by skipping over the wildcard
+          // and matching zero characters from name. If that fails, restart and
+          // match one more character than the last attempt.
+          pattern_next = pattern;
+          name_next = name + 1;
+          ++pattern;
+          continue;
+      }
+    }
+    // Failed to match a character. Restart if possible.
+    if (name_begin < name_next && name_next <= name_end) {
+      pattern = pattern_next;
+      name = name_next;
+      continue;
+    }
+    return false;
+  }
+  return true;
+}
+
+namespace {
+
+bool IsGlobPattern(const std::string& pattern) {
+  return std::any_of(pattern.begin(), pattern.end(),
+                     [](const char c) { return c == '?' || c == '*'; });
+}
+
+class UnitTestFilter {
+ public:
+  UnitTestFilter() = default;
+
+  // Constructs a filter from a string of patterns separated by `:`.
+  explicit UnitTestFilter(const std::string& filter) {
+    // By design "" filter matches "" string.
+    std::vector<std::string> all_patterns;
+    SplitString(filter, ':', &all_patterns);
+    const auto exact_match_patterns_begin = std::partition(
+        all_patterns.begin(), all_patterns.end(), &IsGlobPattern);
+
+    glob_patterns_.reserve(static_cast<size_t>(
+        std::distance(all_patterns.begin(), exact_match_patterns_begin)));
+    std::move(all_patterns.begin(), exact_match_patterns_begin,
+              std::inserter(glob_patterns_, glob_patterns_.begin()));
+    std::move(
+        exact_match_patterns_begin, all_patterns.end(),
+        std::inserter(exact_match_patterns_, exact_match_patterns_.begin()));
+  }
+
+  // Returns true if and only if name matches at least one of the patterns in
+  // the filter.
+  bool MatchesName(const std::string& name) const {
+    return exact_match_patterns_.find(name) != exact_match_patterns_.end() ||
+           std::any_of(glob_patterns_.begin(), glob_patterns_.end(),
+                       [&name](const std::string& pattern) {
+                         return PatternMatchesString(
+                             name, pattern.c_str(),
+                             pattern.c_str() + pattern.size());
+                       });
+  }
+
+ private:
+  std::vector<std::string> glob_patterns_;
+  std::unordered_set<std::string> exact_match_patterns_;
+};
+
+class PositiveAndNegativeUnitTestFilter {
+ public:
+  // Constructs a positive and a negative filter from a string. The string
+  // contains a positive filter optionally followed by a '-' character and a
+  // negative filter. In case only a negative filter is provided the positive
+  // filter will be assumed "*".
+  // A filter is a list of patterns separated by ':'.
+  explicit PositiveAndNegativeUnitTestFilter(const std::string& filter) {
+    std::vector<std::string> positive_and_negative_filters;
+
+    // NOTE: `SplitString` always returns a non-empty container.
+    SplitString(filter, '-', &positive_and_negative_filters);
+    const auto& positive_filter = positive_and_negative_filters.front();
+
+    if (positive_and_negative_filters.size() > 1) {
+      positive_filter_ = UnitTestFilter(
+          positive_filter.empty() ? kUniversalFilter : positive_filter);
+
+      // TODO(b/214626361): Fail on multiple '-' characters
+      // For the moment to preserve old behavior we concatenate the rest of the
+      // string parts with `-` as separator to generate the negative filter.
+      auto negative_filter_string = positive_and_negative_filters[1];
+      for (std::size_t i = 2; i < positive_and_negative_filters.size(); i++)
+        negative_filter_string =
+            negative_filter_string + '-' + positive_and_negative_filters[i];
+      negative_filter_ = UnitTestFilter(negative_filter_string);
+    } else {
+      // In case we don't have a negative filter and positive filter is ""
+      // we do not use kUniversalFilter by design as opposed to when we have a
+      // negative filter.
+      positive_filter_ = UnitTestFilter(positive_filter);
+    }
+  }
+
+  // Returns true if and only if test name (this is generated by appending test
+  // suit name and test name via a '.' character) matches the positive filter
+  // and does not match the negative filter.
+  bool MatchesTest(const std::string& test_suite_name,
+                   const std::string& test_name) const {
+    return MatchesName(test_suite_name + "." + test_name);
+  }
+
+  // Returns true if and only if name matches the positive filter and does not
+  // match the negative filter.
+  bool MatchesName(const std::string& name) const {
+    return positive_filter_.MatchesName(name) &&
+           !negative_filter_.MatchesName(name);
+  }
+
+ private:
+  UnitTestFilter positive_filter_;
+  UnitTestFilter negative_filter_;
+};
+}  // namespace
+
+bool UnitTestOptions::MatchesFilter(const std::string& name_str,
+                                    const char* filter) {
+  return UnitTestFilter(filter).MatchesName(name_str);
+}
+
+// Returns true if and only if the user-specified filter matches the test
+// suite name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name,
+                                        const std::string& test_name) {
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  return PositiveAndNegativeUnitTestFilter(GTEST_FLAG_GET(filter))
+      .MatchesTest(test_suite_name, test_name);
+}
+
+#if GTEST_HAS_SEH
+static std::string FormatSehExceptionMessage(DWORD exception_code,
+                                             const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) << exception_code
+          << std::setbase(10) << " thrown in " << location << ".";
+  return message.GetString();
+}
+
+int UnitTestOptions::GTestProcessSEH(DWORD seh_code, const char* location) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception or stack overflow, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see https://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  if (!GTEST_FLAG_GET(catch_exceptions) || seh_code == kCxxExceptionCode ||
+      seh_code == EXCEPTION_BREAKPOINT ||
+      seh_code == EXCEPTION_STACK_OVERFLOW) {
+    return EXCEPTION_CONTINUE_SEARCH;  // Don't handle these exceptions
+  }
+
+  internal::ReportFailureInUnknownLocation(
+      TestPartResult::kFatalFailure,
+      FormatSehExceptionMessage(seh_code, location) +
+          "\n"
+          "Stack trace:\n" +
+          ::testing::internal::GetCurrentOsStackTraceExceptTop(1));
+
+  return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode), result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() { return GetTypeId<Test>(); }
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+static AssertionResult HasOneFailure(const char* /* results_expr */,
+                                     const char* /* type_expr */,
+                                     const char* /* substr_expr */,
+                                     const TestPartResultArray& results,
+                                     TestPartResult::Type type,
+                                     const std::string& substr) {
+  const std::string expected(type == TestPartResult::kFatalFailure
+                                 ? "1 fatal failure"
+                                 : "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == nullptr) {
+    return AssertionFailure()
+           << "Expected: " << expected << " containing \"" << substr << "\"\n"
+           << "  Actual:\n"
+           << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker::SingleFailureChecker(const TestPartResultArray* results,
+                                           TestPartResult::Type type,
+                                           const std::string& substr)
+    : results_(results), type_(type), substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test)
+    : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test)
+    : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_reporter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_reporter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test suites.
+int UnitTestImpl::successful_test_suite_count() const {
+  return CountIf(test_suites_, TestSuitePassed);
+}
+
+// Gets the number of failed test suites.
+int UnitTestImpl::failed_test_suite_count() const {
+  return CountIf(test_suites_, TestSuiteFailed);
+}
+
+// Gets the number of all test suites.
+int UnitTestImpl::total_test_suite_count() const {
+  return static_cast<int>(test_suites_.size());
+}
+
+// Gets the number of all test suites that contain at least one test
+// that should run.
+int UnitTestImpl::test_suite_to_run_count() const {
+  return CountIf(test_suites_, ShouldRunTestSuite);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::successful_test_count);
+}
+
+// Gets the number of skipped tests.
+int UnitTestImpl::skipped_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::skipped_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::failed_test_count);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTestImpl::reportable_disabled_test_count() const {
+  return SumOverTestSuiteList(test_suites_,
+                              &TestSuite::reportable_disabled_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::disabled_test_count);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTestImpl::reportable_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::reportable_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::test_to_run_count);
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  return os_stack_trace_getter()->CurrentStackTrace(
+      static_cast<int>(GTEST_FLAG_GET(stack_trace_depth)), skip_count + 1
+      // Skips the user-specified number of frames plus this function
+      // itself.
+  );  // NOLINT
+}
+
+// A helper class for measuring elapsed times.
+class Timer {
+ public:
+  Timer() : start_(clock::now()) {}
+
+  // Return time elapsed in milliseconds since the timer was created.
+  TimeInMillis Elapsed() {
+    return std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() -
+                                                                 start_)
+        .count();
+  }
+
+ private:
+  // Fall back to the system_clock when building with newlib on a system
+  // without a monotonic clock.
+#if defined(_NEWLIB_VERSION) && !defined(CLOCK_MONOTONIC)
+  using clock = std::chrono::system_clock;
+#else
+  using clock = std::chrono::steady_clock;
+#endif
+  clock::time_point start_;
+};
+
+// Returns a timestamp as milliseconds since the epoch. Note this time may jump
+// around subject to adjustments by the system, to measure elapsed time use
+// Timer instead.
+TimeInMillis GetTimeInMillis() {
+  return std::chrono::duration_cast<std::chrono::milliseconds>(
+             std::chrono::system_clock::now() -
+             std::chrono::system_clock::from_time_t(0))
+      .count();
+}
+
+// Utilities
+
+// class String.
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return nullptr;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length, nullptr, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length, unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str) {
+  if (!utf16_str) return nullptr;
+  const int ansi_length = WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, nullptr,
+                                              0, nullptr, nullptr);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, ansi, ansi_length, nullptr,
+                      nullptr);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true if and only if they have the same
+// content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char* lhs, const char* rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+
+  if (rhs == nullptr) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  for (size_t i = 0; i != length;) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0') i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+void SplitString(const ::std::string& str, char delimiter,
+                 ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+}  // namespace internal
+
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+  // By default, we want there to be enough precision when printing
+  // a double to a Message.
+  *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator<<(const wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator<<(wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator<<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+  return internal::StringStreamToString(ss_.get());
+}
+
+namespace internal {
+
+namespace edit_distance {
+std::vector<EditType> CalculateOptimalEdits(const std::vector<size_t>& left,
+                                            const std::vector<size_t>& right) {
+  std::vector<std::vector<double> > costs(
+      left.size() + 1, std::vector<double>(right.size() + 1));
+  std::vector<std::vector<EditType> > best_move(
+      left.size() + 1, std::vector<EditType>(right.size() + 1));
+
+  // Populate for empty right.
+  for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
+    costs[l_i][0] = static_cast<double>(l_i);
+    best_move[l_i][0] = kRemove;
+  }
+  // Populate for empty left.
+  for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
+    costs[0][r_i] = static_cast<double>(r_i);
+    best_move[0][r_i] = kAdd;
+  }
+
+  for (size_t l_i = 0; l_i < left.size(); ++l_i) {
+    for (size_t r_i = 0; r_i < right.size(); ++r_i) {
+      if (left[l_i] == right[r_i]) {
+        // Found a match. Consume it.
+        costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
+        best_move[l_i + 1][r_i + 1] = kMatch;
+        continue;
+      }
+
+      const double add = costs[l_i + 1][r_i];
+      const double remove = costs[l_i][r_i + 1];
+      const double replace = costs[l_i][r_i];
+      if (add < remove && add < replace) {
+        costs[l_i + 1][r_i + 1] = add + 1;
+        best_move[l_i + 1][r_i + 1] = kAdd;
+      } else if (remove < add && remove < replace) {
+        costs[l_i + 1][r_i + 1] = remove + 1;
+        best_move[l_i + 1][r_i + 1] = kRemove;
+      } else {
+        // We make replace a little more expensive than add/remove to lower
+        // their priority.
+        costs[l_i + 1][r_i + 1] = replace + 1.00001;
+        best_move[l_i + 1][r_i + 1] = kReplace;
+      }
+    }
+  }
+
+  // Reconstruct the best path. We do it in reverse order.
+  std::vector<EditType> best_path;
+  for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
+    EditType move = best_move[l_i][r_i];
+    best_path.push_back(move);
+    l_i -= move != kAdd;
+    r_i -= move != kRemove;
+  }
+  std::reverse(best_path.begin(), best_path.end());
+  return best_path;
+}
+
+namespace {
+
+// Helper class to convert string into ids with deduplication.
+class InternalStrings {
+ public:
+  size_t GetId(const std::string& str) {
+    IdMap::iterator it = ids_.find(str);
+    if (it != ids_.end()) return it->second;
+    size_t id = ids_.size();
+    return ids_[str] = id;
+  }
+
+ private:
+  typedef std::map<std::string, size_t> IdMap;
+  IdMap ids_;
+};
+
+}  // namespace
+
+std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<std::string>& left,
+    const std::vector<std::string>& right) {
+  std::vector<size_t> left_ids, right_ids;
+  {
+    InternalStrings intern_table;
+    for (size_t i = 0; i < left.size(); ++i) {
+      left_ids.push_back(intern_table.GetId(left[i]));
+    }
+    for (size_t i = 0; i < right.size(); ++i) {
+      right_ids.push_back(intern_table.GetId(right[i]));
+    }
+  }
+  return CalculateOptimalEdits(left_ids, right_ids);
+}
+
+namespace {
+
+// Helper class that holds the state for one hunk and prints it out to the
+// stream.
+// It reorders adds/removes when possible to group all removes before all
+// adds. It also adds the hunk header before printint into the stream.
+class Hunk {
+ public:
+  Hunk(size_t left_start, size_t right_start)
+      : left_start_(left_start),
+        right_start_(right_start),
+        adds_(),
+        removes_(),
+        common_() {}
+
+  void PushLine(char edit, const char* line) {
+    switch (edit) {
+      case ' ':
+        ++common_;
+        FlushEdits();
+        hunk_.push_back(std::make_pair(' ', line));
+        break;
+      case '-':
+        ++removes_;
+        hunk_removes_.push_back(std::make_pair('-', line));
+        break;
+      case '+':
+        ++adds_;
+        hunk_adds_.push_back(std::make_pair('+', line));
+        break;
+    }
+  }
+
+  void PrintTo(std::ostream* os) {
+    PrintHeader(os);
+    FlushEdits();
+    for (std::list<std::pair<char, const char*> >::const_iterator it =
+             hunk_.begin();
+         it != hunk_.end(); ++it) {
+      *os << it->first << it->second << "\n";
+    }
+  }
+
+  bool has_edits() const { return adds_ || removes_; }
+
+ private:
+  void FlushEdits() {
+    hunk_.splice(hunk_.end(), hunk_removes_);
+    hunk_.splice(hunk_.end(), hunk_adds_);
+  }
+
+  // Print a unified diff header for one hunk.
+  // The format is
+  //   "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
+  // where the left/right parts are omitted if unnecessary.
+  void PrintHeader(std::ostream* ss) const {
+    *ss << "@@ ";
+    if (removes_) {
+      *ss << "-" << left_start_ << "," << (removes_ + common_);
+    }
+    if (removes_ && adds_) {
+      *ss << " ";
+    }
+    if (adds_) {
+      *ss << "+" << right_start_ << "," << (adds_ + common_);
+    }
+    *ss << " @@\n";
+  }
+
+  size_t left_start_, right_start_;
+  size_t adds_, removes_, common_;
+  std::list<std::pair<char, const char*> > hunk_, hunk_adds_, hunk_removes_;
+};
+
+}  // namespace
+
+// Create a list of diff hunks in Unified diff format.
+// Each hunk has a header generated by PrintHeader above plus a body with
+// lines prefixed with ' ' for no change, '-' for deletion and '+' for
+// addition.
+// 'context' represents the desired unchanged prefix/suffix around the diff.
+// If two hunks are close enough that their contexts overlap, then they are
+// joined into one hunk.
+std::string CreateUnifiedDiff(const std::vector<std::string>& left,
+                              const std::vector<std::string>& right,
+                              size_t context) {
+  const std::vector<EditType> edits = CalculateOptimalEdits(left, right);
+
+  size_t l_i = 0, r_i = 0, edit_i = 0;
+  std::stringstream ss;
+  while (edit_i < edits.size()) {
+    // Find first edit.
+    while (edit_i < edits.size() && edits[edit_i] == kMatch) {
+      ++l_i;
+      ++r_i;
+      ++edit_i;
+    }
+
+    // Find the first line to include in the hunk.
+    const size_t prefix_context = std::min(l_i, context);
+    Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
+    for (size_t i = prefix_context; i > 0; --i) {
+      hunk.PushLine(' ', left[l_i - i].c_str());
+    }
+
+    // Iterate the edits until we found enough suffix for the hunk or the input
+    // is over.
+    size_t n_suffix = 0;
+    for (; edit_i < edits.size(); ++edit_i) {
+      if (n_suffix >= context) {
+        // Continue only if the next hunk is very close.
+        auto it = edits.begin() + static_cast<int>(edit_i);
+        while (it != edits.end() && *it == kMatch) ++it;
+        if (it == edits.end() ||
+            static_cast<size_t>(it - edits.begin()) - edit_i >= context) {
+          // There is no next edit or it is too far away.
+          break;
+        }
+      }
+
+      EditType edit = edits[edit_i];
+      // Reset count when a non match is found.
+      n_suffix = edit == kMatch ? n_suffix + 1 : 0;
+
+      if (edit == kMatch || edit == kRemove || edit == kReplace) {
+        hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
+      }
+      if (edit == kAdd || edit == kReplace) {
+        hunk.PushLine('+', right[r_i].c_str());
+      }
+
+      // Advance indices, depending on edit type.
+      l_i += edit != kAdd;
+      r_i += edit != kRemove;
+    }
+
+    if (!hunk.has_edits()) {
+      // We are done. We don't want this hunk.
+      break;
+    }
+
+    hunk.PrintTo(&ss);
+  }
+  return ss.str();
+}
+
+}  // namespace edit_distance
+
+namespace {
+
+// The string representation of the values received in EqFailure() are already
+// escaped. Split them on escaped '\n' boundaries. Leave all other escaped
+// characters the same.
+std::vector<std::string> SplitEscapedString(const std::string& str) {
+  std::vector<std::string> lines;
+  size_t start = 0, end = str.size();
+  if (end > 2 && str[0] == '"' && str[end - 1] == '"') {
+    ++start;
+    --end;
+  }
+  bool escaped = false;
+  for (size_t i = start; i + 1 < end; ++i) {
+    if (escaped) {
+      escaped = false;
+      if (str[i] == 'n') {
+        lines.push_back(str.substr(start, i - start - 1));
+        start = i + 1;
+      }
+    } else {
+      escaped = str[i] == '\\';
+    }
+  }
+  lines.push_back(str.substr(start, end - start));
+  return lines;
+}
+
+}  // namespace
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   lhs_expression: "foo"
+//   rhs_expression: "bar"
+//   lhs_value:      "5"
+//   rhs_value:      "6"
+//
+// The ignoring_case parameter is true if and only if the assertion is a
+// *_STRCASEEQ*.  When it's true, the string "Ignoring case" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* lhs_expression,
+                          const char* rhs_expression,
+                          const std::string& lhs_value,
+                          const std::string& rhs_value, bool ignoring_case) {
+  Message msg;
+  msg << "Expected equality of these values:";
+  msg << "\n  " << lhs_expression;
+  if (lhs_value != lhs_expression) {
+    msg << "\n    Which is: " << lhs_value;
+  }
+  msg << "\n  " << rhs_expression;
+  if (rhs_value != rhs_expression) {
+    msg << "\n    Which is: " << rhs_value;
+  }
+
+  if (ignoring_case) {
+    msg << "\nIgnoring case";
+  }
+
+  if (!lhs_value.empty() && !rhs_value.empty()) {
+    const std::vector<std::string> lhs_lines = SplitEscapedString(lhs_value);
+    const std::vector<std::string> rhs_lines = SplitEscapedString(rhs_value);
+    if (lhs_lines.size() > 1 || rhs_lines.size() > 1) {
+      msg << "\nWith diff:\n"
+          << edit_distance::CreateUnifiedDiff(lhs_lines, rhs_lines);
+    }
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result, const char* expression_text,
+    const char* actual_predicate_value, const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0') msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2,
+                                     const char* abs_error_expr, double val1,
+                                     double val2, double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // Find the value which is closest to zero.
+  const double min_abs = std::min(fabs(val1), fabs(val2));
+  // Find the distance to the next double from that value.
+  const double epsilon =
+      nextafter(min_abs, std::numeric_limits<double>::infinity()) - min_abs;
+  // Detect the case where abs_error is so small that EXPECT_NEAR is
+  // effectively the same as EXPECT_EQUAL, and give an informative error
+  // message so that the situation can be more easily understood without
+  // requiring exotic floating-point knowledge.
+  // Don't do an epsilon check if abs_error is zero because that implies
+  // that an equality check was actually intended.
+  if (!(std::isnan)(val1) && !(std::isnan)(val2) && abs_error > 0 &&
+      abs_error < epsilon) {
+    return AssertionFailure()
+           << "The difference between " << expr1 << " and " << expr2 << " is "
+           << diff << ", where\n"
+           << expr1 << " evaluates to " << val1 << ",\n"
+           << expr2 << " evaluates to " << val2 << ".\nThe abs_error parameter "
+           << abs_error_expr << " evaluates to " << abs_error
+           << " which is smaller than the minimum distance between doubles for "
+              "numbers of this magnitude which is "
+           << epsilon
+           << ", thus making this EXPECT_NEAR check equivalent to "
+              "EXPECT_EQUAL. Consider using EXPECT_DOUBLE_EQ instead.";
+  }
+  return AssertionFailure()
+         << "The difference between " << expr1 << " and " << expr2 << " is "
+         << diff << ", which exceeds " << abs_error_expr << ", where\n"
+         << expr1 << " evaluates to " << val1 << ",\n"
+         << expr2 << " evaluates to " << val2 << ", and\n"
+         << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1, const char* expr2,
+                                RawType val1, RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+         << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+         << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+         << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2, float val1,
+                        float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2, double val1,
+                         double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* lhs_expression,
+                               const char* rhs_expression, const char* lhs,
+                               const char* rhs) {
+  if (String::CStringEquals(lhs, rhs)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(lhs_expression, rhs_expression, PrintToString(lhs),
+                   PrintToString(rhs), false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* lhs_expression,
+                                   const char* rhs_expression, const char* lhs,
+                                   const char* rhs) {
+  if (String::CaseInsensitiveCStringEquals(lhs, rhs)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(lhs_expression, rhs_expression, PrintToString(lhs),
+                   PrintToString(rhs), true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression, const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+           << "Expected: (" << s1_expression << ") != (" << s2_expression
+           << "), actual: \"" << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression, const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+           << "Expected: (" << s1_expression << ") != (" << s2_expression
+           << ") (ignoring case), actual: \"" << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true if and only if needle
+// is a substring of haystack.  NULL is considered a substring of
+// itself only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == nullptr || haystack == nullptr) return needle == haystack;
+
+  return strstr(haystack, needle) != nullptr;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == nullptr || haystack == nullptr) return needle == haystack;
+
+  return wcsstr(haystack, needle) != nullptr;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle, const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(bool expected_to_be_substring,
+                                const char* needle_expr,
+                                const char* haystack_expr,
+                                const StringType& needle,
+                                const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+         << "Value of: " << needle_expr << "\n"
+         << "  Actual: " << begin_string_quote << needle << "\"\n"
+         << "Expected: " << (expected_to_be_substring ? "" : "not ")
+         << "a substring of " << haystack_expr << "\n"
+         << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
+                            const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
+                            const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(const char* needle_expr,
+                               const char* haystack_expr, const char* needle,
+                               const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(const char* needle_expr,
+                               const char* haystack_expr, const wchar_t* needle,
+                               const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
+                            const ::std::string& needle,
+                            const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(const char* needle_expr,
+                               const char* haystack_expr,
+                               const ::std::string& needle,
+                               const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
+                            const ::std::wstring& needle,
+                            const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(const char* needle_expr,
+                               const char* haystack_expr,
+                               const ::std::wstring& needle,
+                               const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#ifdef GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr, const char* expected,
+                                     long hr) {  // NOLINT
+#if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_TV_TITLE)
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+#else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags =
+      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = {'\0'};
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          static_cast<DWORD>(hr),  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,    // buf size
+                                          nullptr);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+       --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const std::string error_hex("0x" + String::FormatHexInt(hr));
+  return ::testing::AssertionFailure()
+         << "Expected: " << expr << " " << expected << ".\n"
+         << "  Actual: " << error_hex << " " << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint1 = (static_cast<uint32_t>(1) << 7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint2 = (static_cast<uint32_t>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint3 =
+    (static_cast<uint32_t>(1) << (4 + 2 * 6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint4 =
+    (static_cast<uint32_t>(1) << (3 + 3 * 6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline uint32_t ChopLowBits(uint32_t* bits, int n) {
+  const uint32_t low_bits = *bits & ((static_cast<uint32_t>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type uint32_t because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+std::string CodePointToUtf8(uint32_t code_point) {
+  if (code_point > kMaxCodePoint4) {
+    return "(Invalid Unicode 0x" + String::FormatHexUInt32(code_point) + ")";
+  }
+
+  char str[5];  // Big enough for the largest valid code point.
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);  // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else {  // code_point <= kMaxCodePoint4
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  }
+  return str;
+}
+
+// The following two functions only make sense if the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 && (first & 0xFC00) == 0xD800 &&
+         (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline uint32_t CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                      wchar_t second) {
+  const auto first_u = static_cast<uint32_t>(first);
+  const auto second_u = static_cast<uint32_t>(second);
+  const uint32_t mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2)
+             ? (((first_u & mask) << 10) | (second_u & mask)) + 0x10000
+             :
+             // This function should not be called when the condition is
+             // false, but we provide a sensible default in case it is.
+             first_u;
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1) num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    uint32_t unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point =
+          CreateCodePointFromUtf16SurrogatePair(str[i], str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<uint32_t>(str[i]);
+    }
+
+    stream << CodePointToUtf8(unicode_code_point);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to an std::string using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+std::string String::ShowWideCString(const wchar_t* wide_c_str) {
+  if (wide_c_str == nullptr) return "(null)";
+
+  return internal::WideStringToUtf8(wide_c_str, -1);
+}
+
+// Compares two wide C strings.  Returns true if and only if they have the
+// same content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+
+  if (rhs == nullptr) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* lhs_expression,
+                               const char* rhs_expression, const wchar_t* lhs,
+                               const wchar_t* rhs) {
+  if (String::WideCStringEquals(lhs, rhs)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(lhs_expression, rhs_expression, PrintToString(lhs),
+                   PrintToString(rhs), false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression, const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure()
+         << "Expected: (" << s1_expression << ") != (" << s2_expression
+         << "), actual: " << PrintToString(s1) << " vs " << PrintToString(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true if and only if they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+  if (rhs == nullptr) return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+// Compares two wide C strings, ignoring case.  Returns true if and only if they
+// have the same content.
+//
+// Unlike wcscasecmp(), this function can handle NULL argument(s).
+// A NULL C string is considered different to any non-NULL wide C string,
+// including the empty string.
+// NB: The implementations on different platforms slightly differ.
+// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+// environment variable. On GNU platform this method uses wcscasecmp
+// which compares according to LC_CTYPE category of the current locale.
+// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+// current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+
+  if (rhs == nullptr) return false;
+
+#ifdef GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif defined(GTEST_OS_LINUX) && !defined(GTEST_OS_LINUX_ANDROID)
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(static_cast<wint_t>(*lhs++));
+    right = towlower(static_cast<wint_t>(*rhs++));
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Returns true if and only if str ends with the given suffix, ignoring case.
+// Any string is considered to end with an empty suffix.
+bool String::EndsWithCaseInsensitive(const std::string& str,
+                                     const std::string& suffix) {
+  const size_t str_len = str.length();
+  const size_t suffix_len = suffix.length();
+  return (str_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
+                                      suffix.c_str());
+}
+
+// Formats an int value as "%02d".
+std::string String::FormatIntWidth2(int value) {
+  return FormatIntWidthN(value, 2);
+}
+
+// Formats an int value to given width with leading zeros.
+std::string String::FormatIntWidthN(int value, int width) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(width) << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexUInt32(uint32_t value) {
+  std::stringstream ss;
+  ss << std::hex << std::uppercase << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexInt(int value) {
+  return FormatHexUInt32(static_cast<uint32_t>(value));
+}
+
+// Formats a byte as "%02X".
+std::string String::FormatByte(unsigned char value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
+     << static_cast<unsigned int>(value);
+  return ss.str();
+}
+
+// Converts the buffer in a stringstream to an std::string, converting NUL
+// bytes to "\\0" along the way.
+std::string StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  std::string result;
+  result.reserve(static_cast<size_t>(2 * (end - start)));
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      result += "\\0";  // Replaces NUL with "\\0";
+    } else {
+      result += *ch;
+    }
+  }
+
+  return result;
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+std::string AppendUserMessage(const std::string& gtest_msg,
+                              const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const std::string user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+  if (gtest_msg.empty()) {
+    return user_msg_string;
+  }
+  return gtest_msg + "\n" + user_msg_string;
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0), start_timestamp_(0), elapsed_time_(0) {}
+
+// D'tor.
+TestResult::~TestResult() = default;
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count()) internal::posix::Abort();
+  return test_part_results_.at(static_cast<size_t>(i));
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count()) internal::posix::Abort();
+  return test_properties_.at(static_cast<size_t>(i));
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() { test_part_results_.clear(); }
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const std::string& xml_element,
+                                const TestProperty& test_property) {
+  if (!ValidateTestProperty(xml_element, test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properties_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// The list of reserved attributes used in the <testsuites> element of XML
+// output.
+static const char* const kReservedTestSuitesAttributes[] = {
+    "disabled",    "errors", "failures", "name",
+    "random_seed", "tests",  "time",     "timestamp"};
+
+// The list of reserved attributes used in the <testsuite> element of XML
+// output.
+static const char* const kReservedTestSuiteAttributes[] = {
+    "disabled", "errors", "failures",  "name",
+    "tests",    "time",   "timestamp", "skipped"};
+
+// The list of reserved attributes used in the <testcase> element of XML output.
+static const char* const kReservedTestCaseAttributes[] = {
+    "classname",  "name",        "status", "time",
+    "type_param", "value_param", "file",   "line"};
+
+// Use a slightly different set for allowed output to ensure existing tests can
+// still RecordProperty("result") or RecordProperty("timestamp")
+static const char* const kReservedOutputTestCaseAttributes[] = {
+    "classname",   "name", "status", "time",   "type_param",
+    "value_param", "file", "line",   "result", "timestamp"};
+
+template <size_t kSize>
+std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
+  return std::vector<std::string>(array, array + kSize);
+}
+
+static std::vector<std::string> GetReservedAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+
+#if GTEST_HAS_FILE_SYSTEM
+// TODO(jdesprez): Merge the two getReserved attributes once skip is improved
+// This function is only used when file systems are enabled.
+static std::vector<std::string> GetReservedOutputAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedOutputTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+#endif
+
+static std::string FormatWordList(const std::vector<std::string>& words) {
+  Message word_list;
+  for (size_t i = 0; i < words.size(); ++i) {
+    if (i > 0 && words.size() > 2) {
+      word_list << ", ";
+    }
+    if (i == words.size() - 1) {
+      word_list << "and ";
+    }
+    word_list << "'" << words[i] << "'";
+  }
+  return word_list.GetString();
+}
+
+static bool ValidateTestPropertyName(
+    const std::string& property_name,
+    const std::vector<std::string>& reserved_names) {
+  if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
+      reserved_names.end()) {
+    ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
+                  << " (" << FormatWordList(reserved_names)
+                  << " are reserved by " << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Adds a failure if the key is a reserved attribute of the element named
+// xml_element.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const std::string& xml_element,
+                                      const TestProperty& test_property) {
+  return ValidateTestPropertyName(test_property.key(),
+                                  GetReservedAttributesForElement(xml_element));
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true off the test part was skipped.
+static bool TestPartSkipped(const TestPartResult& result) {
+  return result.skipped();
+}
+
+// Returns true if and only if the test was skipped.
+bool TestResult::Skipped() const {
+  return !Failed() && CountIf(test_part_results_, TestPartSkipped) > 0;
+}
+
+// Returns true if and only if the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed()) return true;
+  }
+  return false;
+}
+
+// Returns true if and only if the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true if and only if the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true if and only if the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true if and only if the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the states of all flags.
+Test::Test() : gtest_flag_saver_(new GTEST_FLAG_SAVER_) {}
+
+// The d'tor restores the states of all flags.  The actual work is
+// done by the d'tor of the gtest_flag_saver_ field, and thus not
+// visible here.
+Test::~Test() = default;
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, const std::string& value) {
+  UnitTest::GetInstance()->RecordProperty(key, value);
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      nullptr,  // No info about the source file where the exception occurred.
+      -1,       // We have no info on which line caused the exception.
+      message,
+      "");  // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test suite to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test suite.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestSuite* const test_suite = impl->current_test_suite();
+
+  // Info about the first test in the current test suite.
+  const TestInfo* const first_test_info = test_suite->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // Both TEST and TEST_F appear in same test suite, which is incorrect.
+      // Tell the user how to fix this.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test suite must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test suite is\n"
+          << "illegal.  In test suite " << this_test_info->test_suite_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // Two fixture classes with the same name appear in two different
+      // namespaces, which is not allowed. Tell the user how to fix this.
+      ADD_FAILURE()
+          << "All tests in the same test suite must use the same test fixture\n"
+          << "class.  However, in test suite "
+          << this_test_info->test_suite_name() << ",\n"
+          << "you defined test " << first_test_name << " and test "
+          << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test suites.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+namespace internal {
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static std::string FormatCxxExceptionMessage(const char* description,
+                                             const char* location) {
+  Message message;
+  if (description != nullptr) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+GoogleTestFailureException::GoogleTestFailureException(
+    const TestPartResult& failure)
+    : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
+                                              const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestProcessSEH(  // NOLINT
+      GetExceptionCode(), location)) {
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
+                                           const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG_GET(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const AssertionException&) {  // NOLINT
+      // This failure was reported already.
+    } catch (const internal::GoogleTestFailureException&) {  // NOLINT
+      // This exception type can only be thrown by a failed Google
+      // Test assertion with the intention of letting another testing
+      // framework catch it.  Therefore we just re-throw it.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(nullptr, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful and didn't call
+  // GTEST_SKIP().
+  if (!HasFatalFailure() && !IsSkipped()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(this, &Test::TestBody,
+                                                  "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::TearDown,
+                                                "TearDown()");
+}
+
+// Returns true if and only if the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true if and only if the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()
+      ->current_test_result()
+      ->HasNonfatalFailure();
+}
+
+// Returns true if and only if the current test was skipped.
+bool Test::IsSkipped() {
+  return internal::GetUnitTestImpl()->current_test_result()->Skipped();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+TestInfo::TestInfo(std::string a_test_suite_name, std::string a_name,
+                   const char* a_type_param, const char* a_value_param,
+                   internal::CodeLocation a_code_location,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_suite_name_(std::move(a_test_suite_name)),
+      name_(std::move(a_name)),
+      type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
+      value_param_(a_value_param ? new std::string(a_value_param) : nullptr),
+      location_(std::move(a_code_location)),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      is_in_another_shard_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_suite_name:  name of the test suite
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   code_location:    code location where the test is defined
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test suite
+//   tear_down_tc:     pointer to the function that tears down the test suite
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    std::string test_suite_name, const char* name, const char* type_param,
+    const char* value_param, CodeLocation code_location,
+    TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
+    TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(std::move(test_suite_name), name, type_param, value_param,
+                   std::move(code_location), fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+void ReportInvalidTestSuiteType(const char* test_suite_name,
+                                const CodeLocation& code_location) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test suite " << test_suite_name << ".\n"
+      << "All tests in the same test suite must use the same test fixture\n"
+      << "class.  However, in test suite " << test_suite_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test suites.";
+
+  GTEST_LOG_(ERROR) << FormatFileLocation(code_location.file.c_str(),
+                                          code_location.line)
+                    << " " << errors.GetString();
+}
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_SUITE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    type_parameterized_test_registry_.CheckForInstantiations();
+    parameterized_tests_registered_ = true;
+  }
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+  if (!should_run_) {
+    if (is_disabled_ && matches_filter_) repeater->OnTestDisabled(*this);
+    return;
+  }
+
+  // Tells UnitTest where to store test result.
+  UnitTest::GetInstance()->set_current_test_info(this);
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+  result_.set_start_timestamp(internal::GetTimeInMillis());
+  internal::Timer timer;
+  UnitTest::GetInstance()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test if the constructor didn't generate a fatal failure or invoke
+  // GTEST_SKIP().
+  // Note that the object will not be null
+  if (!Test::HasFatalFailure() && !Test::IsSkipped()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  if (test != nullptr) {
+    // Deletes the test object.
+    UnitTest::GetInstance()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        test, &Test::DeleteSelf_, "the test fixture's destructor");
+  }
+
+  result_.set_elapsed_time(timer.Elapsed());
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  UnitTest::GetInstance()->set_current_test_info(nullptr);
+}
+
+// Skip and records a skipped test result for this object.
+void TestInfo::Skip() {
+  if (!should_run_) return;
+
+  UnitTest::GetInstance()->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TestPartResult test_part_result =
+      TestPartResult(TestPartResult::kSkip, this->file(), this->line(), "");
+  internal::GetUnitTestImpl()
+      ->GetTestPartResultReporterForCurrentThread()
+      ->ReportTestPartResult(test_part_result);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+  UnitTest::GetInstance()->set_current_test_info(nullptr);
+}
+
+// class TestSuite
+
+// Gets the number of successful tests in this test suite.
+int TestSuite::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of successful tests in this test suite.
+int TestSuite::skipped_test_count() const {
+  return CountIf(test_info_list_, TestSkipped);
+}
+
+// Gets the number of failed tests in this test suite.
+int TestSuite::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int TestSuite::reportable_disabled_test_count() const {
+  return CountIf(test_info_list_, TestReportableDisabled);
+}
+
+// Gets the number of disabled tests in this test suite.
+int TestSuite::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int TestSuite::reportable_test_count() const {
+  return CountIf(test_info_list_, TestReportable);
+}
+
+// Get the number of tests in this test suite that should run.
+int TestSuite::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestSuite::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestSuite with the given name.
+//
+// Arguments:
+//
+//   a_name:       name of the test suite
+//   a_type_param: the name of the test suite's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test suite.
+//   set_up_tc:    pointer to the function that sets up the test suite
+//   tear_down_tc: pointer to the function that tears down the test suite
+TestSuite::TestSuite(const std::string& a_name, const char* a_type_param,
+                     internal::SetUpTestSuiteFunc set_up_tc,
+                     internal::TearDownTestSuiteFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      start_timestamp_(0),
+      elapsed_time_(0) {}
+
+// Destructor of TestSuite.
+TestSuite::~TestSuite() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestSuite::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? nullptr : test_info_list_[static_cast<size_t>(index)];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestSuite::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? nullptr : test_info_list_[static_cast<size_t>(index)];
+}
+
+// Adds a test to this test suite.  Will delete the test upon
+// destruction of the TestSuite object.
+void TestSuite::AddTestInfo(TestInfo* test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestSuite.
+void TestSuite::Run() {
+  if (!should_run_) return;
+
+  UnitTest::GetInstance()->set_current_test_suite(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Ensure our tests are in a deterministic order.
+  //
+  // We do this by sorting lexicographically on (file, line number), providing
+  // an order matching what the user can see in the source code.
+  //
+  // In the common case the line number comparison shouldn't be necessary,
+  // because the registrations made by the TEST macro are executed in order
+  // within a translation unit. But this is not true of the manual registration
+  // API, and in more exotic scenarios a single file may be part of multiple
+  // translation units.
+  std::stable_sort(test_info_list_.begin(), test_info_list_.end(),
+                   [](const TestInfo* const a, const TestInfo* const b) {
+                     if (const int result = std::strcmp(a->file(), b->file())) {
+                       return result < 0;
+                     }
+
+                     return a->line() < b->line();
+                   });
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteStart(*this);
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseStart(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  UnitTest::GetInstance()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
+
+  const bool skip_all =
+      ad_hoc_test_result().Failed() || ad_hoc_test_result().Skipped();
+
+  start_timestamp_ = internal::GetTimeInMillis();
+  internal::Timer timer;
+  for (int i = 0; i < total_test_count(); i++) {
+    if (skip_all) {
+      GetMutableTestInfo(i)->Skip();
+    } else {
+      GetMutableTestInfo(i)->Run();
+    }
+    if (GTEST_FLAG_GET(fail_fast) &&
+        GetMutableTestInfo(i)->result()->Failed()) {
+      for (int j = i + 1; j < total_test_count(); j++) {
+        GetMutableTestInfo(j)->Skip();
+      }
+      break;
+    }
+  }
+  elapsed_time_ = timer.Elapsed();
+
+  UnitTest::GetInstance()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteEnd(*this);
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseEnd(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  UnitTest::GetInstance()->set_current_test_suite(nullptr);
+}
+
+// Skips all tests under this TestSuite.
+void TestSuite::Skip() {
+  if (!should_run_) return;
+
+  UnitTest::GetInstance()->set_current_test_suite(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteStart(*this);
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseStart(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Skip();
+  }
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteEnd(*this);
+  // Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseEnd(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  UnitTest::GetInstance()->set_current_test_suite(nullptr);
+}
+
+// Clears the results of all tests in this test suite.
+void TestSuite::ClearResult() {
+  ad_hoc_test_result_.Clear();
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test suite.
+void TestSuite::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestSuite::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static std::string FormatCountableNoun(int count, const char* singular_form,
+                                       const char* plural_form) {
+  return internal::StreamableToString(count) + " " +
+         (count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static std::string FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test suites.
+static std::string FormatTestSuiteCount(int test_suite_count) {
+  return FormatCountableNoun(test_suite_count, "test suite", "test suites");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char* TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSkip:
+      return "Skipped\n";
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+namespace internal {
+namespace {
+enum class GTestColor { kDefault, kRed, kGreen, kYellow };
+}  // namespace
+
+// Prints a TestPartResult to an std::string.
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message() << internal::FormatFileLocation(
+                           test_part_result.file_name(),
+                           test_part_result.line_number())
+                    << " "
+                    << TestPartResultTypeToString(test_part_result.type())
+                    << test_part_result.message())
+      .GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const std::string& result = PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE)
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) &&       \
+    !defined(GTEST_OS_WINDOWS_GAMES) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_MINGW)
+
+// Returns the character attribute for the given color.
+static WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case GTestColor::kRed:
+      return FOREGROUND_RED;
+    case GTestColor::kGreen:
+      return FOREGROUND_GREEN;
+    case GTestColor::kYellow:
+      return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:
+      return 0;
+  }
+}
+
+static int GetBitOffset(WORD color_mask) {
+  if (color_mask == 0) return 0;
+
+  int bitOffset = 0;
+  while ((color_mask & 1) == 0) {
+    color_mask >>= 1;
+    ++bitOffset;
+  }
+  return bitOffset;
+}
+
+static WORD GetNewColor(GTestColor color, WORD old_color_attrs) {
+  // Let's reuse the BG
+  static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
+                                      BACKGROUND_RED | BACKGROUND_INTENSITY;
+  static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
+                                      FOREGROUND_RED | FOREGROUND_INTENSITY;
+  const WORD existing_bg = old_color_attrs & background_mask;
+
+  WORD new_color =
+      GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY;
+  static const int bg_bitOffset = GetBitOffset(background_mask);
+  static const int fg_bitOffset = GetBitOffset(foreground_mask);
+
+  if (((new_color & background_mask) >> bg_bitOffset) ==
+      ((new_color & foreground_mask) >> fg_bitOffset)) {
+    new_color ^= FOREGROUND_INTENSITY;  // invert intensity
+  }
+  return new_color;
+}
+
+#else
+
+// Returns the ANSI color code for the given color. GTestColor::kDefault is
+// an invalid input.
+static const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case GTestColor::kRed:
+      return "1";
+    case GTestColor::kGreen:
+      return "2";
+    case GTestColor::kYellow:
+      return "3";
+    default:
+      assert(false);
+      return "9";
+  }
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true if and only if Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  std::string c = GTEST_FLAG_GET(color);
+  const char* const gtest_color = c.c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        term != nullptr && (String::CStringEquals(term, "xterm") ||
+                            String::CStringEquals(term, "xterm-color") ||
+                            String::CStringEquals(term, "xterm-kitty") ||
+                            String::CStringEquals(term, "alacritty") ||
+                            String::CStringEquals(term, "screen") ||
+                            String::CStringEquals(term, "tmux") ||
+                            String::CStringEquals(term, "rxvt-unicode") ||
+                            String::CStringEquals(term, "linux") ||
+                            String::CStringEquals(term, "cygwin") ||
+                            String::EndsWithCaseInsensitive(term, "-256color"));
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+         String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+         String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+         String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+
+GTEST_ATTRIBUTE_PRINTF_(2, 3)
+static void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+  static const bool in_color_mode =
+      // We don't condition this on GTEST_HAS_FILE_SYSTEM because we still need
+      // to be able to detect terminal I/O regardless.
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+
+  const bool use_color = in_color_mode && (color != GTestColor::kDefault);
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) &&       \
+    !defined(GTEST_OS_WINDOWS_GAMES) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_MINGW)
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+  const WORD new_color = GetNewColor(color, old_color_attrs);
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle, new_color);
+
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+// Text printed in Google Test's text output and --gtest_list_tests
+// output to label the type parameter and value parameter for a test.
+static const char kTypeParamLabel[] = "TypeParam";
+static const char kValueParamLabel[] = "GetParam()";
+
+static void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != nullptr || value_param != nullptr) {
+    printf(", where ");
+    if (type_param != nullptr) {
+      printf("%s = %s", kTypeParamLabel, type_param);
+      if (value_param != nullptr) printf(" and ");
+    }
+    if (value_param != nullptr) {
+      printf("%s = %s", kValueParamLabel, value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() = default;
+  static void PrintTestName(const char* test_suite, const char* test) {
+    printf("%s.%s", test_suite, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationStart(const UnitTest& unit_test, int iteration) override;
+  void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override;
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& test_case) override;
+#else
+  void OnTestSuiteStart(const TestSuite& test_suite) override;
+#endif  // OnTestCaseStart
+
+  void OnTestStart(const TestInfo& test_info) override;
+  void OnTestDisabled(const TestInfo& test_info) override;
+
+  void OnTestPartResult(const TestPartResult& result) override;
+  void OnTestEnd(const TestInfo& test_info) override;
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& test_case) override;
+#else
+  void OnTestSuiteEnd(const TestSuite& test_suite) override;
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override;
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+  static void PrintFailedTestSuites(const UnitTest& unit_test);
+  static void PrintSkippedTests(const UnitTest& unit_test);
+};
+
+// Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG_GET(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  std::string f = GTEST_FLAG_GET(filter);
+  const char* const filter = f.c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(GTestColor::kYellow, "Note: %s filter = %s\n", GTEST_NAME_,
+                  filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const int32_t shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(GTestColor::kYellow, "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG_GET(shuffle)) {
+    ColoredPrintf(GTestColor::kYellow,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(GTestColor::kGreen, "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case.name());
+  if (test_case.type_param() == nullptr) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
+  }
+  fflush(stdout);
+}
+#else
+void PrettyUnitTestResultPrinter::OnTestSuiteStart(
+    const TestSuite& test_suite) {
+  const std::string counts =
+      FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_suite.name());
+  if (test_suite.type_param() == nullptr) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_suite.type_param());
+  }
+  fflush(stdout);
+}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(GTestColor::kGreen, "[ RUN      ] ");
+  PrintTestName(test_info.test_suite_name(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestDisabled(const TestInfo& test_info) {
+  ColoredPrintf(GTestColor::kYellow, "[ DISABLED ] ");
+  PrintTestName(test_info.test_suite_name(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  switch (result.type()) {
+    // If the test part succeeded, we don't need to do anything.
+    case TestPartResult::kSuccess:
+      return;
+    default:
+      // Print failure message from the assertion
+      // (e.g. expected this and got that).
+      PrintTestPartResult(result);
+      fflush(stdout);
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(GTestColor::kGreen, "[       OK ] ");
+  } else if (test_info.result()->Skipped()) {
+    ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+  } else {
+    ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+  }
+  PrintTestName(test_info.test_suite_name(), test_info.name());
+  if (test_info.result()->Failed()) PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG_GET(print_time)) {
+    printf(" (%s ms)\n",
+           internal::StreamableToString(test_info.result()->elapsed_time())
+               .c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG_GET(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_case.name(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+#else
+void PrettyUnitTestResultPrinter::OnTestSuiteEnd(const TestSuite& test_suite) {
+  if (!GTEST_FLAG_GET(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_suite.name(),
+         internal::StreamableToString(test_suite.elapsed_time()).c_str());
+  fflush(stdout);
+}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+  printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    if (!test_suite.should_run() || (test_suite.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_suite.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_suite.GetTestInfo(j);
+      if (!test_info.should_run() || !test_info.result()->Failed()) {
+        continue;
+      }
+      ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+      printf("%s.%s", test_suite.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+  printf("\n%2d FAILED %s\n", failed_test_count,
+         failed_test_count == 1 ? "TEST" : "TESTS");
+}
+
+// Internal helper for printing the list of test suite failures not covered by
+// PrintFailedTests.
+void PrettyUnitTestResultPrinter::PrintFailedTestSuites(
+    const UnitTest& unit_test) {
+  int suite_failure_count = 0;
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    if (!test_suite.should_run()) {
+      continue;
+    }
+    if (test_suite.ad_hoc_test_result().Failed()) {
+      ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+      printf("%s: SetUpTestSuite or TearDownTestSuite\n", test_suite.name());
+      ++suite_failure_count;
+    }
+  }
+  if (suite_failure_count > 0) {
+    printf("\n%2d FAILED TEST %s\n", suite_failure_count,
+           suite_failure_count == 1 ? "SUITE" : "SUITES");
+  }
+}
+
+// Internal helper for printing the list of skipped tests.
+void PrettyUnitTestResultPrinter::PrintSkippedTests(const UnitTest& unit_test) {
+  const int skipped_test_count = unit_test.skipped_test_count();
+  if (skipped_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    if (!test_suite.should_run() || (test_suite.skipped_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_suite.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_suite.GetTestInfo(j);
+      if (!test_info.should_run() || !test_info.result()->Skipped()) {
+        continue;
+      }
+      ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+      printf("%s.%s", test_suite.name(), test_info.name());
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(GTestColor::kGreen, "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
+  if (GTEST_FLAG_GET(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(GTestColor::kGreen, "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  const int skipped_test_count = unit_test.skipped_test_count();
+  if (skipped_test_count > 0) {
+    ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+    printf("%s, listed below:\n", FormatTestCount(skipped_test_count).c_str());
+    PrintSkippedTests(unit_test);
+  }
+
+  if (!unit_test.Passed()) {
+    PrintFailedTests(unit_test);
+    PrintFailedTestSuites(unit_test);
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG_GET(also_run_disabled_tests)) {
+    if (unit_test.Passed()) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(GTestColor::kYellow, "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled, num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// This class implements the TestEventListener interface.
+//
+// Class BriefUnitTestResultPrinter is copyable.
+class BriefUnitTestResultPrinter : public TestEventListener {
+ public:
+  BriefUnitTestResultPrinter() = default;
+  static void PrintTestName(const char* test_suite, const char* test) {
+    printf("%s.%s", test_suite, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int /*iteration*/) override {}
+  void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& /*test_case*/) override {}
+#else
+  void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {}
+#endif  // OnTestCaseStart
+
+  void OnTestStart(const TestInfo& /*test_info*/) override {}
+  void OnTestDisabled(const TestInfo& /*test_info*/) override {}
+
+  void OnTestPartResult(const TestPartResult& result) override;
+  void OnTestEnd(const TestInfo& test_info) override;
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& /*test_case*/) override {}
+#else
+  void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
+};
+
+// Called after an assertion failure.
+void BriefUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  switch (result.type()) {
+    // If the test part succeeded, we don't need to do anything.
+    case TestPartResult::kSuccess:
+      return;
+    default:
+      // Print failure message from the assertion
+      // (e.g. expected this and got that).
+      PrintTestPartResult(result);
+      fflush(stdout);
+  }
+}
+
+void BriefUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Failed()) {
+    ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+    PrintTestName(test_info.test_suite_name(), test_info.name());
+    PrintFullTestCommentIfPresent(test_info);
+
+    if (GTEST_FLAG_GET(print_time)) {
+      printf(" (%s ms)\n",
+             internal::StreamableToString(test_info.result()->elapsed_time())
+                 .c_str());
+    } else {
+      printf("\n");
+    }
+    fflush(stdout);
+  }
+}
+
+void BriefUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                    int /*iteration*/) {
+  ColoredPrintf(GTestColor::kGreen, "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
+  if (GTEST_FLAG_GET(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(GTestColor::kGreen, "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  const int skipped_test_count = unit_test.skipped_test_count();
+  if (skipped_test_count > 0) {
+    ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+    printf("%s.\n", FormatTestCount(skipped_test_count).c_str());
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG_GET(also_run_disabled_tests)) {
+    if (unit_test.Passed()) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(GTestColor::kYellow, "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled, num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End BriefUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  ~TestEventRepeater() override;
+  void Append(TestEventListener* listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  void OnTestProgramStart(const UnitTest& parameter) override;
+  void OnTestIterationStart(const UnitTest& unit_test, int iteration) override;
+  void OnEnvironmentsSetUpStart(const UnitTest& parameter) override;
+  void OnEnvironmentsSetUpEnd(const UnitTest& parameter) override;
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestSuite& parameter) override;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestSuiteStart(const TestSuite& parameter) override;
+  void OnTestStart(const TestInfo& parameter) override;
+  void OnTestDisabled(const TestInfo& parameter) override;
+  void OnTestPartResult(const TestPartResult& parameter) override;
+  void OnTestEnd(const TestInfo& parameter) override;
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& parameter) override;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestSuiteEnd(const TestSuite& parameter) override;
+  void OnEnvironmentsTearDownStart(const UnitTest& parameter) override;
+  void OnEnvironmentsTearDownEnd(const UnitTest& parameter) override;
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void OnTestProgramEnd(const UnitTest& parameter) override;
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  TestEventRepeater(const TestEventRepeater&) = delete;
+  TestEventRepeater& operator=(const TestEventRepeater&) = delete;
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener* listener) {
+  listeners_.push_back(listener);
+}
+
+TestEventListener* TestEventRepeater::Release(TestEventListener* listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + static_cast<int>(i));
+      return listener;
+    }
+  }
+
+  return nullptr;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type)              \
+  void TestEventRepeater::Name(const Type& parameter) { \
+    if (forwarding_enabled_) {                          \
+      for (size_t i = 0; i < listeners_.size(); i++) {  \
+        listeners_[i]->Name(parameter);                 \
+      }                                                 \
+    }                                                   \
+  }
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type)      \
+  void TestEventRepeater::Name(const Type& parameter) { \
+    if (forwarding_enabled_) {                          \
+      for (size_t i = listeners_.size(); i != 0; i--) { \
+        listeners_[i - 1]->Name(parameter);             \
+      }                                                 \
+    }                                                   \
+  }
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestSuite)
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestDisabled, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestSuite)
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REVERSE_REPEATER_METHOD_(OnTestSuiteEnd, TestSuite)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = listeners_.size(); i > 0; i--) {
+      listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+#if GTEST_HAS_FILE_SYSTEM
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void ListTestsMatchingFilter(const std::vector<TestSuite*>& test_suites);
+
+  // Prints an XML summary of all unit tests.
+  static void PrintXmlTestsList(std::ostream* stream,
+                                const std::vector<TestSuite*>& test_suites);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(unsigned char c) {
+    return c == '\t' || c == '\n' || c == '\r';
+  }
+
+  // May c appear in a well-formed XML document?
+  // https://www.w3.org/TR/REC-xml/#charsets
+  static bool IsValidXmlCharacter(unsigned char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static std::string EscapeXml(const std::string& str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static std::string RemoveInvalidXmlCharacters(const std::string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static std::string EscapeXmlAttribute(const std::string& str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static std::string EscapeXmlText(const char* str) {
+    return EscapeXml(str, false);
+  }
+
+  // Verifies that the given attribute belongs to the given element and
+  // streams the attribute as XML.
+  static void OutputXmlAttribute(std::ostream* stream,
+                                 const std::string& element_name,
+                                 const std::string& name,
+                                 const std::string& value);
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams a test suite XML stanza containing the given test result.
+  //
+  // Requires: result.Failed()
+  static void OutputXmlTestSuiteForTestResult(::std::ostream* stream,
+                                              const TestResult& result);
+
+  // Streams an XML representation of a TestResult object.
+  static void OutputXmlTestResult(::std::ostream* stream,
+                                  const TestResult& result);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_suite_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestSuite object
+  static void PrintXmlTestSuite(::std::ostream* stream,
+                                const TestSuite& test_suite);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(::std::ostream* stream,
+                               const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the std::string is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // Streams an XML representation of the test properties of a TestResult
+  // object.
+  static void OutputXmlTestProperties(std::ostream* stream,
+                                      const TestResult& result);
+
+  // The output file.
+  const std::string output_file_;
+
+  XmlUnitTestResultPrinter(const XmlUnitTestResultPrinter&) = delete;
+  XmlUnitTestResultPrinter& operator=(const XmlUnitTestResultPrinter&) = delete;
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.empty()) {
+    GTEST_LOG_(FATAL) << "XML output file may not be null";
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = OpenFileForWriting(output_file_);
+  std::stringstream stream;
+  PrintXmlUnitTest(&stream, unit_test);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+void XmlUnitTestResultPrinter::ListTestsMatchingFilter(
+    const std::vector<TestSuite*>& test_suites) {
+  FILE* xmlout = OpenFileForWriting(output_file_);
+  std::stringstream stream;
+  PrintXmlTestsList(&stream, test_suites);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+std::string XmlUnitTestResultPrinter::EscapeXml(const std::string& str,
+                                                bool is_attribute) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '<':
+        m << "&lt;";
+        break;
+      case '>':
+        m << "&gt;";
+        break;
+      case '&':
+        m << "&amp;";
+        break;
+      case '\'':
+        if (is_attribute)
+          m << "&apos;";
+        else
+          m << '\'';
+        break;
+      case '"':
+        if (is_attribute)
+          m << "&quot;";
+        else
+          m << '"';
+        break;
+      default:
+        if (IsValidXmlCharacter(static_cast<unsigned char>(ch))) {
+          if (is_attribute &&
+              IsNormalizableWhitespace(static_cast<unsigned char>(ch)))
+            m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
+              << ";";
+          else
+            m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
+    const std::string& str) {
+  std::string output;
+  output.reserve(str.size());
+  for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(static_cast<unsigned char>(*it)))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestSuite object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  // For the exact N seconds, makes sure output has a trailing decimal point.
+  // Sets precision so that we won't have many trailing zeros (e.g., 300 ms
+  // will be just 0.3, 410 ms 0.41, and so on)
+  ss << std::fixed
+     << std::setprecision(
+            ms % 1000 == 0 ? 0 : (ms % 100 == 0 ? 1 : (ms % 10 == 0 ? 2 : 3)))
+     << std::showpoint;
+  ss << (static_cast<double>(ms) * 1e-3);
+  return ss.str();
+}
+
+static bool PortableLocaltime(time_t seconds, struct tm* out) {
+#if defined(_MSC_VER)
+  return localtime_s(out, &seconds) == 0;
+#elif defined(__MINGW32__) || defined(__MINGW64__)
+  // MINGW <time.h> provides neither localtime_r nor localtime_s, but uses
+  // Windows' localtime(), which has a thread-local tm buffer.
+  struct tm* tm_ptr = localtime(&seconds);  // NOLINT
+  if (tm_ptr == nullptr) return false;
+  *out = *tm_ptr;
+  return true;
+#elif defined(__STDC_LIB_EXT1__)
+  // Uses localtime_s when available as localtime_r is only available from
+  // C23 standard.
+  return localtime_s(&seconds, out) != nullptr;
+#else
+  return localtime_r(&seconds, out) != nullptr;
+#endif
+}
+
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+  struct tm time_struct;
+  if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
+    return "";
+  // YYYY-MM-DDThh:mm:ss.sss
+  return StreamableToString(time_struct.tm_year + 1900) + "-" +
+         String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
+         String::FormatIntWidth2(time_struct.tm_mday) + "T" +
+         String::FormatIntWidth2(time_struct.tm_hour) + ":" +
+         String::FormatIntWidth2(time_struct.tm_min) + ":" +
+         String::FormatIntWidth2(time_struct.tm_sec) + "." +
+         String::FormatIntWidthN(static_cast<int>(ms % 1000), 3);
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != nullptr) {
+      stream->write(segment,
+                    static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+void XmlUnitTestResultPrinter::OutputXmlAttribute(
+    std::ostream* stream, const std::string& element_name,
+    const std::string& name, const std::string& value) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedOutputAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+               allowed_names.end())
+      << "Attribute " << name << " is not allowed for element <" << element_name
+      << ">.";
+
+  *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
+}
+
+// Streams a test suite XML stanza containing the given test result.
+void XmlUnitTestResultPrinter::OutputXmlTestSuiteForTestResult(
+    ::std::ostream* stream, const TestResult& result) {
+  // Output the boilerplate for a minimal test suite with one test.
+  *stream << "  <testsuite";
+  OutputXmlAttribute(stream, "testsuite", "name", "NonTestSuiteFailure");
+  OutputXmlAttribute(stream, "testsuite", "tests", "1");
+  OutputXmlAttribute(stream, "testsuite", "failures", "1");
+  OutputXmlAttribute(stream, "testsuite", "disabled", "0");
+  OutputXmlAttribute(stream, "testsuite", "skipped", "0");
+  OutputXmlAttribute(stream, "testsuite", "errors", "0");
+  OutputXmlAttribute(stream, "testsuite", "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(
+      stream, "testsuite", "timestamp",
+      FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
+  *stream << ">";
+
+  // Output the boilerplate for a minimal test case with a single test.
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, "testcase", "name", "");
+  OutputXmlAttribute(stream, "testcase", "status", "run");
+  OutputXmlAttribute(stream, "testcase", "result", "completed");
+  OutputXmlAttribute(stream, "testcase", "classname", "");
+  OutputXmlAttribute(stream, "testcase", "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(
+      stream, "testcase", "timestamp",
+      FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
+
+  // Output the actual test result.
+  OutputXmlTestResult(stream, result);
+
+  // Complete the test suite.
+  *stream << "  </testsuite>\n";
+}
+
+// Prints an XML representation of a TestInfo object.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_suite_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestsuite = "testcase";
+
+  if (test_info.is_in_another_shard()) {
+    return;
+  }
+
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, kTestsuite, "name", test_info.name());
+
+  if (test_info.value_param() != nullptr) {
+    OutputXmlAttribute(stream, kTestsuite, "value_param",
+                       test_info.value_param());
+  }
+  if (test_info.type_param() != nullptr) {
+    OutputXmlAttribute(stream, kTestsuite, "type_param",
+                       test_info.type_param());
+  }
+
+  OutputXmlAttribute(stream, kTestsuite, "file", test_info.file());
+  OutputXmlAttribute(stream, kTestsuite, "line",
+                     StreamableToString(test_info.line()));
+  if (GTEST_FLAG_GET(list_tests)) {
+    *stream << " />\n";
+    return;
+  }
+
+  OutputXmlAttribute(stream, kTestsuite, "status",
+                     test_info.should_run() ? "run" : "notrun");
+  OutputXmlAttribute(stream, kTestsuite, "result",
+                     test_info.should_run()
+                         ? (result.Skipped() ? "skipped" : "completed")
+                         : "suppressed");
+  OutputXmlAttribute(stream, kTestsuite, "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(
+      stream, kTestsuite, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
+  OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name);
+
+  OutputXmlTestResult(stream, result);
+}
+
+void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
+                                                   const TestResult& result) {
+  int failures = 0;
+  int skips = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1 && skips == 0) {
+        *stream << ">\n";
+      }
+      const std::string location =
+          internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                          part.line_number());
+      const std::string summary = location + "\n" + part.summary();
+      *stream << "      <failure message=\"" << EscapeXmlAttribute(summary)
+              << "\" type=\"\">";
+      const std::string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</failure>\n";
+    } else if (part.skipped()) {
+      if (++skips == 1 && failures == 0) {
+        *stream << ">\n";
+      }
+      const std::string location =
+          internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                          part.line_number());
+      const std::string summary = location + "\n" + part.summary();
+      *stream << "      <skipped message=\""
+              << EscapeXmlAttribute(summary.c_str()) << "\">";
+      const std::string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</skipped>\n";
+    }
+  }
+
+  if (failures == 0 && skips == 0 && result.test_property_count() == 0) {
+    *stream << " />\n";
+  } else {
+    if (failures == 0 && skips == 0) {
+      *stream << ">\n";
+    }
+    OutputXmlTestProperties(stream, result);
+    *stream << "    </testcase>\n";
+  }
+}
+
+// Prints an XML representation of a TestSuite object
+void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
+                                                 const TestSuite& test_suite) {
+  const std::string kTestsuite = "testsuite";
+  *stream << "  <" << kTestsuite;
+  OutputXmlAttribute(stream, kTestsuite, "name", test_suite.name());
+  OutputXmlAttribute(stream, kTestsuite, "tests",
+                     StreamableToString(test_suite.reportable_test_count()));
+  if (!GTEST_FLAG_GET(list_tests)) {
+    OutputXmlAttribute(stream, kTestsuite, "failures",
+                       StreamableToString(test_suite.failed_test_count()));
+    OutputXmlAttribute(
+        stream, kTestsuite, "disabled",
+        StreamableToString(test_suite.reportable_disabled_test_count()));
+    OutputXmlAttribute(stream, kTestsuite, "skipped",
+                       StreamableToString(test_suite.skipped_test_count()));
+
+    OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+
+    OutputXmlAttribute(stream, kTestsuite, "time",
+                       FormatTimeInMillisAsSeconds(test_suite.elapsed_time()));
+    OutputXmlAttribute(
+        stream, kTestsuite, "timestamp",
+        FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
+    *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
+  }
+  *stream << ">\n";
+  for (int i = 0; i < test_suite.total_test_count(); ++i) {
+    if (test_suite.GetTestInfo(i)->is_reportable())
+      OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
+  }
+  *stream << "  </" << kTestsuite << ">\n";
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
+                                                const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(unit_test.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "failures",
+                     StreamableToString(unit_test.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "disabled",
+      StreamableToString(unit_test.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "errors", "0");
+  OutputXmlAttribute(stream, kTestsuites, "time",
+                     FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
+
+  if (GTEST_FLAG_GET(shuffle)) {
+    OutputXmlAttribute(stream, kTestsuites, "random_seed",
+                       StreamableToString(unit_test.random_seed()));
+  }
+  *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
+
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
+      PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
+  }
+
+  // If there was a test failure outside of one of the test suites (like in a
+  // test environment) include that in the output.
+  if (unit_test.ad_hoc_test_result().Failed()) {
+    OutputXmlTestSuiteForTestResult(stream, unit_test.ad_hoc_test_result());
+  }
+
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+void XmlUnitTestResultPrinter::PrintXmlTestsList(
+    std::ostream* stream, const std::vector<TestSuite*>& test_suites) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  int total_tests = 0;
+  for (auto test_suite : test_suites) {
+    total_tests += test_suite->total_test_count();
+  }
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(total_tests));
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (auto test_suite : test_suites) {
+    PrintXmlTestSuite(stream, *test_suite);
+  }
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "=" << "\""
+               << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+void XmlUnitTestResultPrinter::OutputXmlTestProperties(
+    std::ostream* stream, const TestResult& result) {
+  const std::string kProperties = "properties";
+  const std::string kProperty = "property";
+
+  if (result.test_property_count() <= 0) {
+    return;
+  }
+
+  *stream << "      <" << kProperties << ">\n";
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    *stream << "        <" << kProperty;
+    *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
+    *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
+    *stream << "/>\n";
+  }
+  *stream << "      </" << kProperties << ">\n";
+}
+
+// End XmlUnitTestResultPrinter
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+#if GTEST_HAS_FILE_SYSTEM
+// This class generates an JSON output file.
+class JsonUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit JsonUnitTestResultPrinter(const char* output_file);
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+
+  // Prints an JSON summary of all unit tests.
+  static void PrintJsonTestList(::std::ostream* stream,
+                                const std::vector<TestSuite*>& test_suites);
+
+ private:
+  // Returns an JSON-escaped copy of the input string str.
+  static std::string EscapeJson(const std::string& str);
+
+  //// Verifies that the given attribute belongs to the given element and
+  //// streams the attribute as JSON.
+  static void OutputJsonKey(std::ostream* stream,
+                            const std::string& element_name,
+                            const std::string& name, const std::string& value,
+                            const std::string& indent, bool comma = true);
+  static void OutputJsonKey(std::ostream* stream,
+                            const std::string& element_name,
+                            const std::string& name, int value,
+                            const std::string& indent, bool comma = true);
+
+  // Streams a test suite JSON stanza containing the given test result.
+  //
+  // Requires: result.Failed()
+  static void OutputJsonTestSuiteForTestResult(::std::ostream* stream,
+                                               const TestResult& result);
+
+  // Streams a JSON representation of a TestResult object.
+  static void OutputJsonTestResult(::std::ostream* stream,
+                                   const TestResult& result);
+
+  // Streams a JSON representation of a TestInfo object.
+  static void OutputJsonTestInfo(::std::ostream* stream,
+                                 const char* test_suite_name,
+                                 const TestInfo& test_info);
+
+  // Prints a JSON representation of a TestSuite object
+  static void PrintJsonTestSuite(::std::ostream* stream,
+                                 const TestSuite& test_suite);
+
+  // Prints a JSON summary of unit_test to output stream out.
+  static void PrintJsonUnitTest(::std::ostream* stream,
+                                const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as
+  // a JSON dictionary.
+  static std::string TestPropertiesAsJson(const TestResult& result,
+                                          const std::string& indent);
+
+  // The output file.
+  const std::string output_file_;
+
+  JsonUnitTestResultPrinter(const JsonUnitTestResultPrinter&) = delete;
+  JsonUnitTestResultPrinter& operator=(const JsonUnitTestResultPrinter&) =
+      delete;
+};
+
+// Creates a new JsonUnitTestResultPrinter.
+JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.empty()) {
+    GTEST_LOG_(FATAL) << "JSON output file may not be null";
+  }
+}
+
+void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                   int /*iteration*/) {
+  FILE* jsonout = OpenFileForWriting(output_file_);
+  std::stringstream stream;
+  PrintJsonUnitTest(&stream, unit_test);
+  fprintf(jsonout, "%s", StringStreamToString(&stream).c_str());
+  fclose(jsonout);
+}
+
+// Returns an JSON-escaped copy of the input string str.
+std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '\\':
+      case '"':
+      case '/':
+        m << '\\' << ch;
+        break;
+      case '\b':
+        m << "\\b";
+        break;
+      case '\t':
+        m << "\\t";
+        break;
+      case '\n':
+        m << "\\n";
+        break;
+      case '\f':
+        m << "\\f";
+        break;
+      case '\r':
+        m << "\\r";
+        break;
+      default:
+        if (ch < ' ') {
+          m << "\\u00" << String::FormatByte(static_cast<unsigned char>(ch));
+        } else {
+          m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// The following routines generate an JSON representation of a UnitTest
+// object.
+
+// Formats the given time in milliseconds as seconds.
+static std::string FormatTimeInMillisAsDuration(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << (static_cast<double>(ms) * 1e-3) << "s";
+  return ss.str();
+}
+
+// Converts the given epoch time in milliseconds to a date string in the
+// RFC3339 format, without the timezone information.
+static std::string FormatEpochTimeInMillisAsRFC3339(TimeInMillis ms) {
+  struct tm time_struct;
+  if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
+    return "";
+  // YYYY-MM-DDThh:mm:ss
+  return StreamableToString(time_struct.tm_year + 1900) + "-" +
+         String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
+         String::FormatIntWidth2(time_struct.tm_mday) + "T" +
+         String::FormatIntWidth2(time_struct.tm_hour) + ":" +
+         String::FormatIntWidth2(time_struct.tm_min) + ":" +
+         String::FormatIntWidth2(time_struct.tm_sec) + "Z";
+}
+
+static inline std::string Indent(size_t width) {
+  return std::string(width, ' ');
+}
+
+void JsonUnitTestResultPrinter::OutputJsonKey(std::ostream* stream,
+                                              const std::string& element_name,
+                                              const std::string& name,
+                                              const std::string& value,
+                                              const std::string& indent,
+                                              bool comma) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedOutputAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+               allowed_names.end())
+      << "Key \"" << name << "\" is not allowed for value \"" << element_name
+      << "\".";
+
+  *stream << indent << "\"" << name << "\": \"" << EscapeJson(value) << "\"";
+  if (comma) *stream << ",\n";
+}
+
+void JsonUnitTestResultPrinter::OutputJsonKey(
+    std::ostream* stream, const std::string& element_name,
+    const std::string& name, int value, const std::string& indent, bool comma) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedOutputAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+               allowed_names.end())
+      << "Key \"" << name << "\" is not allowed for value \"" << element_name
+      << "\".";
+
+  *stream << indent << "\"" << name << "\": " << StreamableToString(value);
+  if (comma) *stream << ",\n";
+}
+
+// Streams a test suite JSON stanza containing the given test result.
+void JsonUnitTestResultPrinter::OutputJsonTestSuiteForTestResult(
+    ::std::ostream* stream, const TestResult& result) {
+  // Output the boilerplate for a new test suite.
+  *stream << Indent(4) << "{\n";
+  OutputJsonKey(stream, "testsuite", "name", "NonTestSuiteFailure", Indent(6));
+  OutputJsonKey(stream, "testsuite", "tests", 1, Indent(6));
+  if (!GTEST_FLAG_GET(list_tests)) {
+    OutputJsonKey(stream, "testsuite", "failures", 1, Indent(6));
+    OutputJsonKey(stream, "testsuite", "disabled", 0, Indent(6));
+    OutputJsonKey(stream, "testsuite", "skipped", 0, Indent(6));
+    OutputJsonKey(stream, "testsuite", "errors", 0, Indent(6));
+    OutputJsonKey(stream, "testsuite", "time",
+                  FormatTimeInMillisAsDuration(result.elapsed_time()),
+                  Indent(6));
+    OutputJsonKey(stream, "testsuite", "timestamp",
+                  FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
+                  Indent(6));
+  }
+  *stream << Indent(6) << "\"testsuite\": [\n";
+
+  // Output the boilerplate for a new test case.
+  *stream << Indent(8) << "{\n";
+  OutputJsonKey(stream, "testcase", "name", "", Indent(10));
+  OutputJsonKey(stream, "testcase", "status", "RUN", Indent(10));
+  OutputJsonKey(stream, "testcase", "result", "COMPLETED", Indent(10));
+  OutputJsonKey(stream, "testcase", "timestamp",
+                FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
+                Indent(10));
+  OutputJsonKey(stream, "testcase", "time",
+                FormatTimeInMillisAsDuration(result.elapsed_time()),
+                Indent(10));
+  OutputJsonKey(stream, "testcase", "classname", "", Indent(10), false);
+  *stream << TestPropertiesAsJson(result, Indent(10));
+
+  // Output the actual test result.
+  OutputJsonTestResult(stream, result);
+
+  // Finish the test suite.
+  *stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
+}
+
+// Prints a JSON representation of a TestInfo object.
+void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
+                                                   const char* test_suite_name,
+                                                   const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestsuite = "testcase";
+  const std::string kIndent = Indent(10);
+
+  *stream << Indent(8) << "{\n";
+  OutputJsonKey(stream, kTestsuite, "name", test_info.name(), kIndent);
+
+  if (test_info.value_param() != nullptr) {
+    OutputJsonKey(stream, kTestsuite, "value_param", test_info.value_param(),
+                  kIndent);
+  }
+  if (test_info.type_param() != nullptr) {
+    OutputJsonKey(stream, kTestsuite, "type_param", test_info.type_param(),
+                  kIndent);
+  }
+
+  OutputJsonKey(stream, kTestsuite, "file", test_info.file(), kIndent);
+  OutputJsonKey(stream, kTestsuite, "line", test_info.line(), kIndent, false);
+  if (GTEST_FLAG_GET(list_tests)) {
+    *stream << "\n" << Indent(8) << "}";
+    return;
+  } else {
+    *stream << ",\n";
+  }
+
+  OutputJsonKey(stream, kTestsuite, "status",
+                test_info.should_run() ? "RUN" : "NOTRUN", kIndent);
+  OutputJsonKey(stream, kTestsuite, "result",
+                test_info.should_run()
+                    ? (result.Skipped() ? "SKIPPED" : "COMPLETED")
+                    : "SUPPRESSED",
+                kIndent);
+  OutputJsonKey(stream, kTestsuite, "timestamp",
+                FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
+                kIndent);
+  OutputJsonKey(stream, kTestsuite, "time",
+                FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent);
+  OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent,
+                false);
+  *stream << TestPropertiesAsJson(result, kIndent);
+
+  OutputJsonTestResult(stream, result);
+}
+
+void JsonUnitTestResultPrinter::OutputJsonTestResult(::std::ostream* stream,
+                                                     const TestResult& result) {
+  const std::string kIndent = Indent(10);
+
+  {
+    int failures = 0;
+    for (int i = 0; i < result.total_part_count(); ++i) {
+      const TestPartResult& part = result.GetTestPartResult(i);
+      if (part.failed()) {
+        *stream << ",\n";
+        if (++failures == 1) {
+          *stream << kIndent << "\"" << "failures" << "\": [\n";
+        }
+        const std::string location =
+            internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                            part.line_number());
+        const std::string message =
+            EscapeJson(location + "\n" + part.message());
+        *stream << kIndent << "  {\n"
+                << kIndent << "    \"failure\": \"" << message << "\",\n"
+                << kIndent << "    \"type\": \"\"\n"
+                << kIndent << "  }";
+      }
+    }
+
+    if (failures > 0) *stream << "\n" << kIndent << "]";
+  }
+
+  {
+    int skipped = 0;
+    for (int i = 0; i < result.total_part_count(); ++i) {
+      const TestPartResult& part = result.GetTestPartResult(i);
+      if (part.skipped()) {
+        *stream << ",\n";
+        if (++skipped == 1) {
+          *stream << kIndent << "\"" << "skipped" << "\": [\n";
+        }
+        const std::string location =
+            internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                            part.line_number());
+        const std::string message =
+            EscapeJson(location + "\n" + part.message());
+        *stream << kIndent << "  {\n"
+                << kIndent << "    \"message\": \"" << message << "\"\n"
+                << kIndent << "  }";
+      }
+    }
+
+    if (skipped > 0) *stream << "\n" << kIndent << "]";
+  }
+
+  *stream << "\n" << Indent(8) << "}";
+}
+
+// Prints an JSON representation of a TestSuite object
+void JsonUnitTestResultPrinter::PrintJsonTestSuite(
+    std::ostream* stream, const TestSuite& test_suite) {
+  const std::string kTestsuite = "testsuite";
+  const std::string kIndent = Indent(6);
+
+  *stream << Indent(4) << "{\n";
+  OutputJsonKey(stream, kTestsuite, "name", test_suite.name(), kIndent);
+  OutputJsonKey(stream, kTestsuite, "tests", test_suite.reportable_test_count(),
+                kIndent);
+  if (!GTEST_FLAG_GET(list_tests)) {
+    OutputJsonKey(stream, kTestsuite, "failures",
+                  test_suite.failed_test_count(), kIndent);
+    OutputJsonKey(stream, kTestsuite, "disabled",
+                  test_suite.reportable_disabled_test_count(), kIndent);
+    OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
+    OutputJsonKey(
+        stream, kTestsuite, "timestamp",
+        FormatEpochTimeInMillisAsRFC3339(test_suite.start_timestamp()),
+        kIndent);
+    OutputJsonKey(stream, kTestsuite, "time",
+                  FormatTimeInMillisAsDuration(test_suite.elapsed_time()),
+                  kIndent, false);
+    *stream << TestPropertiesAsJson(test_suite.ad_hoc_test_result(), kIndent)
+            << ",\n";
+  }
+
+  *stream << kIndent << "\"" << kTestsuite << "\": [\n";
+
+  bool comma = false;
+  for (int i = 0; i < test_suite.total_test_count(); ++i) {
+    if (test_suite.GetTestInfo(i)->is_reportable()) {
+      if (comma) {
+        *stream << ",\n";
+      } else {
+        comma = true;
+      }
+      OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
+    }
+  }
+  *stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
+}
+
+// Prints a JSON summary of unit_test to output stream out.
+void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,
+                                                  const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+  const std::string kIndent = Indent(2);
+  *stream << "{\n";
+
+  OutputJsonKey(stream, kTestsuites, "tests", unit_test.reportable_test_count(),
+                kIndent);
+  OutputJsonKey(stream, kTestsuites, "failures", unit_test.failed_test_count(),
+                kIndent);
+  OutputJsonKey(stream, kTestsuites, "disabled",
+                unit_test.reportable_disabled_test_count(), kIndent);
+  OutputJsonKey(stream, kTestsuites, "errors", 0, kIndent);
+  if (GTEST_FLAG_GET(shuffle)) {
+    OutputJsonKey(stream, kTestsuites, "random_seed", unit_test.random_seed(),
+                  kIndent);
+  }
+  OutputJsonKey(stream, kTestsuites, "timestamp",
+                FormatEpochTimeInMillisAsRFC3339(unit_test.start_timestamp()),
+                kIndent);
+  OutputJsonKey(stream, kTestsuites, "time",
+                FormatTimeInMillisAsDuration(unit_test.elapsed_time()), kIndent,
+                false);
+
+  *stream << TestPropertiesAsJson(unit_test.ad_hoc_test_result(), kIndent)
+          << ",\n";
+
+  OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
+  *stream << kIndent << "\"" << kTestsuites << "\": [\n";
+
+  bool comma = false;
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) {
+      if (comma) {
+        *stream << ",\n";
+      } else {
+        comma = true;
+      }
+      PrintJsonTestSuite(stream, *unit_test.GetTestSuite(i));
+    }
+  }
+
+  // If there was a test failure outside of one of the test suites (like in a
+  // test environment) include that in the output.
+  if (unit_test.ad_hoc_test_result().Failed()) {
+    if (comma) {
+      *stream << ",\n";
+    }
+    OutputJsonTestSuiteForTestResult(stream, unit_test.ad_hoc_test_result());
+  }
+
+  *stream << "\n"
+          << kIndent << "]\n"
+          << "}\n";
+}
+
+void JsonUnitTestResultPrinter::PrintJsonTestList(
+    std::ostream* stream, const std::vector<TestSuite*>& test_suites) {
+  const std::string kTestsuites = "testsuites";
+  const std::string kIndent = Indent(2);
+  *stream << "{\n";
+  int total_tests = 0;
+  for (auto test_suite : test_suites) {
+    total_tests += test_suite->total_test_count();
+  }
+  OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent);
+
+  OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
+  *stream << kIndent << "\"" << kTestsuites << "\": [\n";
+
+  for (size_t i = 0; i < test_suites.size(); ++i) {
+    if (i != 0) {
+      *stream << ",\n";
+    }
+    PrintJsonTestSuite(stream, *test_suites[i]);
+  }
+
+  *stream << "\n"
+          << kIndent << "]\n"
+          << "}\n";
+}
+// Produces a string representing the test properties in a result as
+// a JSON dictionary.
+std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
+    const TestResult& result, const std::string& indent) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << ",\n"
+               << indent << "\"" << property.key() << "\": " << "\""
+               << EscapeJson(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End JsonUnitTestResultPrinter
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+std::string StreamingListener::UrlEncode(const char* str) {
+  std::string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.push_back('%');
+        result.append(String::FormatByte(static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::SocketWriter::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;  // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = nullptr;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num =
+      getaddrinfo(host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != nullptr;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(cur_addr->ai_family, cur_addr->ai_socktype,
+                     cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// class OsStackTraceGetter
+
+const char* const OsStackTraceGetterInterface::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+#ifdef GTEST_HAS_ABSL
+  std::string result;
+
+  if (max_depth <= 0) {
+    return result;
+  }
+
+  max_depth = std::min(max_depth, kMaxStackTraceDepth);
+
+  std::vector<void*> raw_stack(max_depth);
+  // Skips the frames requested by the caller, plus this function.
+  const int raw_stack_size =
+      absl::GetStackTrace(&raw_stack[0], max_depth, skip_count + 1);
+
+  void* caller_frame = nullptr;
+  {
+    MutexLock lock(&mutex_);
+    caller_frame = caller_frame_;
+  }
+
+  for (int i = 0; i < raw_stack_size; ++i) {
+    if (raw_stack[i] == caller_frame &&
+        !GTEST_FLAG_GET(show_internal_stack_frames)) {
+      // Add a marker to the trace and stop adding frames.
+      absl::StrAppend(&result, kElidedFramesMarker, "\n");
+      break;
+    }
+
+    char tmp[1024];
+    const char* symbol = "(unknown)";
+    if (absl::Symbolize(raw_stack[i], tmp, sizeof(tmp))) {
+      symbol = tmp;
+    }
+
+    char line[1024];
+    snprintf(line, sizeof(line), "  %p: %s\n", raw_stack[i], symbol);
+    result += line;
+  }
+
+  return result;
+
+#else   // !GTEST_HAS_ABSL
+  static_cast<void>(max_depth);
+  static_cast<void>(skip_count);
+  return "";
+#endif  // GTEST_HAS_ABSL
+}
+
+void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
+#ifdef GTEST_HAS_ABSL
+  void* caller_frame = nullptr;
+  if (absl::GetStackTrace(&caller_frame, 1, 3) <= 0) {
+    caller_frame = nullptr;
+  }
+
+  MutexLock lock(&mutex_);
+  caller_frame_ = caller_frame;
+#endif  // GTEST_HAS_ABSL
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+// A helper class that creates the premature-exit file in its
+// constructor and deletes the file in its destructor.
+class ScopedPrematureExitFile {
+ public:
+  explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
+      : premature_exit_filepath_(
+            premature_exit_filepath ? premature_exit_filepath : "") {
+    // If a path to the premature-exit file is specified...
+    if (!premature_exit_filepath_.empty()) {
+      // create the file with a single "0" character in it.  I/O
+      // errors are ignored as there's nothing better we can do and we
+      // don't want to fail the test because of this.
+      FILE* pfile = posix::FOpen(premature_exit_filepath_.c_str(), "w");
+      fwrite("0", 1, 1, pfile);
+      fclose(pfile);
+    }
+  }
+
+  ~ScopedPrematureExitFile() {
+#ifndef GTEST_OS_ESP8266
+    if (!premature_exit_filepath_.empty()) {
+      int retval = remove(premature_exit_filepath_.c_str());
+      if (retval) {
+        GTEST_LOG_(ERROR) << "Failed to remove premature exit filepath \""
+                          << premature_exit_filepath_ << "\" with error "
+                          << retval;
+      }
+    }
+#endif
+  }
+
+ private:
+  const std::string premature_exit_filepath_;
+
+  ScopedPrematureExitFile(const ScopedPrematureExitFile&) = delete;
+  ScopedPrematureExitFile& operator=(const ScopedPrematureExitFile&) = delete;
+};
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(nullptr),
+      default_xml_generator_(nullptr) {}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = nullptr;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = nullptr;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != nullptr) Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != nullptr) Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding(bool suppress) {
+  repeater_->set_forwarding_enabled(!suppress);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest* UnitTest::GetInstance() {
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // defined(__BORLANDC__)
+}
+
+// Gets the number of successful test suites.
+int UnitTest::successful_test_suite_count() const {
+  return impl()->successful_test_suite_count();
+}
+
+// Gets the number of failed test suites.
+int UnitTest::failed_test_suite_count() const {
+  return impl()->failed_test_suite_count();
+}
+
+// Gets the number of all test suites.
+int UnitTest::total_test_suite_count() const {
+  return impl()->total_test_suite_count();
+}
+
+// Gets the number of all test suites that contain at least one test
+// that should run.
+int UnitTest::test_suite_to_run_count() const {
+  return impl()->test_suite_to_run_count();
+}
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_suite_count();
+}
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_suite_count();
+}
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_suite_count();
+}
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_suite_to_run_count();
+}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of skipped tests.
+int UnitTest::skipped_test_count() const {
+  return impl()->skipped_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTest::reportable_disabled_test_count() const {
+  return impl()->reportable_disabled_test_count();
+}
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTest::reportable_test_count() const {
+  return impl()->reportable_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+  return impl()->start_timestamp();
+}
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true if and only if the unit test passed (i.e. all test suites
+// passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true if and only if the unit test failed (i.e. some test suite
+// failed or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test suite among all the test suites. i can range from 0 to
+// total_test_suite_count() - 1. If i is not in that range, returns NULL.
+const TestSuite* UnitTest::GetTestSuite(int i) const {
+  return impl()->GetTestSuite(i);
+}
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Returns the TestResult containing information on test failures and
+// properties logged outside of individual test suites.
+const TestResult& UnitTest::ad_hoc_test_result() const {
+  return *impl()->ad_hoc_test_result();
+}
+
+// Gets the i-th test suite among all the test suites. i can range from 0 to
+// total_test_suite_count() - 1. If i is not in that range, returns NULL.
+TestSuite* UnitTest::GetMutableTestSuite(int i) {
+  return impl()->GetMutableSuiteCase(i);
+}
+
+void UnitTest::UponLeavingGTest() {
+  impl()->os_stack_trace_getter()->UponLeavingGTest();
+}
+
+// Sets the TestSuite object for the test that's currently running.
+void UnitTest::set_current_test_suite(TestSuite* a_current_test_suite) {
+  internal::MutexLock lock(&mutex_);
+  impl_->set_current_test_suite(a_current_test_suite);
+}
+
+// Sets the TestInfo object for the test that's currently running.
+void UnitTest::set_current_test_info(TestInfo* a_current_test_info) {
+  internal::MutexLock lock(&mutex_);
+  impl_->set_current_test_info(a_current_test_info);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() { return *impl()->listeners(); }
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == nullptr) {
+    return nullptr;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
+                                 const char* file_name, int line_number,
+                                 const std::string& message,
+                                 const std::string& os_stack_trace)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (!impl_->gtest_trace_stack().empty()) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (size_t i = impl_->gtest_trace_stack().size(); i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n"
+          << internal::FormatFileLocation(trace.file, trace.line) << " "
+          << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != nullptr && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  } else {
+    msg << "\n";
+  }
+
+  const TestPartResult result = TestPartResult(
+      result_type, file_name, line_number, msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->ReportTestPartResult(
+      result);
+
+  if (result_type != TestPartResult::kSuccess &&
+      result_type != TestPartResult::kSkip) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG_GET(break_on_failure)) {
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT)
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#elif (!defined(__native_client__)) &&            \
+    ((defined(__clang__) || defined(__GNUC__)) && \
+     (defined(__x86_64__) || defined(__i386__)))
+      // with clang/gcc we can achieve the same effect on x86 by invoking int3
+      asm("int3");
+#elif GTEST_HAS_BUILTIN(__builtin_trap)
+      __builtin_trap();
+#elif defined(SIGTRAP)
+      raise(SIGTRAP);
+#else
+      // Dereference nullptr through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: some debuggers don't correctly trap abort().
+      *static_cast<volatile int*>(nullptr) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG_GET(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw internal::GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Adds a TestProperty to the current TestResult object when invoked from
+// inside a test, to current TestSuite's ad_hoc_test_result_ when invoked
+// from SetUpTestSuite or TearDownTestSuite, or to the global property set
+// when invoked elsewhere.  If the result already contains a property with
+// the same key, the value will be updated.
+void UnitTest::RecordProperty(const std::string& key,
+                              const std::string& value) {
+  impl_->RecordProperty(TestProperty(key, value));
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+#ifdef GTEST_HAS_DEATH_TEST
+  const bool in_death_test_child_process =
+      !GTEST_FLAG_GET(internal_run_death_test).empty();
+
+  // Google Test implements this protocol for catching that a test
+  // program exits before returning control to Google Test:
+  //
+  //   1. Upon start, Google Test creates a file whose absolute path
+  //      is specified by the environment variable
+  //      TEST_PREMATURE_EXIT_FILE.
+  //   2. When Google Test has finished its work, it deletes the file.
+  //
+  // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
+  // running a Google-Test-based test program and check the existence
+  // of the file at the end of the test execution to see if it has
+  // exited prematurely.
+
+  // If we are in the child process of a death test, don't
+  // create/delete the premature exit file, as doing so is unnecessary
+  // and will confuse the parent process.  Otherwise, create/delete
+  // the file upon entering/leaving this function.  If the program
+  // somehow exits before this function has a chance to return, the
+  // premature-exit file will be left undeleted, causing a test runner
+  // that understands the premature-exit-file protocol to report the
+  // test as having failed.
+  const internal::ScopedPrematureExitFile premature_exit_file(
+      in_death_test_child_process
+          ? nullptr
+          : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
+#else
+  const bool in_death_test_child_process = false;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG_GET(catch_exceptions));
+
+#ifdef GTEST_OS_WINDOWS
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_GAMES)
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+#if (defined(_MSC_VER) || defined(GTEST_OS_WINDOWS_MINGW)) && \
+    !defined(GTEST_OS_WINDOWS_MOBILE)
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+#endif
+
+#if defined(_MSC_VER) && !defined(GTEST_OS_WINDOWS_MOBILE)
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    if (!GTEST_FLAG_GET(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+
+    // In debug mode, the Windows CRT can crash with an assertion over invalid
+    // input (e.g. passing an invalid file descriptor).  The default handling
+    // for these assertions is to pop up a dialog and wait for user input.
+    // Instead ask the CRT to dump such assertions to stderr non-interactively.
+    if (!IsDebuggerPresent()) {
+      (void)_CrtSetReportMode(_CRT_ASSERT,
+                              _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+      (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+    }
+#endif
+  }
+#else
+  (void)in_death_test_child_process;  // Needed inside the #if block above
+#endif  // GTEST_OS_WINDOWS
+
+  return internal::HandleExceptionsInMethodIfSupported(
+             impl(), &internal::UnitTestImpl::RunAllTests,
+             "auxiliary test code (environments or event listeners)")
+             ? 0
+             : 1;
+}
+
+#if GTEST_HAS_FILE_SYSTEM
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+// Returns the TestSuite object for the test that's currently running,
+// or NULL if no test is running.
+const TestSuite* UnitTest::current_test_suite() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_suite();
+}
+
+// Legacy API is still available but deprecated
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+const TestCase* UnitTest::current_test_case() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_suite();
+}
+#endif
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+const TestInfo* UnitTest::current_test_info() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+// Returns ParameterizedTestSuiteRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+internal::ParameterizedTestSuiteRegistry&
+UnitTest::parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_) {
+  return impl_->parameterized_test_registry();
+}
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() { impl_ = new internal::UnitTestImpl(this); }
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() { delete impl_; }
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+void UnitTest::PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+      GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */)
+          default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+      GTEST_DISABLE_MSC_WARNINGS_POP_() global_test_part_result_reporter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+      last_death_test_suite_(-1),
+      current_test_suite_(nullptr),
+      current_test_info_(nullptr),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(nullptr),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),       // Will be reseeded before first use.
+      start_timestamp_(0),
+      elapsed_time_(0),
+#ifdef GTEST_HAS_DEATH_TEST
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestSuite.
+  ForEach(test_suites_, internal::Delete<TestSuite>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+// Adds a TestProperty to the current TestResult object when invoked in a
+// context of a test, to current test suite's ad_hoc_test_result when invoke
+// from SetUpTestSuite/TearDownTestSuite, or to the global property set
+// otherwise.  If the result already contains a property with the same key,
+// the value will be updated.
+void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
+  std::string xml_element;
+  TestResult* test_result;  // TestResult appropriate for property recording.
+
+  if (current_test_info_ != nullptr) {
+    xml_element = "testcase";
+    test_result = &(current_test_info_->result_);
+  } else if (current_test_suite_ != nullptr) {
+    xml_element = "testsuite";
+    test_result = &(current_test_suite_->ad_hoc_test_result_);
+  } else {
+    xml_element = "testsuites";
+    test_result = &ad_hoc_test_result_;
+  }
+  test_result->RecordProperty(xml_element, test_property);
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_ != nullptr)
+    listeners()->SuppressEventForwarding(true);
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+#if GTEST_HAS_FILE_SYSTEM
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format == "json") {
+    listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (!output_format.empty()) {
+    GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \""
+                        << output_format << "\" ignored.";
+  }
+#else
+  if (!output_format.empty()) {
+    GTEST_LOG_(ERROR) << "ERROR: alternative output formats require "
+                      << "GTEST_HAS_FILE_SYSTEM to be enabled";
+  }
+#endif  // GTEST_HAS_FILE_SYSTEM
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in string form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const std::string& target = GTEST_FLAG_GET(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != std::string::npos) {
+      listeners()->Append(
+          new StreamingListener(target.substr(0, pos), target.substr(pos + 1)));
+    } else {
+      GTEST_LOG_(WARNING) << "unrecognized streaming target \"" << target
+                          << "\" ignored.";
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
+    // Register to send notifications about key process state changes.
+    listeners()->Append(new GTEST_CUSTOM_TEST_EVENT_LISTENER_());
+#endif  // defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
+
+#ifdef GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+    if (GTEST_FLAG_GET(brief)) {
+      listeners()->SetDefaultResultPrinter(new BriefUnitTestResultPrinter);
+    }
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+#ifdef GTEST_HAS_ABSL
+    if (GTEST_FLAG_GET(install_failure_signal_handler)) {
+      absl::FailureSignalHandlerOptions options;
+      absl::InstallFailureSignalHandler(options);
+    }
+#endif  // GTEST_HAS_ABSL
+  }
+}
+
+// Finds and returns a TestSuite with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_suite_name: name of the test suite
+//   type_param:      the name of the test suite's type parameter, or NULL if
+//                    this is not a typed or a type-parameterized test suite.
+//   set_up_tc:       pointer to the function that sets up the test suite
+//   tear_down_tc:    pointer to the function that tears down the test suite
+TestSuite* UnitTestImpl::GetTestSuite(
+    const std::string& test_suite_name, const char* type_param,
+    internal::SetUpTestSuiteFunc set_up_tc,
+    internal::TearDownTestSuiteFunc tear_down_tc) {
+  // During initialization, all TestInfos for a given suite are added in
+  // sequence. To optimize this case, see if the most recently added suite is
+  // the one being requested now.
+  if (!test_suites_.empty() &&
+      (*test_suites_.rbegin())->name_ == test_suite_name) {
+    return *test_suites_.rbegin();
+  }
+
+  // Fall back to searching the collection.
+  auto item_it = test_suites_by_name_.find(test_suite_name);
+  if (item_it != test_suites_by_name_.end()) {
+    return item_it->second;
+  }
+
+  // Not found. Create a new instance.
+  auto* const new_test_suite =
+      new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);
+  test_suites_by_name_.emplace(test_suite_name, new_test_suite);
+
+  const UnitTestFilter death_test_suite_filter(kDeathTestSuiteFilter);
+  // Is this a death test suite?
+  if (death_test_suite_filter.MatchesName(test_suite_name)) {
+    // Yes.  Inserts the test suite after the last death test suite
+    // defined so far.  This only works when the test suites haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_suite_;
+    test_suites_.insert(test_suites_.begin() + last_death_test_suite_,
+                        new_test_suite);
+  } else {
+    // No.  Appends to the end of the list.
+    test_suites_.push_back(new_test_suite);
+  }
+
+  test_suite_indices_.push_back(static_cast<int>(test_suite_indices_.size()));
+  return new_test_suite;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // True if and only if Google Test is initialized before RUN_ALL_TESTS() is
+  // called.
+  const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized();
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag) return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+#if GTEST_HAS_FILE_SYSTEM
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+  // True if and only if we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#ifdef GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_ != nullptr);
+#if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
+  if (in_subprocess_for_death_test) {
+    GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_();
+  }
+#endif  // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run =
+      FilterTests(should_shard ? HONOR_SHARDING_PROTOCOL
+                               : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG_GET(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GetRandomSeedFromFlag(GTEST_FLAG_GET(random_seed));
+
+  // True if and only if at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  start_timestamp_ = GetTimeInMillis();
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG_GET(repeat);
+
+  // Repeats forever if the repeat count is negative.
+  const bool gtest_repeat_forever = repeat < 0;
+
+  // Should test environments be set up and torn down for each repeat, or only
+  // set up on the first and torn down on the last iteration? If there is no
+  // "last" iteration because the tests will repeat forever, always recreate the
+  // environments to avoid leaks in case one of the environments is using
+  // resources that are external to this process. Without this check there would
+  // be no way to clean up those external resources automatically.
+  const bool recreate_environments_when_repeating =
+      GTEST_FLAG_GET(recreate_environments_when_repeating) ||
+      gtest_repeat_forever;
+
+  for (int i = 0; gtest_repeat_forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    Timer timer;
+
+    // Shuffles test suites and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG_GET(shuffle)) {
+      random()->Reseed(static_cast<uint32_t>(random_seed_));
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test suite if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand. If test environments aren't
+      // recreated for each iteration, only do so on the first iteration.
+      if (i == 0 || recreate_environments_when_repeating) {
+        repeater->OnEnvironmentsSetUpStart(*parent_);
+        ForEach(environments_, SetUpEnvironment);
+        repeater->OnEnvironmentsSetUpEnd(*parent_);
+      }
+
+      // Runs the tests only if there was no fatal failure or skip triggered
+      // during global set-up.
+      if (Test::IsSkipped()) {
+        // Emit diagnostics when global set-up calls skip, as it will not be
+        // emitted by default.
+        TestResult& test_result =
+            *internal::GetUnitTestImpl()->current_test_result();
+        for (int j = 0; j < test_result.total_part_count(); ++j) {
+          const TestPartResult& test_part_result =
+              test_result.GetTestPartResult(j);
+          if (test_part_result.type() == TestPartResult::kSkip) {
+            const std::string& result = test_part_result.message();
+            printf("%s\n", result.c_str());
+          }
+        }
+        fflush(stdout);
+      } else if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_suite_count();
+             test_index++) {
+          GetMutableSuiteCase(test_index)->Run();
+          if (GTEST_FLAG_GET(fail_fast) &&
+              GetMutableSuiteCase(test_index)->Failed()) {
+            for (int j = test_index + 1; j < total_test_suite_count(); j++) {
+              GetMutableSuiteCase(j)->Skip();
+            }
+            break;
+          }
+        }
+      } else if (Test::HasFatalFailure()) {
+        // If there was a fatal failure during the global setup then we know we
+        // aren't going to run any tests. Explicitly mark all of the tests as
+        // skipped to make this obvious in the output.
+        for (int test_index = 0; test_index < total_test_suite_count();
+             test_index++) {
+          GetMutableSuiteCase(test_index)->Skip();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards. If test
+      // environments aren't recreated for each iteration, only do so on the
+      // last iteration.
+      if (i == repeat - 1 || recreate_environments_when_repeating) {
+        repeater->OnEnvironmentsTearDownStart(*parent_);
+        std::for_each(environments_.rbegin(), environments_.rend(),
+                      TearDownEnvironment);
+        repeater->OnEnvironmentsTearDownEnd(*parent_);
+      }
+    }
+
+    elapsed_time_ = timer.Elapsed();
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG_GET(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+  // Destroy environments in normal code, not in static teardown.
+  bool delete_environment_on_teardown = true;
+  if (delete_environment_on_teardown) {
+    ForEach(environments_, internal::Delete<Environment>);
+    environments_.clear();
+  }
+
+  if (!gtest_is_initialized_before_run_all_tests) {
+    ColoredPrintf(
+        GTestColor::kRed,
+        "\nIMPORTANT NOTICE - DO NOT IGNORE:\n"
+        "This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_
+        "() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_
+        " will start to enforce the valid usage. "
+        "Please fix it ASAP, or IT WILL START TO FAIL.\n");  // NOLINT
+  }
+
+  return !failed;
+}
+
+#if GTEST_HAS_FILE_SYSTEM
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != nullptr) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == nullptr) {
+      ColoredPrintf(GTestColor::kRed,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env, const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const int32_t total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const int32_t shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message() << "Invalid environment variables: you have "
+                                  << kTestShardIndex << " = " << shard_index
+                                  << ", but have left " << kTestTotalShards
+                                  << " unset.\n";
+    ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+                        << "Invalid environment variables: you have "
+                        << kTestTotalShards << " = " << total_shards
+                        << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg =
+        Message() << "Invalid environment variables: we require 0 <= "
+                  << kTestShardIndex << " < " << kTestTotalShards
+                  << ", but you have " << kTestShardIndex << "=" << shard_index
+                  << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+int32_t Int32FromEnvOrDie(const char* var, int32_t default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == nullptr) {
+    return default_val;
+  }
+
+  int32_t result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true if and only if the test should be run on this shard. The test id
+// is some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestSuite and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// https://github.com/google/googletest/blob/main/docs/advanced.md
+// . Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const int32_t total_shards = shard_tests == HONOR_SHARDING_PROTOCOL
+                                   ? Int32FromEnvOrDie(kTestTotalShards, -1)
+                                   : -1;
+  const int32_t shard_index = shard_tests == HONOR_SHARDING_PROTOCOL
+                                  ? Int32FromEnvOrDie(kTestShardIndex, -1)
+                                  : -1;
+
+  const PositiveAndNegativeUnitTestFilter gtest_flag_filter(
+      GTEST_FLAG_GET(filter));
+  const UnitTestFilter disable_test_filter(kDisableTestFilter);
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (auto* test_suite : test_suites_) {
+    const std::string& test_suite_name = test_suite->name_;
+    test_suite->set_should_run(false);
+
+    for (TestInfo* test_info : test_suite->test_info_list()) {
+      const std::string& test_name = test_info->name_;
+      // A test is disabled if test suite name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          disable_test_filter.MatchesName(test_suite_name) ||
+          disable_test_filter.MatchesName(test_name);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          gtest_flag_filter.MatchesTest(test_suite_name, test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG_GET(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_in_another_shard =
+          shard_tests != IGNORE_SHARDING_PROTOCOL &&
+          !ShouldRunTestOnShard(total_shards, shard_index, num_runnable_tests);
+      test_info->is_in_another_shard_ = is_in_another_shard;
+      const bool is_selected = is_runnable && !is_in_another_shard;
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_suite->set_should_run(test_suite->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the given C-string on a single line by replacing all '\n'
+// characters with string "\\n".  If the output takes more than
+// max_length characters, only prints the first max_length characters
+// and "...".
+static void PrintOnOneLine(const char* str, int max_length) {
+  if (str != nullptr) {
+    for (int i = 0; *str != '\0'; ++str) {
+      if (i >= max_length) {
+        printf("...");
+        break;
+      }
+      if (*str == '\n') {
+        printf("\\n");
+        i += 2;
+      } else {
+        printf("%c", *str);
+        ++i;
+      }
+    }
+  }
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  // Print at most this many characters for each type/value parameter.
+  const int kMaxParamLength = 250;
+
+  for (auto* test_suite : test_suites_) {
+    bool printed_test_suite_name = false;
+
+    for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
+      const TestInfo* const test_info = test_suite->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_suite_name) {
+          printed_test_suite_name = true;
+          printf("%s.", test_suite->name());
+          if (test_suite->type_param() != nullptr) {
+            printf("  # %s = ", kTypeParamLabel);
+            // We print the type parameter on a single line to make
+            // the output easy to parse by a program.
+            PrintOnOneLine(test_suite->type_param(), kMaxParamLength);
+          }
+          printf("\n");
+        }
+        printf("  %s", test_info->name());
+        if (test_info->value_param() != nullptr) {
+          printf("  # %s = ", kValueParamLabel);
+          // We print the value parameter on a single line to make the
+          // output easy to parse by a program.
+          PrintOnOneLine(test_info->value_param(), kMaxParamLength);
+        }
+        printf("\n");
+      }
+    }
+  }
+  fflush(stdout);
+#if GTEST_HAS_FILE_SYSTEM
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml" || output_format == "json") {
+    FILE* fileout =
+        OpenFileForWriting(UnitTestOptions::GetAbsolutePathToOutputFile());
+    std::stringstream stream;
+    if (output_format == "xml") {
+      XmlUnitTestResultPrinter(
+          UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
+          .PrintXmlTestsList(&stream, test_suites_);
+    } else if (output_format == "json") {
+      JsonUnitTestResultPrinter(
+          UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
+          .PrintJsonTestList(&stream, test_suites_);
+    }
+    fprintf(fileout, "%s", StringStreamToString(&stream).c_str());
+    fclose(fileout);
+  }
+#endif  // GTEST_HAS_FILE_SYSTEM
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == nullptr) {
+#ifdef GTEST_OS_STACK_TRACE_GETTER_
+    os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_;
+#else
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+#endif  // GTEST_OS_STACK_TRACE_GETTER_
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the most specific TestResult currently running.
+TestResult* UnitTestImpl::current_test_result() {
+  if (current_test_info_ != nullptr) {
+    return &current_test_info_->result_;
+  }
+  if (current_test_suite_ != nullptr) {
+    return &current_test_suite_->ad_hoc_test_result_;
+  }
+  return &ad_hoc_test_result_;
+}
+
+// Shuffles all test suites, and the tests within each test suite,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test suites.
+  ShuffleRange(random(), 0, last_death_test_suite_ + 1, &test_suite_indices_);
+
+  // Shuffles the non-death test suites.
+  ShuffleRange(random(), last_death_test_suite_ + 1,
+               static_cast<int>(test_suites_.size()), &test_suite_indices_);
+
+  // Shuffles the tests inside each test suite.
+  for (auto& test_suite : test_suites_) {
+    test_suite->ShuffleTests(random());
+  }
+}
+
+// Restores the test suites and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_suites_.size(); i++) {
+    // Unshuffles the tests in each test suite.
+    test_suites_[i]->UnshuffleTests();
+    // Resets the index of each test suite.
+    test_suite_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_NO_INLINE_ GTEST_NO_TAIL_CALL_ std::string
+GetCurrentOsStackTraceExceptTop(int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}  // namespace
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false)) throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+static const char* ParseFlagValue(const char* str, const char* flag_name,
+                                  bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == nullptr || flag_name == nullptr) return nullptr;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const std::string flag_str =
+      std::string("--") + GTEST_FLAG_PREFIX_ + flag_name;
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return nullptr;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseFlag(const char* str, const char* flag_name, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag_name, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an int32_t flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseFlag(const char* str, const char* flag_name, int32_t* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag_name, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag_name, value_str,
+                    value);
+}
+
+// Parses a string for a string flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+template <typename String>
+static bool ParseFlag(const char* str, const char* flag_name, String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag_name, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) || SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = GTestColor::kDefault;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == nullptr) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", std::string(str, p).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = GTestColor::kDefault;
+    } else if (ch == 'R') {
+      color = GTestColor::kRed;
+    } else if (ch == 'G') {
+      color = GTestColor::kGreen;
+    } else if (ch == 'Y') {
+      color = GTestColor::kYellow;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+    "This program contains tests written using " GTEST_NAME_
+    ". You can use the\n"
+    "following command line flags to control its behavior:\n"
+    "\n"
+    "Test Selection:\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "list_tests@D\n"
+    "      List the names of all tests instead of running them. The name of\n"
+    "      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "filter=@YPOSITIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+    "      Run only the tests whose name matches one of the positive patterns "
+    "but\n"
+    "      none of the negative patterns. '?' matches any single character; "
+    "'*'\n"
+    "      matches any substring; ':' separates two patterns.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "also_run_disabled_tests@D\n"
+    "      Run all disabled tests too.\n"
+    "\n"
+    "Test Execution:\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "repeat=@Y[COUNT]@D\n"
+    "      Run the tests repeatedly; use a negative count to repeat forever.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "shuffle@D\n"
+    "      Randomize tests' orders on every iteration.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "random_seed=@Y[NUMBER]@D\n"
+    "      Random number seed to use for shuffling test orders (between 1 and\n"
+    "      99999, or 0 to use a seed based on the current time).\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "recreate_environments_when_repeating@D\n"
+    "      Sets up and tears down the global test environment on each repeat\n"
+    "      of the test.\n"
+    "\n"
+    "Test Output:\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+    "      Enable/disable colored output. The default is @Gauto@D.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "brief=1@D\n"
+    "      Only print test failures.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "print_time=0@D\n"
+    "      Don't print the elapsed time of each test.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" GTEST_PATH_SEP_
+    "@Y|@G:@YFILE_PATH]@D\n"
+    "      Generate a JSON or XML report in the given directory or with the "
+    "given\n"
+    "      file name. @YFILE_PATH@D defaults to @Gtest_detail.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+    "  @G--" GTEST_FLAG_PREFIX_
+    "stream_result_to=@YHOST@G:@YPORT@D\n"
+    "      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+    "\n"
+    "Assertion Behavior:\n"
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(GTEST_OS_WINDOWS)
+    "  @G--" GTEST_FLAG_PREFIX_
+    "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+    "      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+    "  @G--" GTEST_FLAG_PREFIX_
+    "break_on_failure@D\n"
+    "      Turn assertion failures into debugger break-points.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "throw_on_failure@D\n"
+    "      Turn assertion failures into C++ exceptions for use by an external\n"
+    "      test framework.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "catch_exceptions=0@D\n"
+    "      Do not report exceptions as test failures. Instead, allow them\n"
+    "      to crash the program or throw a pop-up (on Windows).\n"
+    "\n"
+    "Except for @G--" GTEST_FLAG_PREFIX_
+    "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+    "environment variable of a flag (all letters in upper-case). For example, "
+    "to\n"
+    "disable colored text output, you can either specify "
+    "@G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+    "the @G" GTEST_FLAG_PREFIX_UPPER_
+    "COLOR@D environment variable to @Gno@D.\n"
+    "\n"
+    "For more information, please read the " GTEST_NAME_
+    " documentation at\n"
+    "@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_
+    "\n"
+    "(not one in your own code or tests), please report it to\n"
+    "@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+static bool ParseGoogleTestFlag(const char* const arg) {
+#define GTEST_INTERNAL_PARSE_FLAG(flag_name)  \
+  do {                                        \
+    auto value = GTEST_FLAG_GET(flag_name);   \
+    if (ParseFlag(arg, #flag_name, &value)) { \
+      GTEST_FLAG_SET(flag_name, value);       \
+      return true;                            \
+    }                                         \
+  } while (false)
+
+  GTEST_INTERNAL_PARSE_FLAG(also_run_disabled_tests);
+  GTEST_INTERNAL_PARSE_FLAG(break_on_failure);
+  GTEST_INTERNAL_PARSE_FLAG(catch_exceptions);
+  GTEST_INTERNAL_PARSE_FLAG(color);
+  GTEST_INTERNAL_PARSE_FLAG(death_test_style);
+  GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
+  GTEST_INTERNAL_PARSE_FLAG(fail_fast);
+  GTEST_INTERNAL_PARSE_FLAG(filter);
+  GTEST_INTERNAL_PARSE_FLAG(internal_run_death_test);
+  GTEST_INTERNAL_PARSE_FLAG(list_tests);
+  GTEST_INTERNAL_PARSE_FLAG(output);
+  GTEST_INTERNAL_PARSE_FLAG(brief);
+  GTEST_INTERNAL_PARSE_FLAG(print_time);
+  GTEST_INTERNAL_PARSE_FLAG(print_utf8);
+  GTEST_INTERNAL_PARSE_FLAG(random_seed);
+  GTEST_INTERNAL_PARSE_FLAG(repeat);
+  GTEST_INTERNAL_PARSE_FLAG(recreate_environments_when_repeating);
+  GTEST_INTERNAL_PARSE_FLAG(shuffle);
+  GTEST_INTERNAL_PARSE_FLAG(stack_trace_depth);
+  GTEST_INTERNAL_PARSE_FLAG(stream_result_to);
+  GTEST_INTERNAL_PARSE_FLAG(throw_on_failure);
+  return false;
+}
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_ && GTEST_HAS_FILE_SYSTEM
+static void LoadFlagsFromFile(const std::string& path) {
+  FILE* flagfile = posix::FOpen(path.c_str(), "r");
+  if (!flagfile) {
+    GTEST_LOG_(FATAL) << "Unable to open file \"" << GTEST_FLAG_GET(flagfile)
+                      << "\"";
+  }
+  std::string contents(ReadEntireFile(flagfile));
+  posix::FClose(flagfile);
+  std::vector<std::string> lines;
+  SplitString(contents, '\n', &lines);
+  for (size_t i = 0; i < lines.size(); ++i) {
+    if (lines[i].empty()) continue;
+    if (!ParseGoogleTestFlag(lines[i].c_str())) g_help_flag = true;
+  }
+}
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_ && GTEST_HAS_FILE_SYSTEM
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  std::string flagfile_value;
+  for (int i = 1; i < *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseFlag;
+
+    bool remove_flag = false;
+    if (ParseGoogleTestFlag(arg)) {
+      remove_flag = true;
+#if GTEST_USE_OWN_FLAGFILE_FLAG_ && GTEST_HAS_FILE_SYSTEM
+    } else if (ParseFlag(arg, "flagfile", &flagfile_value)) {
+      GTEST_FLAG_SET(flagfile, flagfile_value);
+      LoadFlagsFromFile(flagfile_value);
+      remove_flag = true;
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_ && GTEST_HAS_FILE_SYSTEM
+    } else if (arg_string == "--help" || HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+
+    if (remove_flag) {
+      // Shift the remainder of the argv list left by one.
+      for (int j = i + 1; j < *argc; ++j) {
+        argv[j - 1] = argv[j];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // Terminate the array with nullptr.
+      argv[*argc] = nullptr;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test. This function updates argc and argv by removing
+// flags that are known to GoogleTest (including other user flags defined using
+// ABSL_FLAG if GoogleTest is built with GTEST_USE_ABSL). Other arguments
+// remain in place. Unrecognized flags are not reported and do not cause the
+// program to exit.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+#ifdef GTEST_HAS_ABSL_FLAGS
+  if (*argc <= 0) return;
+
+  std::vector<char*> positional_args;
+  std::vector<absl::UnrecognizedFlag> unrecognized_flags;
+  absl::ParseAbseilFlagsOnly(*argc, argv, positional_args, unrecognized_flags);
+  absl::flat_hash_set<absl::string_view> unrecognized;
+  for (const auto& flag : unrecognized_flags) {
+    unrecognized.insert(flag.flag_name);
+  }
+  absl::flat_hash_set<char*> positional;
+  for (const auto& arg : positional_args) {
+    positional.insert(arg);
+  }
+
+  int out_pos = 1;
+  int in_pos = 1;
+  for (; in_pos < *argc; ++in_pos) {
+    char* arg = argv[in_pos];
+    absl::string_view arg_str(arg);
+    if (absl::ConsumePrefix(&arg_str, "--")) {
+      // Flag-like argument. If the flag was unrecognized, keep it.
+      // If it was a GoogleTest flag, remove it.
+      if (unrecognized.contains(arg_str)) {
+        argv[out_pos++] = argv[in_pos];
+        continue;
+      }
+    }
+
+    if (arg_str.empty()) {
+      ++in_pos;
+      break;  // '--' indicates that the rest of the arguments are positional
+    }
+
+    // Probably a positional argument. If it is in fact positional, keep it.
+    // If it was a value for the flag argument, remove it.
+    if (positional.contains(arg)) {
+      argv[out_pos++] = arg;
+    }
+  }
+
+  // The rest are positional args for sure.
+  while (in_pos < *argc) {
+    argv[out_pos++] = argv[in_pos++];
+  }
+
+  *argc = out_pos;
+  argv[out_pos] = nullptr;
+#else
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+#endif
+
+  // Fix the value of *_NSGetArgc() on macOS, but if and only if
+  // *_NSGetArgv() == argv
+  // Only applicable to char** version of argv
+#ifdef GTEST_OS_MAC
+#ifndef GTEST_OS_IOS
+  if (*_NSGetArgv() == argv) {
+    *_NSGetArgc() = *argc;
+  }
+#endif
+#endif
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  // We don't want to run the initialization code twice.
+  if (GTestIsInitialized()) return;
+
+  if (*argc <= 0) return;
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#ifdef GTEST_HAS_ABSL
+  absl::InitializeSymbolizer(g_argvs[0].c_str());
+
+#ifdef GTEST_HAS_ABSL_FLAGS
+  // When using the Abseil Flags library, set the program usage message to the
+  // help message, but remove the color-encoding from the message first.
+  absl::SetProgramUsageMessage(absl::StrReplaceAll(
+      kColorEncodedHelpMessage,
+      {{"@D", ""}, {"@R", ""}, {"@G", ""}, {"@Y", ""}, {"@@", "@"}}));
+#endif  // GTEST_HAS_ABSL_FLAGS
+#endif  // GTEST_HAS_ABSL
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
+#else   // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
+#else   // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+// This overloaded version can be used on Arduino/embedded platforms where
+// there is no argc/argv.
+void InitGoogleTest() {
+  // Since Arduino doesn't have a command line, fake out the argc/argv arguments
+  int argc = 1;
+  const auto arg0 = "dummy";
+  char* argv0 = const_cast<char*>(arg0);
+  char** argv = &argv0;
+
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(&argc, argv);
+#else   // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(&argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+#if !defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_) || \
+    !defined(GTEST_CUSTOM_SRCDIR_FUNCTION_)
+// Returns the value of the first environment variable that is set and contains
+// a non-empty string. If there are none, returns the "fallback" string. Adds
+// the director-separator character as a suffix if not provided in the
+// environment variable value.
+static std::string GetDirFromEnv(
+    std::initializer_list<const char*> environment_variables,
+    const char* fallback, char separator) {
+  for (const char* variable_name : environment_variables) {
+    const char* value = internal::posix::GetEnv(variable_name);
+    if (value != nullptr && value[0] != '\0') {
+      if (value[strlen(value) - 1] != separator) {
+        return std::string(value).append(1, separator);
+      }
+      return value;
+    }
+  }
+  return fallback;
+}
+#endif
+
+std::string TempDir() {
+#if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_)
+  return GTEST_CUSTOM_TEMPDIR_FUNCTION_();
+#elif defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_WINDOWS_MOBILE)
+  return GetDirFromEnv({"TEST_TMPDIR", "TEMP"}, "\\temp\\", '\\');
+#elif defined(GTEST_OS_LINUX_ANDROID)
+  return GetDirFromEnv({"TEST_TMPDIR", "TMPDIR"}, "/data/local/tmp/", '/');
+#else
+  return GetDirFromEnv({"TEST_TMPDIR", "TMPDIR"}, "/tmp/", '/');
+#endif
+}
+
+#if GTEST_HAS_FILE_SYSTEM && !defined(GTEST_CUSTOM_SRCDIR_FUNCTION_)
+// Returns the directory path (including terminating separator) of the current
+// executable as derived from argv[0].
+static std::string GetCurrentExecutableDirectory() {
+  internal::FilePath argv_0(internal::GetArgvs()[0]);
+  return argv_0.RemoveFileName().string();
+}
+#endif
+
+#if GTEST_HAS_FILE_SYSTEM
+std::string SrcDir() {
+#if defined(GTEST_CUSTOM_SRCDIR_FUNCTION_)
+  return GTEST_CUSTOM_SRCDIR_FUNCTION_();
+#elif defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_WINDOWS_MOBILE)
+  return GetDirFromEnv({"TEST_SRCDIR"}, GetCurrentExecutableDirectory().c_str(),
+                       '\\');
+#elif defined(GTEST_OS_LINUX_ANDROID)
+  return GetDirFromEnv({"TEST_SRCDIR"}, GetCurrentExecutableDirectory().c_str(),
+                       '/');
+#else
+  return GetDirFromEnv({"TEST_SRCDIR"}, GetCurrentExecutableDirectory().c_str(),
+                       '/');
+#endif
+}
+#endif
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+void ScopedTrace::PushTrace(const char* file, int line, std::string message) {
+  internal::TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message.swap(message);
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+ScopedTrace::~ScopedTrace() GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/src/gtest_main.cc b/3rd-party/googletest/googletest/src/gtest_main.cc
new file mode 100644
index 0000000..8141caf
--- /dev/null
+++ b/3rd-party/googletest/googletest/src/gtest_main.cc
@@ -0,0 +1,66 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <cstdio>
+
+#include "gtest/gtest.h"
+
+#if defined(GTEST_OS_ESP8266) || defined(GTEST_OS_ESP32) || \
+    (defined(GTEST_OS_NRF52) && defined(ARDUINO))
+// Arduino-like platforms: program entry points are setup/loop instead of main.
+
+#ifdef GTEST_OS_ESP8266
+extern "C" {
+#endif
+
+void setup() { testing::InitGoogleTest(); }
+
+void loop() { RUN_ALL_TESTS(); }
+
+#ifdef GTEST_OS_ESP8266
+}
+#endif
+
+#elif defined(GTEST_OS_QURT)
+// QuRT: program entry point is main, but argc/argv are unusable.
+
+GTEST_API_ int main() {
+  printf("Running main() from %s\n", __FILE__);
+  testing::InitGoogleTest();
+  return RUN_ALL_TESTS();
+}
+#else
+// Normal platforms: program entry point is main, argc/argv are initialized.
+
+GTEST_API_ int main(int argc, char **argv) {
+  printf("Running main() from %s\n", __FILE__);
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+#endif
diff --git a/3rd-party/googletest/googletest/test/BUILD.bazel b/3rd-party/googletest/googletest/test/BUILD.bazel
new file mode 100644
index 0000000..1890b6f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/BUILD.bazel
@@ -0,0 +1,595 @@
+# Copyright 2017 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Bazel BUILD for The Google C++ Testing Framework (Google Test)
+
+load("@rules_python//python:defs.bzl", "py_library", "py_test")
+
+licenses(["notice"])
+
+package(default_visibility = ["//:__subpackages__"])
+
+#on windows exclude gtest-tuple.h
+cc_test(
+    name = "gtest_all_test",
+    size = "small",
+    srcs = glob(
+        include = [
+            "gtest-*.cc",
+            "googletest-*.cc",
+            "*.h",
+            "googletest/include/gtest/**/*.h",
+        ],
+        exclude = [
+            "gtest-unittest-api_test.cc",
+            "googletest/src/gtest-all.cc",
+            "gtest_all_test.cc",
+            "gtest-death-test_ex_test.cc",
+            "gtest-listener_test.cc",
+            "gtest-unittest-api_test.cc",
+            "googletest-param-test-test.cc",
+            "googletest-param-test2-test.cc",
+            "googletest-catch-exceptions-test_.cc",
+            "googletest-color-test_.cc",
+            "googletest-env-var-test_.cc",
+            "googletest-failfast-unittest_.cc",
+            "googletest-filter-unittest_.cc",
+            "googletest-global-environment-unittest_.cc",
+            "googletest-break-on-failure-unittest_.cc",
+            "googletest-listener-test.cc",
+            "googletest-message-test.cc",
+            "googletest-output-test_.cc",
+            "googletest-list-tests-unittest_.cc",
+            "googletest-shuffle-test_.cc",
+            "googletest-setuptestsuite-test_.cc",
+            "googletest-uninitialized-test_.cc",
+            "googletest-death-test_ex_test.cc",
+            "googletest-param-test-test",
+            "googletest-throw-on-failure-test_.cc",
+            "googletest-param-test-invalid-name1-test_.cc",
+            "googletest-param-test-invalid-name2-test_.cc",
+        ],
+    ) + select({
+        "//:windows": [],
+        "//conditions:default": [],
+    }),
+    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",
+        "googletest/include",
+        "googletest/include/internal",
+        "googletest/test",
+    ],
+    linkopts = select({
+        "//:qnx": [],
+        "//:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
+    deps = ["//:gtest_main"],
+)
+
+# Tests death tests.
+cc_test(
+    name = "googletest-death-test-test",
+    size = "medium",
+    srcs = ["googletest-death-test-test.cc"],
+    deps = ["//:gtest_main"],
+)
+
+cc_test(
+    name = "gtest_test_macro_stack_footprint_test",
+    size = "small",
+    srcs = ["gtest_test_macro_stack_footprint_test.cc"],
+    deps = ["//:gtest"],
+)
+
+#These googletest tests have their own main()
+cc_test(
+    name = "googletest-listener-test",
+    size = "small",
+    srcs = ["googletest-listener-test.cc"],
+    deps = ["//:gtest_main"],
+)
+
+cc_test(
+    name = "gtest-unittest-api_test",
+    size = "small",
+    srcs = [
+        "gtest-unittest-api_test.cc",
+    ],
+    deps = [
+        "//:gtest",
+    ],
+)
+
+cc_test(
+    name = "googletest-param-test-test",
+    size = "small",
+    srcs = [
+        "googletest-param-test-test.cc",
+        "googletest-param-test-test.h",
+        "googletest-param-test2-test.cc",
+    ],
+    deps = ["//:gtest"],
+)
+
+cc_test(
+    name = "gtest_unittest",
+    size = "small",
+    srcs = ["gtest_unittest.cc"],
+    shard_count = 2,
+    deps = ["//:gtest_main"],
+)
+
+#  Py tests
+
+py_library(
+    name = "gtest_test_utils",
+    testonly = 1,
+    srcs = ["gtest_test_utils.py"],
+    imports = ["."],
+)
+
+cc_binary(
+    name = "gtest_help_test_",
+    testonly = 1,
+    srcs = ["gtest_help_test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+py_test(
+    name = "gtest_help_test",
+    size = "small",
+    srcs = ["gtest_help_test.py"],
+    args = select({
+        "//:has_absl": ["--has_absl_flags"],
+        "//conditions:default": [],
+    }),
+    data = [":gtest_help_test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-output-test_",
+    testonly = 1,
+    srcs = ["googletest-output-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-output-test",
+    size = "small",
+    srcs = ["googletest-output-test.py"],
+    args = select({
+        "//:has_absl": [],
+        "//conditions:default": ["--no_stacktrace_support"],
+    }),
+    data = [
+        "googletest-output-test-golden-lin.txt",
+        ":googletest-output-test_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-color-test_",
+    testonly = 1,
+    srcs = ["googletest-color-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-color-test",
+    size = "small",
+    srcs = ["googletest-color-test.py"],
+    data = [":googletest-color-test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-env-var-test_",
+    testonly = 1,
+    srcs = ["googletest-env-var-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-env-var-test",
+    size = "medium",
+    srcs = ["googletest-env-var-test.py"],
+    data = [":googletest-env-var-test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-failfast-unittest_",
+    testonly = 1,
+    srcs = ["googletest-failfast-unittest_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-failfast-unittest",
+    size = "medium",
+    srcs = ["googletest-failfast-unittest.py"],
+    data = [":googletest-failfast-unittest_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-filter-unittest_",
+    testonly = 1,
+    srcs = ["googletest-filter-unittest_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-filter-unittest",
+    size = "medium",
+    srcs = ["googletest-filter-unittest.py"],
+    data = [":googletest-filter-unittest_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-global-environment-unittest_",
+    testonly = 1,
+    srcs = ["googletest-global-environment-unittest_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-global-environment-unittest",
+    size = "medium",
+    srcs = ["googletest-global-environment-unittest.py"],
+    data = [":googletest-global-environment-unittest_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-break-on-failure-unittest_",
+    testonly = 1,
+    srcs = ["googletest-break-on-failure-unittest_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-break-on-failure-unittest",
+    size = "small",
+    srcs = ["googletest-break-on-failure-unittest.py"],
+    data = [":googletest-break-on-failure-unittest_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_test(
+    name = "gtest_assert_by_exception_test",
+    size = "small",
+    srcs = ["gtest_assert_by_exception_test.cc"],
+    deps = ["//:gtest"],
+)
+
+cc_binary(
+    name = "googletest-throw-on-failure-test_",
+    testonly = 1,
+    srcs = ["googletest-throw-on-failure-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-throw-on-failure-test",
+    size = "small",
+    srcs = ["googletest-throw-on-failure-test.py"],
+    data = [":googletest-throw-on-failure-test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-list-tests-unittest_",
+    testonly = 1,
+    srcs = ["googletest-list-tests-unittest_.cc"],
+    deps = ["//:gtest"],
+)
+
+cc_test(
+    name = "gtest_skip_test",
+    size = "small",
+    srcs = ["gtest_skip_test.cc"],
+    deps = ["//:gtest_main"],
+)
+
+cc_test(
+    name = "gtest_skip_in_environment_setup_test",
+    size = "small",
+    srcs = ["gtest_skip_in_environment_setup_test.cc"],
+    deps = ["//:gtest_main"],
+)
+
+py_test(
+    name = "gtest_skip_check_output_test",
+    size = "small",
+    srcs = ["gtest_skip_check_output_test.py"],
+    data = [":gtest_skip_test"],
+    deps = [":gtest_test_utils"],
+)
+
+py_test(
+    name = "gtest_skip_environment_check_output_test",
+    size = "small",
+    srcs = ["gtest_skip_environment_check_output_test.py"],
+    data = [
+        ":gtest_skip_in_environment_setup_test",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+py_test(
+    name = "googletest-list-tests-unittest",
+    size = "small",
+    srcs = ["googletest-list-tests-unittest.py"],
+    data = [":googletest-list-tests-unittest_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-shuffle-test_",
+    srcs = ["googletest-shuffle-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-shuffle-test",
+    size = "small",
+    srcs = ["googletest-shuffle-test.py"],
+    data = [":googletest-shuffle-test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-catch-exceptions-no-ex-test_",
+    testonly = 1,
+    srcs = ["googletest-catch-exceptions-test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+cc_binary(
+    name = "googletest-catch-exceptions-ex-test_",
+    testonly = 1,
+    srcs = ["googletest-catch-exceptions-test_.cc"],
+    copts = ["-fexceptions"],
+    deps = ["//:gtest_main"],
+)
+
+py_test(
+    name = "googletest-catch-exceptions-test",
+    size = "small",
+    srcs = ["googletest-catch-exceptions-test.py"],
+    data = [
+        ":googletest-catch-exceptions-ex-test_",
+        ":googletest-catch-exceptions-no-ex-test_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "gtest_xml_output_unittest_",
+    testonly = 1,
+    srcs = ["gtest_xml_output_unittest_.cc"],
+    deps = ["//:gtest"],
+)
+
+cc_test(
+    name = "gtest_no_test_unittest",
+    size = "small",
+    srcs = ["gtest_no_test_unittest.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "gtest_xml_output_unittest",
+    size = "small",
+    srcs = [
+        "gtest_xml_output_unittest.py",
+        "gtest_xml_test_utils.py",
+    ],
+    args = select({
+        "//:has_absl": [],
+        "//conditions:default": ["--no_stacktrace_support"],
+    }),
+    data = [
+        # We invoke gtest_no_test_unittest to verify the XML output
+        # when the test program contains no test definition.
+        ":gtest_no_test_unittest",
+        ":gtest_xml_output_unittest_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "gtest_xml_outfile1_test_",
+    testonly = 1,
+    srcs = ["gtest_xml_outfile1_test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+cc_binary(
+    name = "gtest_xml_outfile2_test_",
+    testonly = 1,
+    srcs = ["gtest_xml_outfile2_test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+py_test(
+    name = "gtest_xml_outfiles_test",
+    size = "small",
+    srcs = [
+        "gtest_xml_outfiles_test.py",
+        "gtest_xml_test_utils.py",
+    ],
+    data = [
+        ":gtest_xml_outfile1_test_",
+        ":gtest_xml_outfile2_test_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-setuptestsuite-test_",
+    testonly = 1,
+    srcs = ["googletest-setuptestsuite-test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+py_test(
+    name = "googletest-setuptestsuite-test",
+    size = "medium",
+    srcs = ["googletest-setuptestsuite-test.py"],
+    data = [":googletest-setuptestsuite-test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "googletest-uninitialized-test_",
+    testonly = 1,
+    srcs = ["googletest-uninitialized-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-uninitialized-test",
+    size = "medium",
+    srcs = ["googletest-uninitialized-test.py"],
+    data = ["googletest-uninitialized-test_"],
+    deps = [":gtest_test_utils"],
+)
+
+cc_binary(
+    name = "gtest_testbridge_test_",
+    testonly = 1,
+    srcs = ["gtest_testbridge_test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+# Tests that filtering via testbridge works
+py_test(
+    name = "gtest_testbridge_test",
+    size = "small",
+    srcs = ["gtest_testbridge_test.py"],
+    data = [":gtest_testbridge_test_"],
+    deps = [":gtest_test_utils"],
+)
+
+py_test(
+    name = "googletest-json-outfiles-test",
+    size = "small",
+    srcs = [
+        "googletest-json-outfiles-test.py",
+        "gtest_json_test_utils.py",
+    ],
+    data = [
+        ":gtest_xml_outfile1_test_",
+        ":gtest_xml_outfile2_test_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+py_test(
+    name = "googletest-json-output-unittest",
+    size = "medium",
+    srcs = [
+        "googletest-json-output-unittest.py",
+        "gtest_json_test_utils.py",
+    ],
+    args = select({
+        "//:has_absl": [],
+        "//conditions:default": ["--no_stacktrace_support"],
+    }),
+    data = [
+        # We invoke gtest_no_test_unittest to verify the JSON output
+        # when the test program contains no test definition.
+        ":gtest_no_test_unittest",
+        ":gtest_xml_output_unittest_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+# Verifies interaction of death tests and exceptions.
+cc_test(
+    name = "googletest-death-test_ex_catch_test",
+    size = "medium",
+    srcs = ["googletest-death-test_ex_test.cc"],
+    copts = ["-fexceptions"],
+    defines = ["GTEST_ENABLE_CATCH_EXCEPTIONS_=1"],
+    deps = ["//:gtest"],
+)
+
+cc_binary(
+    name = "googletest-param-test-invalid-name1-test_",
+    testonly = 1,
+    srcs = ["googletest-param-test-invalid-name1-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+cc_binary(
+    name = "googletest-param-test-invalid-name2-test_",
+    testonly = 1,
+    srcs = ["googletest-param-test-invalid-name2-test_.cc"],
+    deps = ["//:gtest"],
+)
+
+py_test(
+    name = "googletest-param-test-invalid-name1-test",
+    size = "small",
+    srcs = ["googletest-param-test-invalid-name1-test.py"],
+    data = [":googletest-param-test-invalid-name1-test_"],
+    tags = [
+        "no_test_msvc2015",
+        "no_test_msvc2017",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
+py_test(
+    name = "googletest-param-test-invalid-name2-test",
+    size = "small",
+    srcs = ["googletest-param-test-invalid-name2-test.py"],
+    data = [":googletest-param-test-invalid-name2-test_"],
+    tags = [
+        "no_test_msvc2015",
+        "no_test_msvc2017",
+    ],
+    deps = [":gtest_test_utils"],
+)
diff --git a/3rd-party/googletest/googletest/test/googletest-break-on-failure-unittest.py b/3rd-party/googletest/googletest/test/googletest-break-on-failure-unittest.py
new file mode 100755
index 0000000..e314b5c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-break-on-failure-unittest.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test's break-on-failure mode.
+
+A user can ask Google Test to seg-fault when an assertion fails, using
+either the GTEST_BREAK_ON_FAILURE environment variable or the
+--gtest_break_on_failure flag.  This script tests such functionality
+by invoking googletest-break-on-failure-unittest_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+import os
+from googletest.test import gtest_test_utils
+
+# Constants.
+
+IS_WINDOWS = os.name == 'nt'
+
+# The environment variable for enabling/disabling the break-on-failure mode.
+BREAK_ON_FAILURE_ENV_VAR = 'GTEST_BREAK_ON_FAILURE'
+
+# The command line flag for enabling/disabling the break-on-failure mode.
+BREAK_ON_FAILURE_FLAG = 'gtest_break_on_failure'
+
+# The environment variable for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE_ENV_VAR = 'GTEST_THROW_ON_FAILURE'
+
+# The environment variable for enabling/disabling the catch-exceptions mode.
+CATCH_EXCEPTIONS_ENV_VAR = 'GTEST_CATCH_EXCEPTIONS'
+
+# Path to the googletest-break-on-failure-unittest_ program.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'googletest-break-on-failure-unittest_'
+)
+
+
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely.  Therefore they are incompatible with
+# the premature-exit-file protocol by design.  Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
+
+def Run(command):
+  """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
+
+  p = gtest_test_utils.Subprocess(command, env=environ)
+  if p.terminated_by_signal:
+    return 1
+  else:
+    return 0
+
+
+# The tests.
+
+
+class GTestBreakOnFailureUnitTest(gtest_test_utils.TestCase):
+  """Unit test for Google Test's break-on-failure mode.
+
+  Tests using the GTEST_BREAK_ON_FAILURE environment variable or
+  the --gtest_break_on_failure flag to turn assertion failures into
+  segmentation faults.
+  """
+
+  def RunAndVerify(self, env_var_value, flag_value, expect_seg_fault):
+    """Runs googletest-break-on-failure-unittest_ and verifies its behavior.
+
+    Runs googletest-break-on-failure-unittest_ and verifies that it does
+    (or does not) have a seg-fault.
+
+    Args:
+      env_var_value:    value of the GTEST_BREAK_ON_FAILURE environment
+        variable; None if the variable should be unset.
+      flag_value:       value of the --gtest_break_on_failure flag; None if the
+        flag should not be present.
+      expect_seg_fault: 1 if the program is expected to generate a seg-fault; 0
+        otherwise.
+    """
+
+    SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, env_var_value)
+
+    if env_var_value is None:
+      env_var_value_msg = ' is not set'
+    else:
+      env_var_value_msg = '=' + env_var_value
+
+    if flag_value is None:
+      flag = ''
+    elif flag_value == '0':
+      flag = '--%s=0' % BREAK_ON_FAILURE_FLAG
+    else:
+      flag = '--%s' % BREAK_ON_FAILURE_FLAG
+
+    command = [EXE_PATH]
+    if flag:
+      command.append(flag)
+
+    if expect_seg_fault:
+      should_or_not = 'should'
+    else:
+      should_or_not = 'should not'
+
+    has_seg_fault = Run(command)
+
+    SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, None)
+
+    msg = 'when %s%s, an assertion failure in "%s" %s cause a seg-fault.' % (
+        BREAK_ON_FAILURE_ENV_VAR,
+        env_var_value_msg,
+        ' '.join(command),
+        should_or_not,
+    )
+    self.assertTrue(has_seg_fault == expect_seg_fault, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(env_var_value=None, flag_value=None, expect_seg_fault=0)
+
+  def testEnvVar(self):
+    """Tests using the GTEST_BREAK_ON_FAILURE environment variable."""
+
+    self.RunAndVerify(env_var_value='0', flag_value=None, expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='1', flag_value=None, expect_seg_fault=1)
+
+  def testFlag(self):
+    """Tests using the --gtest_break_on_failure flag."""
+
+    self.RunAndVerify(env_var_value=None, flag_value='0', expect_seg_fault=0)
+    self.RunAndVerify(env_var_value=None, flag_value='1', expect_seg_fault=1)
+
+  def testFlagOverridesEnvVar(self):
+    """Tests that the flag overrides the environment variable."""
+
+    self.RunAndVerify(env_var_value='0', flag_value='0', expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='0', flag_value='1', expect_seg_fault=1)
+    self.RunAndVerify(env_var_value='1', flag_value='0', expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='1', flag_value='1', expect_seg_fault=1)
+
+  def testBreakOnFailureOverridesThrowOnFailure(self):
+    """Tests that gtest_break_on_failure overrides gtest_throw_on_failure."""
+
+    SetEnvVar(THROW_ON_FAILURE_ENV_VAR, '1')
+    try:
+      self.RunAndVerify(env_var_value=None, flag_value='1', expect_seg_fault=1)
+    finally:
+      SetEnvVar(THROW_ON_FAILURE_ENV_VAR, None)
+
+  if IS_WINDOWS:
+
+    def testCatchExceptionsDoesNotInterfere(self):
+      """Tests that gtest_catch_exceptions doesn't interfere."""
+
+      SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, '1')
+      try:
+        self.RunAndVerify(env_var_value='1', flag_value='1', expect_seg_fault=1)
+      finally:
+        SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, None)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-break-on-failure-unittest_.cc b/3rd-party/googletest/googletest/test/googletest-break-on-failure-unittest_.cc
new file mode 100644
index 0000000..337e34c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-break-on-failure-unittest_.cc
@@ -0,0 +1,83 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test's break-on-failure mode.
+//
+// A user can ask Google Test to seg-fault when an assertion fails, using
+// either the GTEST_BREAK_ON_FAILURE environment variable or the
+// --gtest_break_on_failure flag.  This file is used for testing such
+// functionality.
+//
+// This program will be invoked from a Python unit test.  It is
+// expected to fail.  Don't run it directly.
+
+#include "gtest/gtest.h"
+
+#ifdef GTEST_OS_WINDOWS
+#include <stdlib.h>
+#include <windows.h>
+#endif
+
+namespace {
+
+// A test that's expected to fail.
+TEST(Foo, Bar) { EXPECT_EQ(2, 3); }
+
+#if GTEST_HAS_SEH && !defined(GTEST_OS_WINDOWS_MOBILE)
+// On Windows Mobile global exception handlers are not supported.
+LONG WINAPI
+ExitWithExceptionCode(struct _EXCEPTION_POINTERS* exception_pointers) {
+  exit(exception_pointers->ExceptionRecord->ExceptionCode);
+}
+#endif
+
+}  // namespace
+
+int main(int argc, char** argv) {
+#ifdef GTEST_OS_WINDOWS
+  // Suppresses display of the Windows error dialog upon encountering
+  // a general protection fault (segment violation).
+  SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);
+
+#if GTEST_HAS_SEH && !defined(GTEST_OS_WINDOWS_MOBILE)
+
+  // The default unhandled exception filter does not always exit
+  // with the exception code as exit code - for example it exits with
+  // 0 for EXCEPTION_ACCESS_VIOLATION and 1 for EXCEPTION_BREAKPOINT
+  // if the application is compiled in debug mode. Thus we use our own
+  // filter which always exits with the exception code for unhandled
+  // exceptions.
+  SetUnhandledExceptionFilter(ExitWithExceptionCode);
+
+#endif
+#endif  // GTEST_OS_WINDOWS
+  testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-catch-exceptions-test.py b/3rd-party/googletest/googletest/test/googletest-catch-exceptions-test.py
new file mode 100755
index 0000000..180e18d
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-catch-exceptions-test.py
@@ -0,0 +1,315 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Google Inc.  All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests Google Test's exception catching behavior.
+
+This script invokes googletest-catch-exceptions-test_ and
+googletest-catch-exceptions-ex-test_ (programs written with
+Google Test) and verifies their output.
+"""
+
+from googletest.test import gtest_test_utils
+
+# Constants.
+FLAG_PREFIX = '--gtest_'
+LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
+NO_CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions=0'
+FILTER_FLAG = FLAG_PREFIX + 'filter'
+
+# Path to the googletest-catch-exceptions-ex-test_ binary, compiled with
+# exceptions enabled.
+EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'googletest-catch-exceptions-ex-test_'
+)
+
+# Path to the googletest-catch-exceptions-test_ binary, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'googletest-catch-exceptions-no-ex-test_'
+)
+
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely.  Therefore they are incompatible with
+# the premature-exit-file protocol by design.  Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
+TEST_LIST = gtest_test_utils.Subprocess(
+    [EXE_PATH, LIST_TESTS_FLAG], env=environ
+).output
+
+SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST
+
+if SUPPORTS_SEH_EXCEPTIONS:
+  BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH], env=environ).output
+
+EX_BINARY_OUTPUT = gtest_test_utils.Subprocess(
+    [EX_EXE_PATH], env=environ
+).output
+
+
+# The tests.
+if SUPPORTS_SEH_EXCEPTIONS:
+
+  class CatchSehExceptionsTest(gtest_test_utils.TestCase):
+    """Tests exception-catching behavior."""
+
+    def TestSehExceptions(self, test_output):
+      self.assertIn(
+          (
+              'SEH exception with code 0x2a thrown '
+              "in the test fixture's constructor"
+          ),
+          test_output,
+      )
+      self.assertIn(
+          (
+              'SEH exception with code 0x2a thrown '
+              "in the test fixture's destructor"
+          ),
+          test_output,
+      )
+      self.assertIn(
+          'SEH exception with code 0x2a thrown in SetUpTestSuite()', test_output
+      )
+      self.assertIn(
+          'SEH exception with code 0x2a thrown in TearDownTestSuite()',
+          test_output,
+      )
+      self.assertIn(
+          'SEH exception with code 0x2a thrown in SetUp()', test_output
+      )
+      self.assertIn(
+          'SEH exception with code 0x2a thrown in TearDown()', test_output
+      )
+      self.assertIn(
+          'SEH exception with code 0x2a thrown in the test body', test_output
+      )
+
+    def testCatchesSehExceptionsWithCxxExceptionsEnabled(self):
+      self.TestSehExceptions(EX_BINARY_OUTPUT)
+
+    def testCatchesSehExceptionsWithCxxExceptionsDisabled(self):
+      self.TestSehExceptions(BINARY_OUTPUT)
+
+
+class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
+  """Tests C++ exception-catching behavior.
+
+  Tests in this test case verify that:
+  * C++ exceptions are caught and logged as C++ (not SEH) exceptions
+  * Exception thrown affect the remainder of the test work flow in the
+    expected manner.
+  """
+
+  def testCatchesCxxExceptionsInFixtureConstructor(self):
+    self.assertTrue(
+        'C++ exception with description '
+        '"Standard C++ exception" thrown '
+        "in the test fixture's constructor"
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'unexpected' not in EX_BINARY_OUTPUT,
+        (
+            'This failure belongs in this test only if '
+            '"CxxExceptionInConstructorTest" (no quotes) '
+            'appears on the same line as words "called unexpectedly"'
+        ),
+    )
+
+  if (
+      'CxxExceptionInDestructorTest.ThrowsExceptionInDestructor'
+      in EX_BINARY_OUTPUT
+  ):
+
+    def testCatchesCxxExceptionsInFixtureDestructor(self):
+      self.assertTrue(
+          'C++ exception with description '
+          '"Standard C++ exception" thrown '
+          "in the test fixture's destructor"
+          in EX_BINARY_OUTPUT,
+          EX_BINARY_OUTPUT,
+      )
+      self.assertTrue(
+          'CxxExceptionInDestructorTest::TearDownTestSuite() '
+          'called as expected.'
+          in EX_BINARY_OUTPUT,
+          EX_BINARY_OUTPUT,
+      )
+
+  def testCatchesCxxExceptionsInSetUpTestCase(self):
+    self.assertTrue(
+        'C++ exception with description "Standard C++ exception"'
+        ' thrown in SetUpTestSuite()'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInConstructorTest::TearDownTestSuite() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertFalse(
+        'CxxExceptionInSetUpTestSuiteTest constructor called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertFalse(
+        'CxxExceptionInSetUpTestSuiteTest destructor called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertFalse(
+        'CxxExceptionInSetUpTestSuiteTest::SetUp() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertFalse(
+        'CxxExceptionInSetUpTestSuiteTest::TearDown() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertFalse(
+        'CxxExceptionInSetUpTestSuiteTest test body called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+
+  def testCatchesCxxExceptionsInTearDownTestCase(self):
+    self.assertTrue(
+        'C++ exception with description "Standard C++ exception"'
+        ' thrown in TearDownTestSuite()'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+
+  def testCatchesCxxExceptionsInSetUp(self):
+    self.assertTrue(
+        'C++ exception with description "Standard C++ exception"'
+        ' thrown in SetUp()'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInSetUpTest::TearDownTestSuite() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInSetUpTest destructor called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInSetUpTest::TearDown() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'unexpected' not in EX_BINARY_OUTPUT,
+        (
+            'This failure belongs in this test only if '
+            '"CxxExceptionInSetUpTest" (no quotes) '
+            'appears on the same line as words "called unexpectedly"'
+        ),
+    )
+
+  def testCatchesCxxExceptionsInTearDown(self):
+    self.assertTrue(
+        'C++ exception with description "Standard C++ exception"'
+        ' thrown in TearDown()'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInTearDownTest::TearDownTestSuite() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInTearDownTest destructor called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+
+  def testCatchesCxxExceptionsInTestBody(self):
+    self.assertTrue(
+        'C++ exception with description "Standard C++ exception"'
+        ' thrown in the test body'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInTestBodyTest::TearDownTestSuite() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInTestBodyTest destructor called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+    self.assertTrue(
+        'CxxExceptionInTestBodyTest::TearDown() called as expected.'
+        in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+
+  def testCatchesNonStdCxxExceptions(self):
+    self.assertTrue(
+        'Unknown C++ exception thrown in the test body' in EX_BINARY_OUTPUT,
+        EX_BINARY_OUTPUT,
+    )
+
+  def testUnhandledCxxExceptionsAbortTheProgram(self):
+    # Filters out SEH exception tests on Windows. Unhandled SEH exceptions
+    # cause tests to show pop-up windows there.
+    filter_out_seh_tests_flag = FILTER_FLAG + '=-*Seh*'
+    # By default, Google Test doesn't catch the exceptions.
+    uncaught_exceptions_ex_binary_output = gtest_test_utils.Subprocess(
+        [EX_EXE_PATH, NO_CATCH_EXCEPTIONS_FLAG, filter_out_seh_tests_flag],
+        env=environ,
+    ).output
+
+    self.assertIn(
+        'Unhandled C++ exception terminating the program',
+        uncaught_exceptions_ex_binary_output,
+    )
+    self.assertNotIn('unexpected', uncaught_exceptions_ex_binary_output)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-catch-exceptions-test_.cc b/3rd-party/googletest/googletest/test/googletest-catch-exceptions-test_.cc
new file mode 100644
index 0000000..3c8f4f4
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-catch-exceptions-test_.cc
@@ -0,0 +1,289 @@
+// Copyright 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for Google Test itself. Tests in this file throw C++ or SEH
+// exceptions, and the output is verified by
+// googletest-catch-exceptions-test.py.
+
+#include <stdio.h>   // NOLINT
+#include <stdlib.h>  // For exit().
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_SEH
+#include <windows.h>
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+#include <exception>  // For set_terminate().
+#include <stdexcept>
+#endif
+
+using testing::Test;
+
+#if GTEST_HAS_SEH
+
+class SehExceptionInConstructorTest : public Test {
+ public:
+  SehExceptionInConstructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInConstructorTest, ThrowsExceptionInConstructor) {}
+
+class SehExceptionInDestructorTest : public Test {
+ public:
+  ~SehExceptionInDestructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+
+class SehExceptionInSetUpTestSuiteTest : public Test {
+ public:
+  static void SetUpTestSuite() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTestSuiteTest, ThrowsExceptionInSetUpTestSuite) {}
+
+class SehExceptionInTearDownTestSuiteTest : public Test {
+ public:
+  static void TearDownTestSuite() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTestSuiteTest,
+       ThrowsExceptionInTearDownTestSuite) {}
+
+class SehExceptionInSetUpTest : public Test {
+ protected:
+  virtual void SetUp() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTest, ThrowsExceptionInSetUp) {}
+
+class SehExceptionInTearDownTest : public Test {
+ protected:
+  virtual void TearDown() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+TEST(SehExceptionTest, ThrowsSehException) { RaiseException(42, 0, 0, NULL); }
+
+#endif  // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+class CxxExceptionInConstructorTest : public Test {
+ public:
+  CxxExceptionInConstructorTest() {
+    // Without this macro VC++ complains about unreachable code at the end of
+    // the constructor.
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        throw std::runtime_error("Standard C++ exception"));
+  }
+
+  static void TearDownTestSuite() {
+    printf("%s",
+           "CxxExceptionInConstructorTest::TearDownTestSuite() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInConstructorTest() override {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest destructor "
+                  << "called unexpectedly.";
+  }
+
+  void SetUp() override {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest::SetUp() "
+                  << "called unexpectedly.";
+  }
+
+  void TearDown() override {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest::TearDown() "
+                  << "called unexpectedly.";
+  }
+};
+
+TEST_F(CxxExceptionInConstructorTest, ThrowsExceptionInConstructor) {
+  ADD_FAILURE() << "CxxExceptionInConstructorTest test body "
+                << "called unexpectedly.";
+}
+
+class CxxExceptionInSetUpTestSuiteTest : public Test {
+ public:
+  CxxExceptionInSetUpTestSuiteTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTestSuiteTest constructor "
+           "called as expected.\n");
+  }
+
+  static void SetUpTestSuite() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+
+  static void TearDownTestSuite() {
+    printf("%s",
+           "CxxExceptionInSetUpTestSuiteTest::TearDownTestSuite() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInSetUpTestSuiteTest() override {
+    printf("%s",
+           "CxxExceptionInSetUpTestSuiteTest destructor "
+           "called as expected.\n");
+  }
+
+  void SetUp() override {
+    printf("%s",
+           "CxxExceptionInSetUpTestSuiteTest::SetUp() "
+           "called as expected.\n");
+  }
+
+  void TearDown() override {
+    printf("%s",
+           "CxxExceptionInSetUpTestSuiteTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInSetUpTestSuiteTest, ThrowsExceptionInSetUpTestSuite) {
+  printf("%s",
+         "CxxExceptionInSetUpTestSuiteTest test body "
+         "called as expected.\n");
+}
+
+class CxxExceptionInTearDownTestSuiteTest : public Test {
+ public:
+  static void TearDownTestSuite() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+};
+
+TEST_F(CxxExceptionInTearDownTestSuiteTest,
+       ThrowsExceptionInTearDownTestSuite) {}
+
+class CxxExceptionInSetUpTest : public Test {
+ public:
+  static void TearDownTestSuite() {
+    printf("%s",
+           "CxxExceptionInSetUpTest::TearDownTestSuite() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInSetUpTest() override {
+    printf("%s",
+           "CxxExceptionInSetUpTest destructor "
+           "called as expected.\n");
+  }
+
+  void SetUp() override { throw std::runtime_error("Standard C++ exception"); }
+
+  void TearDown() override {
+    printf("%s",
+           "CxxExceptionInSetUpTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInSetUpTest, ThrowsExceptionInSetUp) {
+  ADD_FAILURE() << "CxxExceptionInSetUpTest test body "
+                << "called unexpectedly.";
+}
+
+class CxxExceptionInTearDownTest : public Test {
+ public:
+  static void TearDownTestSuite() {
+    printf("%s",
+           "CxxExceptionInTearDownTest::TearDownTestSuite() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInTearDownTest() override {
+    printf("%s",
+           "CxxExceptionInTearDownTest destructor "
+           "called as expected.\n");
+  }
+
+  void TearDown() override {
+    throw std::runtime_error("Standard C++ exception");
+  }
+};
+
+TEST_F(CxxExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+class CxxExceptionInTestBodyTest : public Test {
+ public:
+  static void TearDownTestSuite() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest::TearDownTestSuite() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInTestBodyTest() override {
+    printf("%s",
+           "CxxExceptionInTestBodyTest destructor "
+           "called as expected.\n");
+  }
+
+  void TearDown() override {
+    printf("%s",
+           "CxxExceptionInTestBodyTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInTestBodyTest, ThrowsStdCxxException) {
+  throw std::runtime_error("Standard C++ exception");
+}
+
+TEST(CxxExceptionTest, ThrowsNonStdCxxException) { throw "C-string"; }
+
+// This terminate handler aborts the program using exit() rather than abort().
+// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
+// ones.
+void TerminateHandler() {
+  fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
+  fflush(nullptr);
+  exit(3);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+int main(int argc, char** argv) {
+#if GTEST_HAS_EXCEPTIONS
+  std::set_terminate(&TerminateHandler);
+#endif
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-color-test.py b/3rd-party/googletest/googletest/test/googletest-color-test.py
new file mode 100755
index 0000000..8968cf1
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-color-test.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test correctly determines whether to use colors."""
+
+import os
+from googletest.test import gtest_test_utils
+
+IS_WINDOWS = os.name == 'nt'
+
+COLOR_ENV_VAR = 'GTEST_COLOR'
+COLOR_FLAG = 'gtest_color'
+COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-color-test_')
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    os.environ[env_var] = value
+  elif env_var in os.environ:
+    del os.environ[env_var]
+
+
+def UsesColor(term, color_env_var, color_flag):
+  """Runs googletest-color-test_ and returns its exit code."""
+
+  SetEnvVar('TERM', term)
+  SetEnvVar(COLOR_ENV_VAR, color_env_var)
+
+  if color_flag is None:
+    args = []
+  else:
+    args = ['--%s=%s' % (COLOR_FLAG, color_flag)]
+  p = gtest_test_utils.Subprocess([COMMAND] + args)
+  return not p.exited or p.exit_code
+
+
+class GTestColorTest(gtest_test_utils.TestCase):
+
+  def testNoEnvVarNoFlag(self):
+    """Tests the case when there's neither GTEST_COLOR nor --gtest_color."""
+
+    if not IS_WINDOWS:
+      self.assertTrue(not UsesColor('dumb', None, None))
+      self.assertTrue(not UsesColor('emacs', None, None))
+      self.assertTrue(not UsesColor('xterm-mono', None, None))
+      self.assertTrue(not UsesColor('unknown', None, None))
+      self.assertTrue(not UsesColor(None, None, None))
+    self.assertTrue(UsesColor('linux', None, None))
+    self.assertTrue(UsesColor('cygwin', None, None))
+    self.assertTrue(UsesColor('xterm', None, None))
+    self.assertTrue(UsesColor('xterm-color', None, None))
+    self.assertTrue(UsesColor('xterm-kitty', None, None))
+    self.assertTrue(UsesColor('alacritty', None, None))
+    self.assertTrue(UsesColor('xterm-256color', None, None))
+
+  def testFlagOnly(self):
+    """Tests the case when there's --gtest_color but not GTEST_COLOR."""
+
+    self.assertTrue(not UsesColor('dumb', None, 'no'))
+    self.assertTrue(not UsesColor('xterm-color', None, 'no'))
+    if not IS_WINDOWS:
+      self.assertTrue(not UsesColor('emacs', None, 'auto'))
+    self.assertTrue(UsesColor('xterm', None, 'auto'))
+    self.assertTrue(UsesColor('dumb', None, 'yes'))
+    self.assertTrue(UsesColor('xterm', None, 'yes'))
+
+  def testEnvVarOnly(self):
+    """Tests the case when there's GTEST_COLOR but not --gtest_color."""
+
+    self.assertTrue(not UsesColor('dumb', 'no', None))
+    self.assertTrue(not UsesColor('xterm-color', 'no', None))
+    if not IS_WINDOWS:
+      self.assertTrue(not UsesColor('dumb', 'auto', None))
+    self.assertTrue(UsesColor('xterm-color', 'auto', None))
+    self.assertTrue(UsesColor('dumb', 'yes', None))
+    self.assertTrue(UsesColor('xterm-color', 'yes', None))
+
+  def testEnvVarAndFlag(self):
+    """Tests the case when there are both GTEST_COLOR and --gtest_color."""
+
+    self.assertTrue(not UsesColor('xterm-color', 'no', 'no'))
+    self.assertTrue(UsesColor('dumb', 'no', 'yes'))
+    self.assertTrue(UsesColor('xterm-color', 'no', 'auto'))
+
+  def testAliasesOfYesAndNo(self):
+    """Tests using aliases in specifying --gtest_color."""
+
+    self.assertTrue(UsesColor('dumb', None, 'true'))
+    self.assertTrue(UsesColor('dumb', None, 'YES'))
+    self.assertTrue(UsesColor('dumb', None, 'T'))
+    self.assertTrue(UsesColor('dumb', None, '1'))
+
+    self.assertTrue(not UsesColor('xterm', None, 'f'))
+    self.assertTrue(not UsesColor('xterm', None, 'false'))
+    self.assertTrue(not UsesColor('xterm', None, '0'))
+    self.assertTrue(not UsesColor('xterm', None, 'unknown'))
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-color-test_.cc b/3rd-party/googletest/googletest/test/googletest-color-test_.cc
new file mode 100644
index 0000000..55657b7
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-color-test_.cc
@@ -0,0 +1,60 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A helper program for testing how Google Test determines whether to use
+// colors in the output.  It prints "YES" and returns 1 if Google Test
+// decides to use colors, and prints "NO" and returns 0 otherwise.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+using testing::internal::ShouldUseColor;
+
+// The purpose of this is to ensure that the UnitTest singleton is
+// created before main() is entered, and thus that ShouldUseColor()
+// works the same way as in a real Google-Test-based test.  We don't actual
+// run the TEST itself.
+TEST(GTestColorTest, Dummy) {}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  if (ShouldUseColor(true)) {
+    // Google Test decides to use colors in the output (assuming it
+    // goes to a TTY).
+    printf("YES\n");
+    return 1;
+  } else {
+    // Google Test decides not to use colors in the output.
+    printf("NO\n");
+    return 0;
+  }
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-death-test-test.cc b/3rd-party/googletest/googletest/test/googletest-death-test-test.cc
new file mode 100644
index 0000000..44b8046
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-death-test-test.cc
@@ -0,0 +1,1512 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for death tests.
+
+#include <stdlib.h>
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-filepath.h"
+
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+#ifdef GTEST_OS_WINDOWS
+#include <direct.h>  // For chdir().
+#include <fcntl.h>   // For O_BINARY
+#include <io.h>
+#else
+#include <sys/wait.h>  // For waitpid.
+#include <unistd.h>
+#endif  // GTEST_OS_WINDOWS
+
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <string>
+#include <vector>
+
+#ifdef GTEST_OS_LINUX
+#include <sys/time.h>
+#endif  // GTEST_OS_LINUX
+
+#include "gtest/gtest-spi.h"
+#include "src/gtest-internal-inl.h"
+
+namespace posix = ::testing::internal::posix;
+
+using testing::ContainsRegex;
+using testing::Matcher;
+using testing::Message;
+using testing::internal::DeathTest;
+using testing::internal::DeathTestFactory;
+using testing::internal::FilePath;
+using testing::internal::GetLastErrnoDescription;
+using testing::internal::GetUnitTestImpl;
+using testing::internal::InDeathTestChild;
+using testing::internal::ParseNaturalNumber;
+
+namespace testing {
+namespace internal {
+
+// A helper class whose objects replace the death test factory for a
+// single UnitTest object during their lifetimes.
+class ReplaceDeathTestFactory {
+ public:
+  explicit ReplaceDeathTestFactory(DeathTestFactory* new_factory)
+      : unit_test_impl_(GetUnitTestImpl()) {
+    old_factory_ = unit_test_impl_->death_test_factory_.release();
+    unit_test_impl_->death_test_factory_.reset(new_factory);
+  }
+
+  ~ReplaceDeathTestFactory() {
+    unit_test_impl_->death_test_factory_.release();
+    unit_test_impl_->death_test_factory_.reset(old_factory_);
+  }
+
+ private:
+  // Prevents copying ReplaceDeathTestFactory objects.
+  ReplaceDeathTestFactory(const ReplaceDeathTestFactory&);
+  void operator=(const ReplaceDeathTestFactory&);
+
+  UnitTestImpl* unit_test_impl_;
+  DeathTestFactory* old_factory_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+namespace {
+
+void DieWithMessage(const ::std::string& message) {
+  fprintf(stderr, "%s", message.c_str());
+  fflush(stderr);  // Make sure the text is printed before the process exits.
+
+  // We call _Exit() instead of exit(), as the former is a direct
+  // system call and thus safer in the presence of threads.  exit()
+  // will invoke user-defined exit-hooks, which may do dangerous
+  // things that conflict with death tests.
+  //
+  // Some compilers can recognize that _Exit() never returns and issue the
+  // 'unreachable code' warning for code following this function, unless
+  // fooled by a fake condition.
+  if (AlwaysTrue()) _Exit(1);
+}
+
+void DieInside(const ::std::string& function) {
+  DieWithMessage("death inside " + function + "().");
+}
+
+// Tests that death tests work.
+
+class TestForDeathTest : public testing::Test {
+ protected:
+  TestForDeathTest() : original_dir_(FilePath::GetCurrentDir()) {}
+
+  ~TestForDeathTest() override { posix::ChDir(original_dir_.c_str()); }
+
+  // A static member function that's expected to die.
+  static void StaticMemberFunction() { DieInside("StaticMemberFunction"); }
+
+  // A method of the test fixture that may die.
+  void MemberFunction() {
+    if (should_die_) DieInside("MemberFunction");
+  }
+
+  // True if and only if MemberFunction() should die.
+  bool should_die_;
+  const FilePath original_dir_;
+};
+
+// A class with a member function that may die.
+class MayDie {
+ public:
+  explicit MayDie(bool should_die) : should_die_(should_die) {}
+
+  // A member function that may die.
+  void MemberFunction() const {
+    if (should_die_) DieInside("MayDie::MemberFunction");
+  }
+
+ private:
+  // True if and only if MemberFunction() should die.
+  bool should_die_;
+};
+
+// A global function that's expected to die.
+void GlobalFunction() { DieInside("GlobalFunction"); }
+
+// A non-void function that's expected to die.
+int NonVoidFunction() {
+  DieInside("NonVoidFunction");
+  return 1;
+}
+
+// A unary function that may die.
+void DieIf(bool should_die) {
+  if (should_die) DieInside("DieIf");
+}
+
+// A binary function that may die.
+bool DieIfLessThan(int x, int y) {
+  if (x < y) {
+    DieInside("DieIfLessThan");
+  }
+  return true;
+}
+
+// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
+void DeathTestSubroutine() {
+  EXPECT_DEATH(GlobalFunction(), "death.*GlobalFunction");
+  ASSERT_DEATH(GlobalFunction(), "death.*GlobalFunction");
+}
+
+// Death in dbg, not opt.
+int DieInDebugElse12(int* sideeffect) {
+  if (sideeffect) *sideeffect = 12;
+
+#ifndef NDEBUG
+
+  DieInside("DieInDebugElse12");
+
+#endif  // NDEBUG
+
+  return 12;
+}
+
+#ifdef GTEST_OS_WINDOWS
+
+// Death in dbg due to Windows CRT assertion failure, not opt.
+int DieInCRTDebugElse12(int* sideeffect) {
+  if (sideeffect) *sideeffect = 12;
+
+  // Create an invalid fd by closing a valid one
+  int fdpipe[2];
+  EXPECT_EQ(_pipe(fdpipe, 256, O_BINARY), 0);
+  EXPECT_EQ(_close(fdpipe[0]), 0);
+  EXPECT_EQ(_close(fdpipe[1]), 0);
+
+  // _dup() should crash in debug mode
+  EXPECT_EQ(_dup(fdpipe[0]), -1);
+
+  return 12;
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_FUCHSIA)
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+  // On Windows, the process's exit code is the same as its exit status,
+  // so the predicate just compares the its input with its parameter.
+  EXPECT_TRUE(testing::ExitedWithCode(0)(0));
+  EXPECT_TRUE(testing::ExitedWithCode(1)(1));
+  EXPECT_TRUE(testing::ExitedWithCode(42)(42));
+  EXPECT_FALSE(testing::ExitedWithCode(0)(1));
+  EXPECT_FALSE(testing::ExitedWithCode(1)(0));
+}
+
+#else
+
+// Returns the exit status of a process that calls _Exit(2) with a
+// given exit code.  This is a helper function for the
+// ExitStatusPredicateTest test suite.
+static int NormalExitStatus(int exit_code) {
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    _Exit(exit_code);
+  }
+  int status;
+  waitpid(child_pid, &status, 0);
+  return status;
+}
+
+// Returns the exit status of a process that raises a given signal.
+// If the signal does not cause the process to die, then it returns
+// instead the exit status of a process that exits normally with exit
+// code 1.  This is a helper function for the ExitStatusPredicateTest
+// test suite.
+static int KilledExitStatus(int signum) {
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    raise(signum);
+    _Exit(1);
+  }
+  int status;
+  waitpid(child_pid, &status, 0);
+  return status;
+}
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+  const int status0 = NormalExitStatus(0);
+  const int status1 = NormalExitStatus(1);
+  const int status42 = NormalExitStatus(42);
+  const testing::ExitedWithCode pred0(0);
+  const testing::ExitedWithCode pred1(1);
+  const testing::ExitedWithCode pred42(42);
+  EXPECT_PRED1(pred0, status0);
+  EXPECT_PRED1(pred1, status1);
+  EXPECT_PRED1(pred42, status42);
+  EXPECT_FALSE(pred0(status1));
+  EXPECT_FALSE(pred42(status0));
+  EXPECT_FALSE(pred1(status42));
+}
+
+// Tests the KilledBySignal predicate.
+TEST(ExitStatusPredicateTest, KilledBySignal) {
+  const int status_segv = KilledExitStatus(SIGSEGV);
+  const int status_kill = KilledExitStatus(SIGKILL);
+  const testing::KilledBySignal pred_segv(SIGSEGV);
+  const testing::KilledBySignal pred_kill(SIGKILL);
+#if !(defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ <= 21)
+  EXPECT_PRED1(pred_segv, status_segv);
+#endif
+  EXPECT_PRED1(pred_kill, status_kill);
+  EXPECT_FALSE(pred_segv(status_kill));
+  EXPECT_FALSE(pred_kill(status_segv));
+}
+
+#endif  // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+
+// The following code intentionally tests a suboptimal syntax.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-else"
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+TEST_F(TestForDeathTest, SingleStatement) {
+  if (AlwaysFalse())
+    // This would fail if executed; this is a compilation test only
+    ASSERT_DEATH(return, "");
+
+  if (AlwaysTrue())
+    EXPECT_DEATH(_Exit(1), "");
+  else
+    // This empty "else" branch is meant to ensure that EXPECT_DEATH
+    // doesn't expand into an "if" statement without an "else"
+    ;
+
+  if (AlwaysFalse()) ASSERT_DEATH(return, "") << "did not die";
+
+  if (AlwaysFalse())
+    ;
+  else
+    EXPECT_DEATH(_Exit(1), "") << 1 << 2 << 3;
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+// Tests that death test macros expand to code which interacts well with switch
+// statements.
+TEST_F(TestForDeathTest, SwitchStatement) {
+  // Microsoft compiler usually complains about switch statements without
+  // case labels. We suppress that warning for this test.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
+
+  switch (0)
+  default:
+    ASSERT_DEATH(_Exit(1), "") << "exit in default switch handler";
+
+  switch (0)
+  case 0:
+    EXPECT_DEATH(_Exit(1), "") << "exit in switch case";
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+}
+
+// Tests that a static member function can be used in a "fast" style
+// death test.
+TEST_F(TestForDeathTest, StaticMemberFunctionFastStyle) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
+}
+
+// Tests that a method of the test fixture can be used in a "fast"
+// style death test.
+TEST_F(TestForDeathTest, MemberFunctionFastStyle) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  should_die_ = true;
+  EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
+}
+
+void ChangeToRootDir() { posix::ChDir(GTEST_PATH_SEP_); }
+
+// Tests that death tests work even if the current directory has been
+// changed.
+TEST_F(TestForDeathTest, FastDeathTestInChangedDir) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+
+  ChangeToRootDir();
+  EXPECT_EXIT(_Exit(1), testing::ExitedWithCode(1), "");
+
+  ChangeToRootDir();
+  ASSERT_DEATH(_Exit(1), "");
+}
+
+#ifdef GTEST_OS_LINUX
+void SigprofAction(int, siginfo_t*, void*) { /* no op */
+}
+
+// Sets SIGPROF action and ITIMER_PROF timer (interval: 1ms).
+void SetSigprofActionAndTimer() {
+  struct sigaction signal_action;
+  memset(&signal_action, 0, sizeof(signal_action));
+  sigemptyset(&signal_action.sa_mask);
+  signal_action.sa_sigaction = SigprofAction;
+  signal_action.sa_flags = SA_RESTART | SA_SIGINFO;
+  ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, nullptr));
+  // timer comes second, to avoid SIGPROF premature delivery, as suggested at
+  // https://www.gnu.org/software/libc/manual/html_node/Setting-an-Alarm.html
+  struct itimerval timer;
+  timer.it_interval.tv_sec = 0;
+  timer.it_interval.tv_usec = 1;
+  timer.it_value = timer.it_interval;
+  ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, nullptr));
+}
+
+// Disables ITIMER_PROF timer and ignores SIGPROF signal.
+void DisableSigprofActionAndTimer(struct sigaction* old_signal_action) {
+  struct itimerval timer;
+  timer.it_interval.tv_sec = 0;
+  timer.it_interval.tv_usec = 0;
+  timer.it_value = timer.it_interval;
+  ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, nullptr));
+  struct sigaction signal_action;
+  memset(&signal_action, 0, sizeof(signal_action));
+  sigemptyset(&signal_action.sa_mask);
+  signal_action.sa_handler = SIG_IGN;
+  ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, old_signal_action));
+}
+
+// Tests that death tests work when SIGPROF handler and timer are set.
+TEST_F(TestForDeathTest, FastSigprofActionSet) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  SetSigprofActionAndTimer();
+  EXPECT_DEATH(_Exit(1), "");
+  struct sigaction old_signal_action;
+  DisableSigprofActionAndTimer(&old_signal_action);
+  EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
+}
+
+TEST_F(TestForDeathTest, ThreadSafeSigprofActionSet) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  SetSigprofActionAndTimer();
+  EXPECT_DEATH(_Exit(1), "");
+  struct sigaction old_signal_action;
+  DisableSigprofActionAndTimer(&old_signal_action);
+  EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
+}
+#endif  // GTEST_OS_LINUX
+
+// Repeats a representative sample of death tests in the "threadsafe" style:
+
+TEST_F(TestForDeathTest, StaticMemberFunctionThreadsafeStyle) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
+}
+
+TEST_F(TestForDeathTest, MemberFunctionThreadsafeStyle) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  should_die_ = true;
+  EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
+}
+
+TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+
+  for (int i = 0; i < 3; ++i)
+    EXPECT_EXIT(_Exit(i), testing::ExitedWithCode(i), "") << ": i = " << i;
+}
+
+TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+
+  ChangeToRootDir();
+  EXPECT_EXIT(_Exit(1), testing::ExitedWithCode(1), "");
+
+  ChangeToRootDir();
+  ASSERT_DEATH(_Exit(1), "");
+}
+
+TEST_F(TestForDeathTest, MixedStyles) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  EXPECT_DEATH(_Exit(1), "");
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_DEATH(_Exit(1), "");
+}
+
+#if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
+
+bool pthread_flag;
+
+void SetPthreadFlag() { pthread_flag = true; }
+
+TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
+  if (!GTEST_FLAG_GET(death_test_use_fork)) {
+    GTEST_FLAG_SET(death_test_style, "threadsafe");
+    pthread_flag = false;
+    ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, nullptr, nullptr));
+    ASSERT_DEATH(_Exit(1), "");
+    ASSERT_FALSE(pthread_flag);
+  }
+}
+
+#endif  // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
+
+// Tests that a method of another class can be used in a death test.
+TEST_F(TestForDeathTest, MethodOfAnotherClass) {
+  const MayDie x(true);
+  ASSERT_DEATH(x.MemberFunction(), "MayDie\\:\\:MemberFunction");
+}
+
+// Tests that a global function can be used in a death test.
+TEST_F(TestForDeathTest, GlobalFunction) {
+  EXPECT_DEATH(GlobalFunction(), "GlobalFunction");
+}
+
+// Tests that any value convertible to an RE works as a second
+// argument to EXPECT_DEATH.
+TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
+  static const char regex_c_str[] = "GlobalFunction";
+  EXPECT_DEATH(GlobalFunction(), regex_c_str);
+
+  const testing::internal::RE regex(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex);
+
+  const ::std::string regex_std_str(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex_std_str);
+
+  // This one is tricky; a temporary pointer into another temporary.  Reference
+  // lifetime extension of the pointer is not sufficient.
+  EXPECT_DEATH(GlobalFunction(), ::std::string(regex_c_str).c_str());
+}
+
+// Tests that a non-void function can be used in a death test.
+TEST_F(TestForDeathTest, NonVoidFunction) {
+  ASSERT_DEATH(NonVoidFunction(), "NonVoidFunction");
+}
+
+// Tests that functions that take parameter(s) can be used in a death test.
+TEST_F(TestForDeathTest, FunctionWithParameter) {
+  EXPECT_DEATH(DieIf(true), "DieIf\\(\\)");
+  EXPECT_DEATH(DieIfLessThan(2, 3), "DieIfLessThan");
+}
+
+// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
+TEST_F(TestForDeathTest, OutsideFixture) { DeathTestSubroutine(); }
+
+// Tests that death tests can be done inside a loop.
+TEST_F(TestForDeathTest, InsideLoop) {
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH(DieIfLessThan(-1, i), "DieIfLessThan") << "where i == " << i;
+  }
+}
+
+// Tests that a compound statement can be used in a death test.
+TEST_F(TestForDeathTest, CompoundStatement) {
+  EXPECT_DEATH(
+      {  // NOLINT
+        const int x = 2;
+        const int y = x + 1;
+        DieIfLessThan(x, y);
+      },
+      "DieIfLessThan");
+}
+
+// Tests that code that doesn't die causes a death test to fail.
+TEST_F(TestForDeathTest, DoesNotDie) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"), "failed to die");
+}
+
+// Tests that a death test fails when the error message isn't expected.
+TEST_F(TestForDeathTest, ErrorMessageMismatch) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_DEATH(DieIf(true), "DieIfLessThan")
+            << "End of death test message.";
+      },
+      "died but not with expected error");
+}
+
+// On exit, *aborted will be true if and only if the EXPECT_DEATH()
+// statement aborted the function.
+void ExpectDeathTestHelper(bool* aborted) {
+  *aborted = true;
+  EXPECT_DEATH(DieIf(false), "DieIf");  // This assertion should fail.
+  *aborted = false;
+}
+
+// Tests that EXPECT_DEATH doesn't abort the test on failure.
+TEST_F(TestForDeathTest, EXPECT_DEATH) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted), "failed to die");
+  EXPECT_FALSE(aborted);
+}
+
+// Tests that ASSERT_DEATH does abort the test on failure.
+TEST_F(TestForDeathTest, ASSERT_DEATH) {
+  static bool aborted;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        aborted = true;
+        ASSERT_DEATH(DieIf(false), "DieIf");  // This assertion should fail.
+        aborted = false;
+      },
+      "failed to die");
+  EXPECT_TRUE(aborted);
+}
+
+// Tests that EXPECT_DEATH evaluates the arguments exactly once.
+TEST_F(TestForDeathTest, SingleEvaluation) {
+  int x = 3;
+  EXPECT_DEATH(DieIf((++x) == 4), "DieIf");
+
+  const char* regex = "DieIf";
+  const char* regex_save = regex;
+  EXPECT_DEATH(DieIfLessThan(3, 4), regex++);
+  EXPECT_EQ(regex_save + 1, regex);
+}
+
+// Tests that run-away death tests are reported as failures.
+TEST_F(TestForDeathTest, RunawayIsFailure) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(static_cast<void>(0), "Foo"),
+                          "failed to die.");
+}
+
+// Tests that death tests report executing 'return' in the statement as
+// failure.
+TEST_F(TestForDeathTest, ReturnIsFailure) {
+  EXPECT_FATAL_FAILURE(ASSERT_DEATH(return, "Bar"),
+                       "illegal return in test statement.");
+}
+
+// Tests that EXPECT_DEBUG_DEATH works as expected, that is, you can stream a
+// message to it, and in debug mode it:
+// 1. Asserts on death.
+// 2. Has no side effect.
+//
+// And in opt mode, it:
+// 1.  Has side effects but does not assert.
+TEST_F(TestForDeathTest, TestExpectDebugDeath) {
+  int sideeffect = 0;
+
+  // Put the regex in a local variable to make sure we don't get an "unused"
+  // warning in opt mode.
+  const char* regex = "death.*DieInDebugElse12";
+
+  EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), regex)
+      << "Must accept a streamed message";
+
+#ifdef NDEBUG
+
+  // Checks that the assignment occurs in opt mode (sideeffect).
+  EXPECT_EQ(12, sideeffect);
+
+#else
+
+  // Checks that the assignment does not occur in dbg mode (no sideeffect).
+  EXPECT_EQ(0, sideeffect);
+
+#endif
+}
+
+#ifdef GTEST_OS_WINDOWS
+
+// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/crtsetreportmode
+// In debug mode, the calls to _CrtSetReportMode and _CrtSetReportFile enable
+// the dumping of assertions to stderr. Tests that EXPECT_DEATH works as
+// expected when in CRT debug mode (compiled with /MTd or /MDd, which defines
+// _DEBUG) the Windows CRT crashes the process with an assertion failure.
+// 1. Asserts on death.
+// 2. Has no side effect (doesn't pop up a window or wait for user input).
+#ifdef _DEBUG
+TEST_F(TestForDeathTest, CRTDebugDeath) {
+  EXPECT_DEATH(DieInCRTDebugElse12(nullptr), "dup.* : Assertion failed")
+      << "Must accept a streamed message";
+}
+#endif  // _DEBUG
+
+#endif  // GTEST_OS_WINDOWS
+
+// Tests that ASSERT_DEBUG_DEATH works as expected, that is, you can stream a
+// message to it, and in debug mode it:
+// 1. Asserts on death.
+// 2. Has no side effect.
+//
+// And in opt mode, it:
+// 1.  Has side effects but does not assert.
+TEST_F(TestForDeathTest, TestAssertDebugDeath) {
+  int sideeffect = 0;
+
+  ASSERT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12")
+      << "Must accept a streamed message";
+
+#ifdef NDEBUG
+
+  // Checks that the assignment occurs in opt mode (sideeffect).
+  EXPECT_EQ(12, sideeffect);
+
+#else
+
+  // Checks that the assignment does not occur in dbg mode (no sideeffect).
+  EXPECT_EQ(0, sideeffect);
+
+#endif
+}
+
+#ifndef NDEBUG
+
+void ExpectDebugDeathHelper(bool* aborted) {
+  *aborted = true;
+  EXPECT_DEBUG_DEATH(return, "") << "This is expected to fail.";
+  *aborted = false;
+}
+
+#ifdef GTEST_OS_WINDOWS
+TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) {
+  printf(
+      "This test should be considered failing if it shows "
+      "any pop-up dialogs.\n");
+  fflush(stdout);
+
+  EXPECT_DEATH(
+      {
+        GTEST_FLAG_SET(catch_exceptions, false);
+        abort();
+      },
+      "");
+}
+#endif  // GTEST_OS_WINDOWS
+
+// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
+// the function.
+TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(ExpectDebugDeathHelper(&aborted), "");
+  EXPECT_FALSE(aborted);
+}
+
+void AssertDebugDeathHelper(bool* aborted) {
+  *aborted = true;
+  GTEST_LOG_(INFO) << "Before ASSERT_DEBUG_DEATH";
+  ASSERT_DEBUG_DEATH(GTEST_LOG_(INFO) << "In ASSERT_DEBUG_DEATH"; return, "")
+      << "This is expected to fail.";
+  GTEST_LOG_(INFO) << "After ASSERT_DEBUG_DEATH";
+  *aborted = false;
+}
+
+// Tests that ASSERT_DEBUG_DEATH in debug mode aborts the function on
+// failure.
+TEST_F(TestForDeathTest, AssertDebugDeathAborts) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts2) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts3) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts4) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts5) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts6) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts7) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts8) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts9) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts10) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+#endif  // _NDEBUG
+
+// Tests the *_EXIT family of macros, using a variety of predicates.
+static void TestExitMacros() {
+  EXPECT_EXIT(_Exit(1), testing::ExitedWithCode(1), "");
+  ASSERT_EXIT(_Exit(42), testing::ExitedWithCode(42), "");
+
+#ifdef GTEST_OS_WINDOWS
+
+  // Of all signals effects on the process exit code, only those of SIGABRT
+  // are documented on Windows.
+  // See https://msdn.microsoft.com/en-us/query-bi/m/dwwzkt4c.
+  EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "") << "b_ar";
+
+#elif !defined(GTEST_OS_FUCHSIA)
+
+  // Fuchsia has no unix signals.
+  EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
+  ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
+
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_EXIT(_Exit(0), testing::KilledBySignal(SIGSEGV), "")
+            << "This failure is expected, too.";
+      },
+      "This failure is expected, too.");
+
+#endif  // GTEST_OS_WINDOWS
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
+            << "This failure is expected.";
+      },
+      "This failure is expected.");
+}
+
+TEST_F(TestForDeathTest, ExitMacros) { TestExitMacros(); }
+
+TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
+  GTEST_FLAG_SET(death_test_use_fork, true);
+  TestExitMacros();
+}
+
+TEST_F(TestForDeathTest, InvalidStyle) {
+  GTEST_FLAG_SET(death_test_style, "rococo");
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_DEATH(_Exit(0), "") << "This failure is expected.";
+      },
+      "This failure is expected.");
+}
+
+TEST_F(TestForDeathTest, DeathTestFailedOutput) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("death\n"), "expected message"),
+      "Actual msg:\n"
+      "[  DEATH   ] death\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestUnexpectedReturnOutput) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(
+                              {
+                                fprintf(stderr, "returning\n");
+                                fflush(stderr);
+                                return;
+                              },
+                              ""),
+                          "    Result: illegal return in test statement.\n"
+                          " Error msg:\n"
+                          "[  DEATH   ] returning\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestBadExitCodeOutput) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_EXIT(DieWithMessage("exiting with rc 1\n"),
+                  testing::ExitedWithCode(3), "expected message"),
+      "    Result: died but not with expected exit code:\n"
+      "            Exited with exit status 1\n"
+      "Actual msg:\n"
+      "[  DEATH   ] exiting with rc 1\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestMultiLineMatchFail) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
+                   "line 1\nxyz\nline 3\n"),
+      "Actual msg:\n"
+      "[  DEATH   ] line 1\n"
+      "[  DEATH   ] line 2\n"
+      "[  DEATH   ] line 3\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestMultiLineMatchPass) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
+               "line 1\nline 2\nline 3\n");
+}
+
+// A DeathTestFactory that returns MockDeathTests.
+class MockDeathTestFactory : public DeathTestFactory {
+ public:
+  MockDeathTestFactory();
+  bool Create(const char* statement,
+              testing::Matcher<const std::string&> matcher, const char* file,
+              int line, DeathTest** test) override;
+
+  // Sets the parameters for subsequent calls to Create.
+  void SetParameters(bool create, DeathTest::TestRole role, int status,
+                     bool passed);
+
+  // Accessors.
+  int AssumeRoleCalls() const { return assume_role_calls_; }
+  int WaitCalls() const { return wait_calls_; }
+  size_t PassedCalls() const { return passed_args_.size(); }
+  bool PassedArgument(int n) const {
+    return passed_args_[static_cast<size_t>(n)];
+  }
+  size_t AbortCalls() const { return abort_args_.size(); }
+  DeathTest::AbortReason AbortArgument(int n) const {
+    return abort_args_[static_cast<size_t>(n)];
+  }
+  bool TestDeleted() const { return test_deleted_; }
+
+ private:
+  friend class MockDeathTest;
+  // If true, Create will return a MockDeathTest; otherwise it returns
+  // NULL.
+  bool create_;
+  // The value a MockDeathTest will return from its AssumeRole method.
+  DeathTest::TestRole role_;
+  // The value a MockDeathTest will return from its Wait method.
+  int status_;
+  // The value a MockDeathTest will return from its Passed method.
+  bool passed_;
+
+  // Number of times AssumeRole was called.
+  int assume_role_calls_;
+  // Number of times Wait was called.
+  int wait_calls_;
+  // The arguments to the calls to Passed since the last call to
+  // SetParameters.
+  std::vector<bool> passed_args_;
+  // The arguments to the calls to Abort since the last call to
+  // SetParameters.
+  std::vector<DeathTest::AbortReason> abort_args_;
+  // True if the last MockDeathTest returned by Create has been
+  // deleted.
+  bool test_deleted_;
+};
+
+// A DeathTest implementation useful in testing.  It returns values set
+// at its creation from its various inherited DeathTest methods, and
+// reports calls to those methods to its parent MockDeathTestFactory
+// object.
+class MockDeathTest : public DeathTest {
+ public:
+  MockDeathTest(MockDeathTestFactory* parent, TestRole role, int status,
+                bool passed)
+      : parent_(parent), role_(role), status_(status), passed_(passed) {}
+  ~MockDeathTest() override { parent_->test_deleted_ = true; }
+  TestRole AssumeRole() override {
+    ++parent_->assume_role_calls_;
+    return role_;
+  }
+  int Wait() override {
+    ++parent_->wait_calls_;
+    return status_;
+  }
+  bool Passed(bool exit_status_ok) override {
+    parent_->passed_args_.push_back(exit_status_ok);
+    return passed_;
+  }
+  void Abort(AbortReason reason) override {
+    parent_->abort_args_.push_back(reason);
+  }
+
+ private:
+  MockDeathTestFactory* const parent_;
+  const TestRole role_;
+  const int status_;
+  const bool passed_;
+};
+
+// MockDeathTestFactory constructor.
+MockDeathTestFactory::MockDeathTestFactory()
+    : create_(true),
+      role_(DeathTest::OVERSEE_TEST),
+      status_(0),
+      passed_(true),
+      assume_role_calls_(0),
+      wait_calls_(0),
+      passed_args_(),
+      abort_args_() {}
+
+// Sets the parameters for subsequent calls to Create.
+void MockDeathTestFactory::SetParameters(bool create, DeathTest::TestRole role,
+                                         int status, bool passed) {
+  create_ = create;
+  role_ = role;
+  status_ = status;
+  passed_ = passed;
+
+  assume_role_calls_ = 0;
+  wait_calls_ = 0;
+  passed_args_.clear();
+  abort_args_.clear();
+}
+
+// Sets test to NULL (if create_ is false) or to the address of a new
+// MockDeathTest object with parameters taken from the last call
+// to SetParameters (if create_ is true).  Always returns true.
+bool MockDeathTestFactory::Create(
+    const char* /*statement*/, testing::Matcher<const std::string&> /*matcher*/,
+    const char* /*file*/, int /*line*/, DeathTest** test) {
+  test_deleted_ = false;
+  if (create_) {
+    *test = new MockDeathTest(this, role_, status_, passed_);
+  } else {
+    *test = nullptr;
+  }
+  return true;
+}
+
+// A test fixture for testing the logic of the GTEST_DEATH_TEST_ macro.
+// It installs a MockDeathTestFactory that is used for the duration
+// of the test case.
+class MacroLogicDeathTest : public testing::Test {
+ protected:
+  static testing::internal::ReplaceDeathTestFactory* replacer_;
+  static MockDeathTestFactory* factory_;
+
+  static void SetUpTestSuite() {
+    factory_ = new MockDeathTestFactory;
+    replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_);
+  }
+
+  static void TearDownTestSuite() {
+    delete replacer_;
+    replacer_ = nullptr;
+    delete factory_;
+    factory_ = nullptr;
+  }
+
+  // Runs a death test that breaks the rules by returning.  Such a death
+  // test cannot be run directly from a test routine that uses a
+  // MockDeathTest, or the remainder of the routine will not be executed.
+  static void RunReturningDeathTest(bool* flag) {
+    ASSERT_DEATH(
+        {  // NOLINT
+          *flag = true;
+          return;
+        },
+        "");
+  }
+};
+
+testing::internal::ReplaceDeathTestFactory* MacroLogicDeathTest::replacer_ =
+    nullptr;
+MockDeathTestFactory* MacroLogicDeathTest::factory_ = nullptr;
+
+// Test that nothing happens when the factory doesn't return a DeathTest:
+TEST_F(MacroLogicDeathTest, NothingHappens) {
+  bool flag = false;
+  factory_->SetParameters(false, DeathTest::OVERSEE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(0, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0U, factory_->PassedCalls());
+  EXPECT_EQ(0U, factory_->AbortCalls());
+  EXPECT_FALSE(factory_->TestDeleted());
+}
+
+// Test that the parent process doesn't run the death test code,
+// and that the Passed method returns false when the (simulated)
+// child process exits with status 0:
+TEST_F(MacroLogicDeathTest, ChildExitsSuccessfully) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(1, factory_->WaitCalls());
+  ASSERT_EQ(1U, factory_->PassedCalls());
+  EXPECT_FALSE(factory_->PassedArgument(0));
+  EXPECT_EQ(0U, factory_->AbortCalls());
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the Passed method was given the argument "true" when
+// the (simulated) child process exits with status 1:
+TEST_F(MacroLogicDeathTest, ChildExitsUnsuccessfully) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 1, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(1, factory_->WaitCalls());
+  ASSERT_EQ(1U, factory_->PassedCalls());
+  EXPECT_TRUE(factory_->PassedArgument(0));
+  EXPECT_EQ(0U, factory_->AbortCalls());
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the (simulated) child process executes the death test
+// code, and is aborted with the correct AbortReason if it
+// executes a return statement.
+TEST_F(MacroLogicDeathTest, ChildPerformsReturn) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
+  RunReturningDeathTest(&flag);
+  EXPECT_TRUE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0U, factory_->PassedCalls());
+  EXPECT_EQ(1U, factory_->AbortCalls());
+  EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
+            factory_->AbortArgument(0));
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the (simulated) child process is aborted with the
+// correct AbortReason if it does not die.
+TEST_F(MacroLogicDeathTest, ChildDoesNotDie) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_TRUE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0U, factory_->PassedCalls());
+  // This time there are two calls to Abort: one since the test didn't
+  // die, and another from the ReturnSentinel when it's destroyed.  The
+  // sentinel normally isn't destroyed if a test doesn't die, since
+  // _Exit(2) is called in that case by ForkingDeathTest, but not by
+  // our MockDeathTest.
+  ASSERT_EQ(2U, factory_->AbortCalls());
+  EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE, factory_->AbortArgument(0));
+  EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
+            factory_->AbortArgument(1));
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that a successful death test does not register a successful
+// test part.
+TEST(SuccessRegistrationDeathTest, NoSuccessPart) {
+  EXPECT_DEATH(_Exit(1), "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+TEST(StreamingAssertionsDeathTest, DeathTest) {
+  EXPECT_DEATH(_Exit(1), "") << "unexpected failure";
+  ASSERT_DEATH(_Exit(1), "") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_DEATH(_Exit(0), "") << "expected failure";
+      },
+      "expected failure");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_DEATH(_Exit(0), "") << "expected failure";
+      },
+      "expected failure");
+}
+
+// Tests that GetLastErrnoDescription returns an empty string when the
+// last error is 0 and non-empty string when it is non-zero.
+TEST(GetLastErrnoDescription, GetLastErrnoDescriptionWorks) {
+  errno = ENOENT;
+  EXPECT_STRNE("", GetLastErrnoDescription().c_str());
+  errno = 0;
+  EXPECT_STREQ("", GetLastErrnoDescription().c_str());
+}
+
+#ifdef GTEST_OS_WINDOWS
+TEST(AutoHandleTest, AutoHandleWorks) {
+  HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+  ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+
+  // Tests that the AutoHandle is correctly initialized with a handle.
+  testing::internal::AutoHandle auto_handle(handle);
+  EXPECT_EQ(handle, auto_handle.Get());
+
+  // Tests that Reset assigns INVALID_HANDLE_VALUE.
+  // Note that this cannot verify whether the original handle is closed.
+  auto_handle.Reset();
+  EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get());
+
+  // Tests that Reset assigns the new handle.
+  // Note that this cannot verify whether the original handle is closed.
+  handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+  ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+  auto_handle.Reset(handle);
+  EXPECT_EQ(handle, auto_handle.Get());
+
+  // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default.
+  testing::internal::AutoHandle auto_handle2;
+  EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get());
+}
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef GTEST_OS_WINDOWS
+typedef unsigned __int64 BiggestParsable;
+typedef signed __int64 BiggestSignedParsable;
+#else
+typedef unsigned long long BiggestParsable;
+typedef signed long long BiggestSignedParsable;
+#endif  // GTEST_OS_WINDOWS
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the
+// max() macro defined by <windows.h>.
+const BiggestParsable kBiggestParsableMax = ULLONG_MAX;
+const BiggestSignedParsable kBiggestSignedParsableMax = LLONG_MAX;
+
+TEST(ParseNaturalNumberTest, RejectsInvalidFormat) {
+  BiggestParsable result = 0;
+
+  // Rejects non-numbers.
+  EXPECT_FALSE(ParseNaturalNumber("non-number string", &result));
+
+  // Rejects numbers with whitespace prefix.
+  EXPECT_FALSE(ParseNaturalNumber(" 123", &result));
+
+  // Rejects negative numbers.
+  EXPECT_FALSE(ParseNaturalNumber("-123", &result));
+
+  // Rejects numbers starting with a plus sign.
+  EXPECT_FALSE(ParseNaturalNumber("+123", &result));
+  errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) {
+  BiggestParsable result = 0;
+
+  EXPECT_FALSE(ParseNaturalNumber("99999999999999999999999", &result));
+
+  signed char char_result = 0;
+  EXPECT_FALSE(ParseNaturalNumber("200", &char_result));
+  errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, AcceptsValidNumbers) {
+  BiggestParsable result = 0;
+
+  result = 0;
+  ASSERT_TRUE(ParseNaturalNumber("123", &result));
+  EXPECT_EQ(123U, result);
+
+  // Check 0 as an edge case.
+  result = 1;
+  ASSERT_TRUE(ParseNaturalNumber("0", &result));
+  EXPECT_EQ(0U, result);
+
+  result = 1;
+  ASSERT_TRUE(ParseNaturalNumber("00000", &result));
+  EXPECT_EQ(0U, result);
+}
+
+TEST(ParseNaturalNumberTest, AcceptsTypeLimits) {
+  Message msg;
+  msg << kBiggestParsableMax;
+
+  BiggestParsable result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result));
+  EXPECT_EQ(kBiggestParsableMax, result);
+
+  Message msg2;
+  msg2 << kBiggestSignedParsableMax;
+
+  BiggestSignedParsable signed_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result));
+  EXPECT_EQ(kBiggestSignedParsableMax, signed_result);
+
+  Message msg3;
+  msg3 << INT_MAX;
+
+  int int_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result));
+  EXPECT_EQ(INT_MAX, int_result);
+
+  Message msg4;
+  msg4 << UINT_MAX;
+
+  unsigned int uint_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result));
+  EXPECT_EQ(UINT_MAX, uint_result);
+}
+
+TEST(ParseNaturalNumberTest, WorksForShorterIntegers) {
+  short short_result = 0;
+  ASSERT_TRUE(ParseNaturalNumber("123", &short_result));
+  EXPECT_EQ(123, short_result);
+
+  signed char char_result = 0;
+  ASSERT_TRUE(ParseNaturalNumber("123", &char_result));
+  EXPECT_EQ(123, char_result);
+}
+
+#ifdef GTEST_OS_WINDOWS
+TEST(EnvironmentTest, HandleFitsIntoSizeT) {
+  ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t));
+}
+#endif  // GTEST_OS_WINDOWS
+
+// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
+// failures when death tests are available on the system.
+TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) {
+  EXPECT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestExpectMacro"),
+                            "death inside CondDeathTestExpectMacro");
+  ASSERT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestAssertMacro"),
+                            "death inside CondDeathTestAssertMacro");
+
+  // Empty statement will not crash, which must trigger a failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH_IF_SUPPORTED(;, ""), "");
+  EXPECT_FATAL_FAILURE(ASSERT_DEATH_IF_SUPPORTED(;, ""), "");
+}
+
+TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInFastStyle) {
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_FALSE(InDeathTestChild());
+  EXPECT_DEATH(
+      {
+        fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
+        fflush(stderr);
+        _Exit(1);
+      },
+      "Inside");
+}
+
+TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInThreadSafeStyle) {
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  EXPECT_FALSE(InDeathTestChild());
+  EXPECT_DEATH(
+      {
+        fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
+        fflush(stderr);
+        _Exit(1);
+      },
+      "Inside");
+}
+
+void DieWithMessage(const char* message) {
+  fputs(message, stderr);
+  fflush(stderr);  // Make sure the text is printed before the process exits.
+  _Exit(1);
+}
+
+TEST(MatcherDeathTest, DoesNotBreakBareRegexMatching) {
+  // googletest tests this, of course; here we ensure that including googlemock
+  // has not broken it.
+#ifdef GTEST_USES_POSIX_RE
+  EXPECT_DEATH(DieWithMessage("O, I die, Horatio."), "I d[aeiou]e");
+#else
+  EXPECT_DEATH(DieWithMessage("O, I die, Horatio."), "I di?e");
+#endif
+}
+
+TEST(MatcherDeathTest, MonomorphicMatcherMatches) {
+  EXPECT_DEATH(DieWithMessage("Behind O, I am slain!"),
+               Matcher<const std::string&>(ContainsRegex("I am slain")));
+}
+
+TEST(MatcherDeathTest, MonomorphicMatcherDoesNotMatch) {
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(
+          DieWithMessage("Behind O, I am slain!"),
+          Matcher<const std::string&>(ContainsRegex("Ow, I am slain"))),
+      "Expected: contains regular expression \"Ow, I am slain\"");
+}
+
+TEST(MatcherDeathTest, PolymorphicMatcherMatches) {
+  EXPECT_DEATH(DieWithMessage("The rest is silence."),
+               ContainsRegex("rest is silence"));
+}
+
+TEST(MatcherDeathTest, PolymorphicMatcherDoesNotMatch) {
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("The rest is silence."),
+                   ContainsRegex("rest is science")),
+      "Expected: contains regular expression \"rest is science\"");
+}
+
+}  // namespace
+
+#else  // !GTEST_HAS_DEATH_TEST follows
+
+namespace {
+
+using testing::internal::CaptureStderr;
+using testing::internal::GetCapturedStderr;
+
+// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still
+// defined but do not trigger failures when death tests are not available on
+// the system.
+TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) {
+  // Empty statement will not crash, but that should not trigger a failure
+  // when death tests are not supported.
+  CaptureStderr();
+  EXPECT_DEATH_IF_SUPPORTED(;, "");
+  std::string output = GetCapturedStderr();
+  ASSERT_TRUE(NULL != strstr(output.c_str(),
+                             "Death tests are not supported on this platform"));
+  ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+  // The streamed message should not be printed as there is no test failure.
+  CaptureStderr();
+  EXPECT_DEATH_IF_SUPPORTED(;, "") << "streamed message";
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+
+  CaptureStderr();
+  ASSERT_DEATH_IF_SUPPORTED(;, "");  // NOLINT
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL != strstr(output.c_str(),
+                             "Death tests are not supported on this platform"));
+  ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+  CaptureStderr();
+  ASSERT_DEATH_IF_SUPPORTED(;, "") << "streamed message";  // NOLINT
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+}
+
+void FuncWithAssert(int* n) {
+  ASSERT_DEATH_IF_SUPPORTED(return;, "");
+  (*n)++;
+}
+
+// Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current
+// function (as ASSERT_DEATH does) if death tests are not supported.
+TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
+  int n = 0;
+  FuncWithAssert(&n);
+  EXPECT_EQ(1, n);
+}
+
+}  // namespace
+
+#endif  // !GTEST_HAS_DEATH_TEST
+
+namespace {
+
+// The following code intentionally tests a suboptimal syntax.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-else"
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+//
+// The syntax should work whether death tests are available or not.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) {
+  if (AlwaysFalse())
+    // This would fail if executed; this is a compilation test only
+    ASSERT_DEATH_IF_SUPPORTED(return, "");
+
+  if (AlwaysTrue())
+    EXPECT_DEATH_IF_SUPPORTED(_Exit(1), "");
+  else
+    // This empty "else" branch is meant to ensure that EXPECT_DEATH
+    // doesn't expand into an "if" statement without an "else"
+    ;  // NOLINT
+
+  if (AlwaysFalse()) ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    EXPECT_DEATH_IF_SUPPORTED(_Exit(1), "") << 1 << 2 << 3;
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+// Tests that conditional death test macros expand to code which interacts
+// well with switch statements.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
+  // Microsoft compiler usually complains about switch statements without
+  // case labels. We suppress that warning for this test.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
+
+  switch (0)
+  default:
+    ASSERT_DEATH_IF_SUPPORTED(_Exit(1), "") << "exit in default switch handler";
+
+  switch (0)
+  case 0:
+    EXPECT_DEATH_IF_SUPPORTED(_Exit(1), "") << "exit in switch case";
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+}
+
+// Tests that a test case whose name ends with "DeathTest" works fine
+// on Windows.
+TEST(NotADeathTest, Test) { SUCCEED(); }
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/test/googletest-death-test_ex_test.cc b/3rd-party/googletest/googletest/test/googletest-death-test_ex_test.cc
new file mode 100644
index 0000000..34d5501
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-death-test_ex_test.cc
@@ -0,0 +1,91 @@
+// Copyright 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests that verify interaction of exceptions and death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest.h"
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+#if GTEST_HAS_SEH
+#include <windows.h>  // For RaiseException().
+#endif
+
+#include "gtest/gtest-spi.h"
+
+#if GTEST_HAS_EXCEPTIONS
+
+#include <exception>  // For std::exception.
+
+// Tests that death tests report thrown exceptions as failures and that the
+// exceptions do not escape death test macros.
+TEST(CxxExceptionDeathTest, ExceptionIsFailure) {
+  try {
+    EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw 1, ""), "threw an exception");
+  } catch (...) {  // NOLINT
+    FAIL() << "An exception escaped a death test macro invocation "
+           << "with catch_exceptions "
+           << (GTEST_FLAG_GET(catch_exceptions) ? "enabled" : "disabled");
+  }
+}
+
+class TestException : public std::exception {
+ public:
+  const char* what() const noexcept override { return "exceptional message"; }
+};
+
+TEST(CxxExceptionDeathTest, PrintsMessageForStdExceptions) {
+  // Verifies that the exception message is quoted in the failure text.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
+                          "exceptional message");
+  // Verifies that the location is mentioned in the failure text.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""), __FILE__);
+}
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if GTEST_HAS_SEH
+// Tests that enabling interception of SEH exceptions with the
+// catch_exceptions flag does not interfere with SEH exceptions being
+// treated as death by death tests.
+TEST(SehExceptionDeasTest, CatchExceptionsDoesNotInterfere) {
+  EXPECT_DEATH(RaiseException(42, 0x0, 0, NULL), "")
+      << "with catch_exceptions "
+      << (GTEST_FLAG_GET(catch_exceptions) ? "enabled" : "disabled");
+}
+#endif
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  GTEST_FLAG_SET(catch_exceptions, GTEST_ENABLE_CATCH_EXCEPTIONS_ != 0);
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-env-var-test.py b/3rd-party/googletest/googletest/test/googletest-env-var-test.py
new file mode 100755
index 0000000..24d8edb
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-env-var-test.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test correctly parses environment variables."""
+
+import os
+from googletest.test import gtest_test_utils
+
+
+IS_WINDOWS = os.name == 'nt'
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+
+COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-env-var-test_')
+
+environ = os.environ.copy()
+
+
+def AssertEq(expected, actual):
+  if expected != actual:
+    print('Expected: %s' % (expected,))
+    print('  Actual: %s' % (actual,))
+    raise AssertionError
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def GetFlag(flag):
+  """Runs googletest-env-var-test_ and returns its output."""
+
+  args = [COMMAND]
+  if flag is not None:
+    args += [flag]
+  return gtest_test_utils.Subprocess(args, env=environ).output
+
+
+def TestFlag(flag, test_val, default_val):
+  """Verifies that the given flag is affected by the corresponding env var."""
+
+  env_var = 'GTEST_' + flag.upper()
+  SetEnvVar(env_var, test_val)
+  AssertEq(test_val, GetFlag(flag))
+  SetEnvVar(env_var, None)
+  AssertEq(default_val, GetFlag(flag))
+
+
+class GTestEnvVarTest(gtest_test_utils.TestCase):
+
+  def testEnvVarAffectsFlag(self):
+    """Tests that environment variable should affect the corresponding flag."""
+
+    TestFlag('break_on_failure', '1', '0')
+    TestFlag('color', 'yes', 'auto')
+    SetEnvVar('TESTBRIDGE_TEST_RUNNER_FAIL_FAST', None)  # For 'fail_fast' test
+    TestFlag('fail_fast', '1', '0')
+    TestFlag('filter', 'FooTest.Bar', '*')
+    SetEnvVar('XML_OUTPUT_FILE', None)  # For 'output' test
+    TestFlag('output', 'xml:tmp/foo.xml', '')
+    TestFlag('brief', '1', '0')
+    TestFlag('print_time', '0', '1')
+    TestFlag('repeat', '999', '1')
+    TestFlag('throw_on_failure', '1', '0')
+    TestFlag('death_test_style', 'threadsafe', 'fast')
+    TestFlag('catch_exceptions', '0', '1')
+
+    if IS_LINUX:
+      TestFlag('death_test_use_fork', '1', '0')
+      TestFlag('stack_trace_depth', '0', '100')
+
+  def testXmlOutputFile(self):
+    """Tests that $XML_OUTPUT_FILE affects the output flag."""
+
+    SetEnvVar('GTEST_OUTPUT', None)
+    SetEnvVar('XML_OUTPUT_FILE', 'tmp/bar.xml')
+    AssertEq('xml:tmp/bar.xml', GetFlag('output'))
+
+  def testXmlOutputFileOverride(self):
+    """Tests that $XML_OUTPUT_FILE is overridden by $GTEST_OUTPUT."""
+
+    SetEnvVar('GTEST_OUTPUT', 'xml:tmp/foo.xml')
+    SetEnvVar('XML_OUTPUT_FILE', 'tmp/bar.xml')
+    AssertEq('xml:tmp/foo.xml', GetFlag('output'))
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-env-var-test_.cc b/3rd-party/googletest/googletest/test/googletest-env-var-test_.cc
new file mode 100644
index 0000000..3653375
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-env-var-test_.cc
@@ -0,0 +1,130 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A helper program for testing that Google Test parses the environment
+// variables correctly.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+using ::std::cout;
+
+namespace testing {
+
+// The purpose of this is to make the test more realistic by ensuring
+// that the UnitTest singleton is created before main() is entered.
+// We don't actual run the TEST itself.
+TEST(GTestEnvVarTest, Dummy) {}
+
+void PrintFlag(const char* flag) {
+  if (strcmp(flag, "break_on_failure") == 0) {
+    cout << GTEST_FLAG_GET(break_on_failure);
+    return;
+  }
+
+  if (strcmp(flag, "catch_exceptions") == 0) {
+    cout << GTEST_FLAG_GET(catch_exceptions);
+    return;
+  }
+
+  if (strcmp(flag, "color") == 0) {
+    cout << GTEST_FLAG_GET(color);
+    return;
+  }
+
+  if (strcmp(flag, "death_test_style") == 0) {
+    cout << GTEST_FLAG_GET(death_test_style);
+    return;
+  }
+
+  if (strcmp(flag, "death_test_use_fork") == 0) {
+    cout << GTEST_FLAG_GET(death_test_use_fork);
+    return;
+  }
+
+  if (strcmp(flag, "fail_fast") == 0) {
+    cout << GTEST_FLAG_GET(fail_fast);
+    return;
+  }
+
+  if (strcmp(flag, "filter") == 0) {
+    cout << GTEST_FLAG_GET(filter);
+    return;
+  }
+
+  if (strcmp(flag, "output") == 0) {
+    cout << GTEST_FLAG_GET(output);
+    return;
+  }
+
+  if (strcmp(flag, "brief") == 0) {
+    cout << GTEST_FLAG_GET(brief);
+    return;
+  }
+
+  if (strcmp(flag, "print_time") == 0) {
+    cout << GTEST_FLAG_GET(print_time);
+    return;
+  }
+
+  if (strcmp(flag, "repeat") == 0) {
+    cout << GTEST_FLAG_GET(repeat);
+    return;
+  }
+
+  if (strcmp(flag, "stack_trace_depth") == 0) {
+    cout << GTEST_FLAG_GET(stack_trace_depth);
+    return;
+  }
+
+  if (strcmp(flag, "throw_on_failure") == 0) {
+    cout << GTEST_FLAG_GET(throw_on_failure);
+    return;
+  }
+
+  cout << "Invalid flag name " << flag
+       << ".  Valid names are break_on_failure, color, filter, etc.\n";
+  exit(1);
+}
+
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  if (argc != 2) {
+    cout << "Usage: googletest-env-var-test_ NAME_OF_FLAG\n";
+    return 1;
+  }
+
+  testing::PrintFlag(argv[1]);
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-failfast-unittest.py b/3rd-party/googletest/googletest/test/googletest-failfast-unittest.py
new file mode 100755
index 0000000..cdbce0c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-failfast-unittest.py
@@ -0,0 +1,461 @@
+#!/usr/bin/env python
+#
+# Copyright 2020 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test fail_fast.
+
+A user can specify if a Google Test program should continue test execution
+after a test failure via the GTEST_FAIL_FAST environment variable or the
+--gtest_fail_fast flag. The default value of the flag can also be changed
+by Bazel fail fast environment variable TESTBRIDGE_TEST_RUNNER_FAIL_FAST.
+
+This script tests such functionality by invoking googletest-failfast-unittest_
+(a program written with Google Test) with different environments and command
+line flags.
+"""
+
+import os
+from googletest.test import gtest_test_utils
+
+# Constants.
+
+# Bazel testbridge environment variable for fail fast
+BAZEL_FAIL_FAST_ENV_VAR = 'TESTBRIDGE_TEST_RUNNER_FAIL_FAST'
+
+# The environment variable for specifying fail fast.
+FAIL_FAST_ENV_VAR = 'GTEST_FAIL_FAST'
+
+# The command line flag for specifying fail fast.
+FAIL_FAST_FLAG = 'gtest_fail_fast'
+
+# The command line flag to run disabled tests.
+RUN_DISABLED_FLAG = 'gtest_also_run_disabled_tests'
+
+# The command line flag for specifying a filter.
+FILTER_FLAG = 'gtest_filter'
+
+# Command to run the googletest-failfast-unittest_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath(
+    'googletest-failfast-unittest_'
+)
+
+# The command line flag to tell Google Test to output the list of tests it
+# will run.
+LIST_TESTS_FLAG = '--gtest_list_tests'
+
+# Indicates whether Google Test supports death tests.
+SUPPORTS_DEATH_TESTS = (
+    'HasDeathTest'
+    in gtest_test_utils.Subprocess([COMMAND, LIST_TESTS_FLAG]).output
+)
+
+# Utilities.
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def RunAndReturnOutput(test_suite=None, fail_fast=None, run_disabled=False):
+  """Runs the test program and returns its output."""
+
+  args = []
+  xml_path = os.path.join(
+      gtest_test_utils.GetTempDir(), '.GTestFailFastUnitTest.xml'
+  )
+  args += ['--gtest_output=xml:' + xml_path]
+  if fail_fast is not None:
+    if isinstance(fail_fast, str):
+      args += ['--%s=%s' % (FAIL_FAST_FLAG, fail_fast)]
+    elif fail_fast:
+      args += ['--%s' % FAIL_FAST_FLAG]
+    else:
+      args += ['--no%s' % FAIL_FAST_FLAG]
+  if test_suite:
+    args += ['--%s=%s.*' % (FILTER_FLAG, test_suite)]
+  if run_disabled:
+    args += ['--%s' % RUN_DISABLED_FLAG]
+  txt_out = gtest_test_utils.Subprocess([COMMAND] + args, env=environ).output
+  with open(xml_path) as xml_file:
+    return txt_out, xml_file.read()
+
+
+# The unit test.
+class GTestFailFastUnitTest(gtest_test_utils.TestCase):
+  """Tests the env variable or the command line flag for fail_fast."""
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of not specifying the fail_fast."""
+
+    txt, _ = RunAndReturnOutput()
+    self.assertIn('22 FAILED TEST', txt)
+
+  def testGoogletestFlag(self):
+    txt, _ = RunAndReturnOutput(test_suite='HasSimpleTest', fail_fast=True)
+    self.assertIn('1 FAILED TEST', txt)
+    self.assertIn('[  SKIPPED ] 3 tests', txt)
+
+    txt, _ = RunAndReturnOutput(test_suite='HasSimpleTest', fail_fast=False)
+    self.assertIn('4 FAILED TEST', txt)
+    self.assertNotIn('[  SKIPPED ]', txt)
+
+  def testGoogletestEnvVar(self):
+    """Tests the behavior of specifying fail_fast via Googletest env var."""
+
+    try:
+      SetEnvVar(FAIL_FAST_ENV_VAR, '1')
+      txt, _ = RunAndReturnOutput('HasSimpleTest')
+      self.assertIn('1 FAILED TEST', txt)
+      self.assertIn('[  SKIPPED ] 3 tests', txt)
+
+      SetEnvVar(FAIL_FAST_ENV_VAR, '0')
+      txt, _ = RunAndReturnOutput('HasSimpleTest')
+      self.assertIn('4 FAILED TEST', txt)
+      self.assertNotIn('[  SKIPPED ]', txt)
+    finally:
+      SetEnvVar(FAIL_FAST_ENV_VAR, None)
+
+  def testBazelEnvVar(self):
+    """Tests the behavior of specifying fail_fast via Bazel testbridge."""
+
+    try:
+      SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '1')
+      txt, _ = RunAndReturnOutput('HasSimpleTest')
+      self.assertIn('1 FAILED TEST', txt)
+      self.assertIn('[  SKIPPED ] 3 tests', txt)
+
+      SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '0')
+      txt, _ = RunAndReturnOutput('HasSimpleTest')
+      self.assertIn('4 FAILED TEST', txt)
+      self.assertNotIn('[  SKIPPED ]', txt)
+    finally:
+      SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, None)
+
+  def testFlagOverridesEnvVar(self):
+    """Tests precedence of flag over env var."""
+
+    try:
+      SetEnvVar(FAIL_FAST_ENV_VAR, '0')
+      txt, _ = RunAndReturnOutput('HasSimpleTest', True)
+      self.assertIn('1 FAILED TEST', txt)
+      self.assertIn('[  SKIPPED ] 3 tests', txt)
+    finally:
+      SetEnvVar(FAIL_FAST_ENV_VAR, None)
+
+  def testGoogletestEnvVarOverridesBazelEnvVar(self):
+    """Tests that the Googletest native env var over Bazel testbridge."""
+
+    try:
+      SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '0')
+      SetEnvVar(FAIL_FAST_ENV_VAR, '1')
+      txt, _ = RunAndReturnOutput('HasSimpleTest')
+      self.assertIn('1 FAILED TEST', txt)
+      self.assertIn('[  SKIPPED ] 3 tests', txt)
+    finally:
+      SetEnvVar(FAIL_FAST_ENV_VAR, None)
+      SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, None)
+
+  def testEventListener(self):
+    txt, _ = RunAndReturnOutput(test_suite='HasSkipTest', fail_fast=True)
+    self.assertIn('1 FAILED TEST', txt)
+    self.assertIn('[  SKIPPED ] 3 tests', txt)
+    for expected_count, callback in [
+        (1, 'OnTestSuiteStart'),
+        (5, 'OnTestStart'),
+        (5, 'OnTestEnd'),
+        (5, 'OnTestPartResult'),
+        (1, 'OnTestSuiteEnd'),
+    ]:
+      self.assertEqual(
+          expected_count,
+          txt.count(callback),
+          'Expected %d calls to callback %s match count on output: %s '
+          % (expected_count, callback, txt),
+      )
+
+    txt, _ = RunAndReturnOutput(test_suite='HasSkipTest', fail_fast=False)
+    self.assertIn('3 FAILED TEST', txt)
+    self.assertIn('[  SKIPPED ] 1 test', txt)
+    for expected_count, callback in [
+        (1, 'OnTestSuiteStart'),
+        (5, 'OnTestStart'),
+        (5, 'OnTestEnd'),
+        (5, 'OnTestPartResult'),
+        (1, 'OnTestSuiteEnd'),
+    ]:
+      self.assertEqual(
+          expected_count,
+          txt.count(callback),
+          'Expected %d calls to callback %s match count on output: %s '
+          % (expected_count, callback, txt),
+      )
+
+  def assertXmlResultCount(self, result, count, xml):
+    self.assertEqual(
+        count,
+        xml.count('result="%s"' % result),
+        'Expected \'result="%s"\' match count of %s: %s '
+        % (result, count, xml),
+    )
+
+  def assertXmlStatusCount(self, status, count, xml):
+    self.assertEqual(
+        count,
+        xml.count('status="%s"' % status),
+        'Expected \'status="%s"\' match count of %s: %s '
+        % (status, count, xml),
+    )
+
+  def assertFailFastXmlAndTxtOutput(
+      self,
+      fail_fast,
+      test_suite,
+      passed_count,
+      failure_count,
+      skipped_count,
+      suppressed_count,
+      run_disabled=False,
+  ):
+    """Assert XML and text output of a test execution."""
+
+    txt, xml = RunAndReturnOutput(test_suite, fail_fast, run_disabled)
+    if failure_count > 0:
+      self.assertIn('%s FAILED TEST' % failure_count, txt)
+    if suppressed_count > 0:
+      self.assertIn('%s DISABLED TEST' % suppressed_count, txt)
+    if skipped_count > 0:
+      self.assertIn('[  SKIPPED ] %s tests' % skipped_count, txt)
+    self.assertXmlStatusCount(
+        'run', passed_count + failure_count + skipped_count, xml
+    )
+    self.assertXmlStatusCount('notrun', suppressed_count, xml)
+    self.assertXmlResultCount('completed', passed_count + failure_count, xml)
+    self.assertXmlResultCount('skipped', skipped_count, xml)
+    self.assertXmlResultCount('suppressed', suppressed_count, xml)
+
+  def assertFailFastBehavior(
+      self,
+      test_suite,
+      passed_count,
+      failure_count,
+      skipped_count,
+      suppressed_count,
+      run_disabled=False,
+  ):
+    """Assert --fail_fast via flag."""
+
+    for fail_fast in ('true', '1', 't', True):
+      self.assertFailFastXmlAndTxtOutput(
+          fail_fast,
+          test_suite,
+          passed_count,
+          failure_count,
+          skipped_count,
+          suppressed_count,
+          run_disabled,
+      )
+
+  def assertNotFailFastBehavior(
+      self,
+      test_suite,
+      passed_count,
+      failure_count,
+      skipped_count,
+      suppressed_count,
+      run_disabled=False,
+  ):
+    """Assert --nofail_fast via flag."""
+
+    for fail_fast in ('false', '0', 'f', False):
+      self.assertFailFastXmlAndTxtOutput(
+          fail_fast,
+          test_suite,
+          passed_count,
+          failure_count,
+          skipped_count,
+          suppressed_count,
+          run_disabled,
+      )
+
+  def testFlag_HasFixtureTest(self):
+    """Tests the behavior of fail_fast and TEST_F."""
+    self.assertFailFastBehavior(
+        test_suite='HasFixtureTest',
+        passed_count=1,
+        failure_count=1,
+        skipped_count=3,
+        suppressed_count=0,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='HasFixtureTest',
+        passed_count=1,
+        failure_count=4,
+        skipped_count=0,
+        suppressed_count=0,
+    )
+
+  def testFlag_HasSimpleTest(self):
+    """Tests the behavior of fail_fast and TEST."""
+    self.assertFailFastBehavior(
+        test_suite='HasSimpleTest',
+        passed_count=1,
+        failure_count=1,
+        skipped_count=3,
+        suppressed_count=0,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='HasSimpleTest',
+        passed_count=1,
+        failure_count=4,
+        skipped_count=0,
+        suppressed_count=0,
+    )
+
+  def testFlag_HasParametersTest(self):
+    """Tests the behavior of fail_fast and TEST_P."""
+    self.assertFailFastBehavior(
+        test_suite='HasParametersSuite/HasParametersTest',
+        passed_count=0,
+        failure_count=1,
+        skipped_count=3,
+        suppressed_count=0,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='HasParametersSuite/HasParametersTest',
+        passed_count=0,
+        failure_count=4,
+        skipped_count=0,
+        suppressed_count=0,
+    )
+
+  def testFlag_HasDisabledTest(self):
+    """Tests the behavior of fail_fast and Disabled test cases."""
+    self.assertFailFastBehavior(
+        test_suite='HasDisabledTest',
+        passed_count=1,
+        failure_count=1,
+        skipped_count=2,
+        suppressed_count=1,
+        run_disabled=False,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='HasDisabledTest',
+        passed_count=1,
+        failure_count=3,
+        skipped_count=0,
+        suppressed_count=1,
+        run_disabled=False,
+    )
+
+  def testFlag_HasDisabledRunDisabledTest(self):
+    """Tests the behavior of fail_fast and Disabled test cases enabled."""
+    self.assertFailFastBehavior(
+        test_suite='HasDisabledTest',
+        passed_count=1,
+        failure_count=1,
+        skipped_count=3,
+        suppressed_count=0,
+        run_disabled=True,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='HasDisabledTest',
+        passed_count=1,
+        failure_count=4,
+        skipped_count=0,
+        suppressed_count=0,
+        run_disabled=True,
+    )
+
+  def testFlag_HasDisabledSuiteTest(self):
+    """Tests the behavior of fail_fast and Disabled test suites."""
+    self.assertFailFastBehavior(
+        test_suite='DISABLED_HasDisabledSuite',
+        passed_count=0,
+        failure_count=0,
+        skipped_count=0,
+        suppressed_count=5,
+        run_disabled=False,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='DISABLED_HasDisabledSuite',
+        passed_count=0,
+        failure_count=0,
+        skipped_count=0,
+        suppressed_count=5,
+        run_disabled=False,
+    )
+
+  def testFlag_HasDisabledSuiteRunDisabledTest(self):
+    """Tests the behavior of fail_fast and Disabled test suites enabled."""
+    self.assertFailFastBehavior(
+        test_suite='DISABLED_HasDisabledSuite',
+        passed_count=1,
+        failure_count=1,
+        skipped_count=3,
+        suppressed_count=0,
+        run_disabled=True,
+    )
+    self.assertNotFailFastBehavior(
+        test_suite='DISABLED_HasDisabledSuite',
+        passed_count=1,
+        failure_count=4,
+        skipped_count=0,
+        suppressed_count=0,
+        run_disabled=True,
+    )
+
+  if SUPPORTS_DEATH_TESTS:
+
+    def testFlag_HasDeathTest(self):
+      """Tests the behavior of fail_fast and death tests."""
+      self.assertFailFastBehavior(
+          test_suite='HasDeathTest',
+          passed_count=1,
+          failure_count=1,
+          skipped_count=3,
+          suppressed_count=0,
+      )
+      self.assertNotFailFastBehavior(
+          test_suite='HasDeathTest',
+          passed_count=1,
+          failure_count=4,
+          skipped_count=0,
+          suppressed_count=0,
+      )
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-failfast-unittest_.cc b/3rd-party/googletest/googletest/test/googletest-failfast-unittest_.cc
new file mode 100644
index 0000000..3bd05a8
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-failfast-unittest_.cc
@@ -0,0 +1,166 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test test filters.
+//
+// A user can specify which test(s) in a Google Test program to run via
+// either the GTEST_FILTER environment variable or the --gtest_filter
+// flag.  This is used for testing such functionality.
+//
+// The program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// Test HasFixtureTest.
+
+class HasFixtureTest : public testing::Test {};
+
+TEST_F(HasFixtureTest, Test0) {}
+
+TEST_F(HasFixtureTest, Test1) { FAIL() << "Expected failure."; }
+
+TEST_F(HasFixtureTest, Test2) { FAIL() << "Expected failure."; }
+
+TEST_F(HasFixtureTest, Test3) { FAIL() << "Expected failure."; }
+
+TEST_F(HasFixtureTest, Test4) { FAIL() << "Expected failure."; }
+
+// Test HasSimpleTest.
+
+TEST(HasSimpleTest, Test0) {}
+
+TEST(HasSimpleTest, Test1) { FAIL() << "Expected failure."; }
+
+TEST(HasSimpleTest, Test2) { FAIL() << "Expected failure."; }
+
+TEST(HasSimpleTest, Test3) { FAIL() << "Expected failure."; }
+
+TEST(HasSimpleTest, Test4) { FAIL() << "Expected failure."; }
+
+// Test HasDisabledTest.
+
+TEST(HasDisabledTest, Test0) {}
+
+TEST(HasDisabledTest, DISABLED_Test1) { FAIL() << "Expected failure."; }
+
+TEST(HasDisabledTest, Test2) { FAIL() << "Expected failure."; }
+
+TEST(HasDisabledTest, Test3) { FAIL() << "Expected failure."; }
+
+TEST(HasDisabledTest, Test4) { FAIL() << "Expected failure."; }
+
+// Test HasDeathTest
+
+TEST(HasDeathTest, Test0) { EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*"); }
+
+TEST(HasDeathTest, Test1) {
+  EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
+}
+
+TEST(HasDeathTest, Test2) {
+  EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
+}
+
+TEST(HasDeathTest, Test3) {
+  EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
+}
+
+TEST(HasDeathTest, Test4) {
+  EXPECT_DEATH_IF_SUPPORTED(FAIL() << "Expected failure.", ".*");
+}
+
+// Test DISABLED_HasDisabledSuite
+
+TEST(DISABLED_HasDisabledSuite, Test0) {}
+
+TEST(DISABLED_HasDisabledSuite, Test1) { FAIL() << "Expected failure."; }
+
+TEST(DISABLED_HasDisabledSuite, Test2) { FAIL() << "Expected failure."; }
+
+TEST(DISABLED_HasDisabledSuite, Test3) { FAIL() << "Expected failure."; }
+
+TEST(DISABLED_HasDisabledSuite, Test4) { FAIL() << "Expected failure."; }
+
+// Test HasParametersTest
+
+class HasParametersTest : public testing::TestWithParam<int> {};
+
+TEST_P(HasParametersTest, Test1) { FAIL() << "Expected failure."; }
+
+TEST_P(HasParametersTest, Test2) { FAIL() << "Expected failure."; }
+
+INSTANTIATE_TEST_SUITE_P(HasParametersSuite, HasParametersTest,
+                         testing::Values(1, 2));
+
+class MyTestListener : public ::testing::EmptyTestEventListener {
+  void OnTestSuiteStart(const ::testing::TestSuite& test_suite) override {
+    printf("We are in OnTestSuiteStart of %s.\n", test_suite.name());
+  }
+
+  void OnTestStart(const ::testing::TestInfo& test_info) override {
+    printf("We are in OnTestStart of %s.%s.\n", test_info.test_suite_name(),
+           test_info.name());
+  }
+
+  void OnTestPartResult(
+      const ::testing::TestPartResult& test_part_result) override {
+    printf("We are in OnTestPartResult %s:%d.\n", test_part_result.file_name(),
+           test_part_result.line_number());
+  }
+
+  void OnTestEnd(const ::testing::TestInfo& test_info) override {
+    printf("We are in OnTestEnd of %s.%s.\n", test_info.test_suite_name(),
+           test_info.name());
+  }
+
+  void OnTestSuiteEnd(const ::testing::TestSuite& test_suite) override {
+    printf("We are in OnTestSuiteEnd of %s.\n", test_suite.name());
+  }
+};
+
+TEST(HasSkipTest, Test0) { SUCCEED() << "Expected success."; }
+
+TEST(HasSkipTest, Test1) { GTEST_SKIP() << "Expected skip."; }
+
+TEST(HasSkipTest, Test2) { FAIL() << "Expected failure."; }
+
+TEST(HasSkipTest, Test3) { FAIL() << "Expected failure."; }
+
+TEST(HasSkipTest, Test4) { FAIL() << "Expected failure."; }
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  ::testing::UnitTest::GetInstance()->listeners().Append(new MyTestListener());
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-filepath-test.cc b/3rd-party/googletest/googletest/test/googletest-filepath-test.cc
new file mode 100644
index 0000000..3e9c79f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-filepath-test.cc
@@ -0,0 +1,671 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Google Test filepath utilities
+//
+// This file tests classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included from gtest-internal.h.
+// Do not #include this file anywhere else!
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "src/gtest-internal-inl.h"
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+#include <windows.h>  // NOLINT
+#elif defined(GTEST_OS_WINDOWS)
+#include <direct.h>  // NOLINT
+#endif               // GTEST_OS_WINDOWS_MOBILE
+
+namespace testing {
+namespace internal {
+namespace {
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+
+// Windows CE doesn't have the remove C function.
+int remove(const char* path) {
+  LPCWSTR wpath = String::AnsiToUtf16(path);
+  int ret = DeleteFile(wpath) ? 0 : -1;
+  delete[] wpath;
+  return ret;
+}
+// Windows CE doesn't have the _rmdir C function.
+int _rmdir(const char* path) {
+  FilePath filepath(path);
+  LPCWSTR wpath =
+      String::AnsiToUtf16(filepath.RemoveTrailingPathSeparator().c_str());
+  int ret = RemoveDirectory(wpath) ? 0 : -1;
+  delete[] wpath;
+  return ret;
+}
+
+#else
+
+TEST(GetCurrentDirTest, ReturnsCurrentDir) {
+  const FilePath original_dir = FilePath::GetCurrentDir();
+  EXPECT_FALSE(original_dir.IsEmpty());
+
+  posix::ChDir(GTEST_PATH_SEP_);
+  const FilePath cwd = FilePath::GetCurrentDir();
+  posix::ChDir(original_dir.c_str());
+
+#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_OS2)
+
+  // Skips the ":".
+  const char* const cwd_without_drive = strchr(cwd.c_str(), ':');
+  ASSERT_TRUE(cwd_without_drive != NULL);
+  EXPECT_STREQ(GTEST_PATH_SEP_, cwd_without_drive + 1);
+
+#else
+
+  EXPECT_EQ(GTEST_PATH_SEP_, cwd.string());
+
+#endif
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+TEST(IsEmptyTest, ReturnsTrueForEmptyPath) {
+  EXPECT_TRUE(FilePath("").IsEmpty());
+}
+
+TEST(IsEmptyTest, ReturnsFalseForNonEmptyPath) {
+  EXPECT_FALSE(FilePath("a").IsEmpty());
+  EXPECT_FALSE(FilePath(".").IsEmpty());
+  EXPECT_FALSE(FilePath("a/b").IsEmpty());
+  EXPECT_FALSE(FilePath("a\\b\\").IsEmpty());
+}
+
+// RemoveDirectoryName "" -> ""
+TEST(RemoveDirectoryNameTest, WhenEmptyName) {
+  EXPECT_EQ("", FilePath("").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ButNoDirectory) {
+  EXPECT_EQ("afile", FilePath("afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileName) {
+  EXPECT_EQ("afile",
+            FilePath(GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "adir/" -> ""
+TEST(RemoveDirectoryNameTest, WhereThereIsNoFileName) {
+  EXPECT_EQ("",
+            FilePath("adir" GTEST_PATH_SEP_).RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "adir/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldGiveFileName) {
+  EXPECT_EQ(
+      "afile",
+      FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "adir/subdir/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
+  EXPECT_EQ("afile",
+            FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
+                .RemoveDirectoryName()
+                .string());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that RemoveDirectoryName() works with the alternate separator
+// on Windows.
+
+// RemoveDirectoryName("/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileNameForAlternateSeparator) {
+  EXPECT_EQ("afile", FilePath("/afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName("adir/") -> ""
+TEST(RemoveDirectoryNameTest, WhereThereIsNoFileNameForAlternateSeparator) {
+  EXPECT_EQ("", FilePath("adir/").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName("adir/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldGiveFileNameForAlternateSeparator) {
+  EXPECT_EQ("afile", FilePath("adir/afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName("adir/subdir/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileNameForAlternateSeparator) {
+  EXPECT_EQ("afile",
+            FilePath("adir/subdir/afile").RemoveDirectoryName().string());
+}
+
+#endif
+
+// RemoveFileName "" -> "./"
+TEST(RemoveFileNameTest, EmptyName) {
+#ifdef GTEST_OS_WINDOWS_MOBILE
+  // On Windows CE, we use the root as the current directory.
+  EXPECT_EQ(GTEST_PATH_SEP_, FilePath("").RemoveFileName().string());
+#else
+  EXPECT_EQ("." GTEST_PATH_SEP_, FilePath("").RemoveFileName().string());
+#endif
+}
+
+// RemoveFileName "adir/" -> "adir/"
+TEST(RemoveFileNameTest, ButNoFile) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir" GTEST_PATH_SEP_).RemoveFileName().string());
+}
+
+// RemoveFileName "adir/afile" -> "adir/"
+TEST(RemoveFileNameTest, GivesDirName) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveFileName().string());
+}
+
+// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
+TEST(RemoveFileNameTest, GivesDirAndSubDirName) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
+            FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
+                .RemoveFileName()
+                .string());
+}
+
+// RemoveFileName "/afile" -> "/"
+TEST(RemoveFileNameTest, GivesRootDir) {
+  EXPECT_EQ(GTEST_PATH_SEP_,
+            FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().string());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that RemoveFileName() works with the alternate separator on
+// Windows.
+
+// RemoveFileName("adir/") -> "adir/"
+TEST(RemoveFileNameTest, ButNoFileForAlternateSeparator) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir/").RemoveFileName().string());
+}
+
+// RemoveFileName("adir/afile") -> "adir/"
+TEST(RemoveFileNameTest, GivesDirNameForAlternateSeparator) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir/afile").RemoveFileName().string());
+}
+
+// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
+TEST(RemoveFileNameTest, GivesDirAndSubDirNameForAlternateSeparator) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
+            FilePath("adir/subdir/afile").RemoveFileName().string());
+}
+
+// RemoveFileName("/afile") -> "\"
+TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
+  EXPECT_EQ(GTEST_PATH_SEP_, FilePath("/afile").RemoveFileName().string());
+}
+
+#endif
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsZero) {
+  FilePath actual =
+      FilePath::MakeFileName(FilePath("foo"), FilePath("bar"), 0, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameNumberGtZero) {
+  FilePath actual =
+      FilePath::MakeFileName(FilePath("foo"), FilePath("bar"), 12, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberIsZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
+                                           FilePath("bar"), 0, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberGtZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
+                                           FilePath("bar"), 12, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsZeroAndDirIsEmpty) {
+  FilePath actual =
+      FilePath::MakeFileName(FilePath(""), FilePath("bar"), 0, "xml");
+  EXPECT_EQ("bar.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsNotZeroAndDirIsEmpty) {
+  FilePath actual =
+      FilePath::MakeFileName(FilePath(""), FilePath("bar"), 14, "xml");
+  EXPECT_EQ("bar_14.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, WorksWhenDirDoesNotEndWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"), FilePath("bar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, WorksWhenPath1EndsWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_),
+                                          FilePath("bar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, Path1BeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath(""), FilePath("bar.xml"));
+  EXPECT_EQ("bar.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, Path2BeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"), FilePath(""));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_, actual.string());
+}
+
+TEST(ConcatPathsTest, BothPathBeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath(""), FilePath(""));
+  EXPECT_EQ("", actual.string());
+}
+
+TEST(ConcatPathsTest, Path1ContainsPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_ "bar"),
+                                          FilePath("foobar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "foobar.xml",
+            actual.string());
+}
+
+TEST(ConcatPathsTest, Path2ContainsPathSep) {
+  FilePath actual =
+      FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_),
+                            FilePath("bar" GTEST_PATH_SEP_ "bar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "bar.xml",
+            actual.string());
+}
+
+TEST(ConcatPathsTest, Path2EndsWithPathSep) {
+  FilePath actual =
+      FilePath::ConcatPaths(FilePath("foo"), FilePath("bar" GTEST_PATH_SEP_));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_, actual.string());
+}
+
+// RemoveTrailingPathSeparator "" -> ""
+TEST(RemoveTrailingPathSeparatorTest, EmptyString) {
+  EXPECT_EQ("", FilePath("").RemoveTrailingPathSeparator().string());
+}
+
+// RemoveTrailingPathSeparator "foo" -> "foo"
+TEST(RemoveTrailingPathSeparatorTest, FileNoSlashString) {
+  EXPECT_EQ("foo", FilePath("foo").RemoveTrailingPathSeparator().string());
+}
+
+// RemoveTrailingPathSeparator "foo/" -> "foo"
+TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
+  EXPECT_EQ(
+      "foo",
+      FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().string());
+#if GTEST_HAS_ALT_PATH_SEP_
+  EXPECT_EQ("foo", FilePath("foo/").RemoveTrailingPathSeparator().string());
+#endif
+}
+
+// RemoveTrailingPathSeparator "foo/bar/" -> "foo/bar/"
+TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveLastSeparator) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_)
+                .RemoveTrailingPathSeparator()
+                .string());
+}
+
+// RemoveTrailingPathSeparator "foo/bar" -> "foo/bar"
+TEST(RemoveTrailingPathSeparatorTest, ShouldReturnUnmodified) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar", FilePath("foo" GTEST_PATH_SEP_ "bar")
+                                             .RemoveTrailingPathSeparator()
+                                             .string());
+}
+
+TEST(DirectoryTest, RootDirectoryExists) {
+#ifdef GTEST_OS_WINDOWS           // We are on Windows.
+  char current_drive[_MAX_PATH];  // NOLINT
+  current_drive[0] = static_cast<char>(_getdrive() + 'A' - 1);
+  current_drive[1] = ':';
+  current_drive[2] = '\\';
+  current_drive[3] = '\0';
+  EXPECT_TRUE(FilePath(current_drive).DirectoryExists());
+#else
+  EXPECT_TRUE(FilePath("/").DirectoryExists());
+#endif  // GTEST_OS_WINDOWS
+}
+
+#ifdef GTEST_OS_WINDOWS
+TEST(DirectoryTest, RootOfWrongDriveDoesNotExists) {
+  const int saved_drive_ = _getdrive();
+  // Find a drive that doesn't exist. Start with 'Z' to avoid common ones.
+  for (char drive = 'Z'; drive >= 'A'; drive--)
+    if (_chdrive(drive - 'A' + 1) == -1) {
+      char non_drive[_MAX_PATH];  // NOLINT
+      non_drive[0] = drive;
+      non_drive[1] = ':';
+      non_drive[2] = '\\';
+      non_drive[3] = '\0';
+      EXPECT_FALSE(FilePath(non_drive).DirectoryExists());
+      break;
+    }
+  _chdrive(saved_drive_);
+}
+#endif  // GTEST_OS_WINDOWS
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+// Windows CE _does_ consider an empty directory to exist.
+TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
+  EXPECT_FALSE(FilePath("").DirectoryExists());
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+TEST(DirectoryTest, CurrentDirectoryExists) {
+#ifdef GTEST_OS_WINDOWS  // We are on Windows.
+#ifndef _WIN32_CE     // Windows CE doesn't have a current directory.
+
+  EXPECT_TRUE(FilePath(".").DirectoryExists());
+  EXPECT_TRUE(FilePath(".\\").DirectoryExists());
+
+#endif  // _WIN32_CE
+#else
+  EXPECT_TRUE(FilePath(".").DirectoryExists());
+  EXPECT_TRUE(FilePath("./").DirectoryExists());
+#endif  // GTEST_OS_WINDOWS
+}
+
+// "foo/bar" == foo//bar" == "foo///bar"
+TEST(NormalizeTest, MultipleConsecutiveSeparatorsInMidstring) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ "bar").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+  EXPECT_EQ(
+      "foo" GTEST_PATH_SEP_ "bar",
+      FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar")
+          .string());
+}
+
+// "/bar" == //bar" == "///bar"
+TEST(NormalizeTest, MultipleConsecutiveSeparatorsAtStringStart) {
+  EXPECT_EQ(GTEST_PATH_SEP_ "bar", FilePath(GTEST_PATH_SEP_ "bar").string());
+#ifdef GTEST_OS_WINDOWS
+  EXPECT_EQ(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar",
+            FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+#else
+  EXPECT_EQ(GTEST_PATH_SEP_ "bar",
+            FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+#endif
+  EXPECT_EQ(
+      GTEST_PATH_SEP_ "bar",
+      FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+}
+
+// "foo/" == foo//" == "foo///"
+TEST(NormalizeTest, MultipleConsecutiveSeparatorsAtStringEnd) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_, FilePath("foo" GTEST_PATH_SEP_).string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+            FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
+  EXPECT_EQ(
+      "foo" GTEST_PATH_SEP_,
+      FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that separators at the end of the string are normalized
+// regardless of their combination (e.g. "foo\" =="foo/\" ==
+// "foo\\/").
+TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_, FilePath("foo/").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+            FilePath("foo" GTEST_PATH_SEP_ "/").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_, FilePath("foo//" GTEST_PATH_SEP_).string());
+}
+
+#endif
+
+TEST(AssignmentOperatorTest, DefaultAssignedToNonDefault) {
+  FilePath default_path;
+  FilePath non_default_path("path");
+  non_default_path = default_path;
+  EXPECT_EQ("", non_default_path.string());
+  EXPECT_EQ("", default_path.string());  // RHS var is unchanged.
+}
+
+TEST(AssignmentOperatorTest, NonDefaultAssignedToDefault) {
+  FilePath non_default_path("path");
+  FilePath default_path;
+  default_path = non_default_path;
+  EXPECT_EQ("path", default_path.string());
+  EXPECT_EQ("path", non_default_path.string());  // RHS var is unchanged.
+}
+
+TEST(AssignmentOperatorTest, ConstAssignedToNonConst) {
+  const FilePath const_default_path("const_path");
+  FilePath non_default_path("path");
+  non_default_path = const_default_path;
+  EXPECT_EQ("const_path", non_default_path.string());
+}
+
+class DirectoryCreationTest : public Test {
+ protected:
+  void SetUp() override {
+    testdata_path_.Set(
+        FilePath(TempDir() + GetCurrentExecutableName().string() +
+                 "_directory_creation" GTEST_PATH_SEP_ "test" GTEST_PATH_SEP_));
+    testdata_file_.Set(testdata_path_.RemoveTrailingPathSeparator());
+
+    unique_file0_.Set(
+        FilePath::MakeFileName(testdata_path_, FilePath("unique"), 0, "txt"));
+    unique_file1_.Set(
+        FilePath::MakeFileName(testdata_path_, FilePath("unique"), 1, "txt"));
+
+    remove(testdata_file_.c_str());
+    remove(unique_file0_.c_str());
+    remove(unique_file1_.c_str());
+    posix::RmDir(testdata_path_.c_str());
+  }
+
+  void TearDown() override {
+    remove(testdata_file_.c_str());
+    remove(unique_file0_.c_str());
+    remove(unique_file1_.c_str());
+    posix::RmDir(testdata_path_.c_str());
+  }
+
+  void CreateTextFile(const char* filename) {
+    FILE* f = posix::FOpen(filename, "w");
+    fprintf(f, "text\n");
+    fclose(f);
+  }
+
+  // Strings representing a directory and a file, with identical paths
+  // except for the trailing separator character that distinguishes
+  // a directory named 'test' from a file named 'test'. Example names:
+  FilePath testdata_path_;  // "/tmp/directory_creation/test/"
+  FilePath testdata_file_;  // "/tmp/directory_creation/test"
+  FilePath unique_file0_;   // "/tmp/directory_creation/test/unique.txt"
+  FilePath unique_file1_;   // "/tmp/directory_creation/test/unique_1.txt"
+};
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesRecursively) {
+  EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.string();
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+  EXPECT_TRUE(testdata_path_.DirectoryExists());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesForAlreadyExistingPath) {
+  EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.string();
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+  // Call 'create' again... should still succeed.
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesAndUniqueFilename) {
+  FilePath file_path(FilePath::GenerateUniqueFileName(
+      testdata_path_, FilePath("unique"), "txt"));
+  EXPECT_EQ(unique_file0_.string(), file_path.string());
+  EXPECT_FALSE(file_path.FileOrDirectoryExists());  // file not there
+
+  testdata_path_.CreateDirectoriesRecursively();
+  EXPECT_FALSE(file_path.FileOrDirectoryExists());  // file still not there
+  CreateTextFile(file_path.c_str());
+  EXPECT_TRUE(file_path.FileOrDirectoryExists());
+
+  FilePath file_path2(FilePath::GenerateUniqueFileName(
+      testdata_path_, FilePath("unique"), "txt"));
+  EXPECT_EQ(unique_file1_.string(), file_path2.string());
+  EXPECT_FALSE(file_path2.FileOrDirectoryExists());  // file not there
+  CreateTextFile(file_path2.c_str());
+  EXPECT_TRUE(file_path2.FileOrDirectoryExists());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesFail) {
+  // force a failure by putting a file where we will try to create a directory.
+  CreateTextFile(testdata_file_.c_str());
+  EXPECT_TRUE(testdata_file_.FileOrDirectoryExists());
+  EXPECT_FALSE(testdata_file_.DirectoryExists());
+  EXPECT_FALSE(testdata_file_.CreateDirectoriesRecursively());
+}
+
+TEST(NoDirectoryCreationTest, CreateNoDirectoriesForDefaultXmlFile) {
+  const FilePath test_detail_xml("test_detail.xml");
+  EXPECT_FALSE(test_detail_xml.CreateDirectoriesRecursively());
+}
+
+TEST(FilePathTest, DefaultConstructor) {
+  FilePath fp;
+  EXPECT_EQ("", fp.string());
+}
+
+TEST(FilePathTest, CharAndCopyConstructors) {
+  const FilePath fp("spicy");
+  EXPECT_EQ("spicy", fp.string());
+
+  const FilePath fp_copy(fp);
+  EXPECT_EQ("spicy", fp_copy.string());
+}
+
+TEST(FilePathTest, StringConstructor) {
+  const FilePath fp(std::string("cider"));
+  EXPECT_EQ("cider", fp.string());
+}
+
+TEST(FilePathTest, Set) {
+  const FilePath apple("apple");
+  FilePath mac("mac");
+  mac.Set(apple);  // Implement Set() since overloading operator= is forbidden.
+  EXPECT_EQ("apple", mac.string());
+  EXPECT_EQ("apple", apple.string());
+}
+
+TEST(FilePathTest, ToString) {
+  const FilePath file("drink");
+  EXPECT_EQ("drink", file.string());
+}
+
+TEST(FilePathTest, RemoveExtension) {
+  EXPECT_EQ("app", FilePath("app.cc").RemoveExtension("cc").string());
+  EXPECT_EQ("app", FilePath("app.exe").RemoveExtension("exe").string());
+  EXPECT_EQ("APP", FilePath("APP.EXE").RemoveExtension("exe").string());
+}
+
+TEST(FilePathTest, RemoveExtensionWhenThereIsNoExtension) {
+  EXPECT_EQ("app", FilePath("app").RemoveExtension("exe").string());
+}
+
+TEST(FilePathTest, IsDirectory) {
+  EXPECT_FALSE(FilePath("cola").IsDirectory());
+  EXPECT_TRUE(FilePath("koala" GTEST_PATH_SEP_).IsDirectory());
+#if GTEST_HAS_ALT_PATH_SEP_
+  EXPECT_TRUE(FilePath("koala/").IsDirectory());
+#endif
+}
+
+TEST(FilePathTest, IsAbsolutePath) {
+  EXPECT_FALSE(FilePath("is" GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+  EXPECT_FALSE(FilePath("").IsAbsolutePath());
+#ifdef GTEST_OS_WINDOWS
+  EXPECT_TRUE(
+      FilePath("c:\\" GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
+          .IsAbsolutePath());
+  EXPECT_FALSE(FilePath("c:foo" GTEST_PATH_SEP_ "bar").IsAbsolutePath());
+  EXPECT_TRUE(
+      FilePath("c:/" GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
+          .IsAbsolutePath());
+  EXPECT_TRUE(FilePath("d:/Windows").IsAbsolutePath());
+  EXPECT_TRUE(FilePath("\\\\Host\\Share").IsAbsolutePath());
+  EXPECT_TRUE(FilePath("\\\\Host\\Share\\Folder").IsAbsolutePath());
+#else
+  EXPECT_TRUE(FilePath(GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
+                  .IsAbsolutePath());
+#endif  // GTEST_OS_WINDOWS
+}
+
+TEST(FilePathTest, IsRootDirectory) {
+#ifdef GTEST_OS_WINDOWS
+  EXPECT_TRUE(FilePath("a:\\").IsRootDirectory());
+  EXPECT_TRUE(FilePath("Z:/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("e://").IsRootDirectory());
+  EXPECT_FALSE(FilePath("").IsRootDirectory());
+  EXPECT_FALSE(FilePath("b:").IsRootDirectory());
+  EXPECT_FALSE(FilePath("b:a").IsRootDirectory());
+  EXPECT_FALSE(FilePath("8:/").IsRootDirectory());
+  EXPECT_FALSE(FilePath("c|/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("c:/").IsRootDirectory());
+  EXPECT_FALSE(FilePath("d:/Windows").IsRootDirectory());
+
+  // This is for backward compatibility, since callers (even in this library)
+  // have assumed IsRootDirectory() implies a trailing directory separator.
+  EXPECT_FALSE(FilePath("\\\\Host\\Share").IsRootDirectory());
+
+  EXPECT_TRUE(FilePath("\\\\Host\\Share\\").IsRootDirectory());
+  EXPECT_FALSE(FilePath("\\\\Host\\Share\\.").IsRootDirectory());
+  EXPECT_FALSE(FilePath("\\\\Host\\Share\\C$\\").IsRootDirectory());
+#else
+  EXPECT_TRUE(FilePath("/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("//").IsRootDirectory());
+  EXPECT_FALSE(FilePath("").IsRootDirectory());
+  EXPECT_FALSE(FilePath("\\").IsRootDirectory());
+  EXPECT_FALSE(FilePath("/x").IsRootDirectory());
+#endif
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/test/googletest-filter-unittest.py b/3rd-party/googletest/googletest/test/googletest-filter-unittest.py
new file mode 100755
index 0000000..f1f3c7a
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-filter-unittest.py
@@ -0,0 +1,746 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test test filters.
+
+A user can specify which test(s) in a Google Test program to run via either
+the GTEST_FILTER environment variable or the --gtest_filter flag.
+This script tests such functionality by invoking
+googletest-filter-unittest_ (a program written with Google Test) with different
+environments and command line flags.
+
+Note that test sharding may also influence which tests are filtered. Therefore,
+we test that here also.
+"""
+
+import os
+import re
+
+try:
+  from sets import Set as set  # For Python 2.3 compatibility
+except ImportError:
+  pass
+import sys
+from googletest.test import gtest_test_utils
+
+# Constants.
+
+# Checks if this platform can pass empty environment variables to child
+# processes.  We set an env variable to an empty string and invoke a python
+# script in a subprocess to print whether the variable is STILL in
+# os.environ.  We then use 'eval' to parse the child's output so that an
+# exception is thrown if the input is anything other than 'True' nor 'False'.
+CAN_PASS_EMPTY_ENV = False
+if sys.executable:
+  os.environ['EMPTY_VAR'] = ''
+  child = gtest_test_utils.Subprocess(
+      [sys.executable, '-c', "import os; print('EMPTY_VAR' in os.environ)"]
+  )
+  CAN_PASS_EMPTY_ENV = eval(child.output)
+
+
+# Check if this platform can unset environment variables in child processes.
+# We set an env variable to a non-empty string, unset it, and invoke
+# a python script in a subprocess to print whether the variable
+# is NO LONGER in os.environ.
+# We use 'eval' to parse the child's output so that an exception
+# is thrown if the input is neither 'True' nor 'False'.
+CAN_UNSET_ENV = False
+if sys.executable:
+  os.environ['UNSET_VAR'] = 'X'
+  del os.environ['UNSET_VAR']
+  child = gtest_test_utils.Subprocess(
+      [sys.executable, '-c', "import os; print('UNSET_VAR' not in os.environ)"]
+  )
+  CAN_UNSET_ENV = eval(child.output)
+
+
+# Checks if we should test with an empty filter. This doesn't
+# make sense on platforms that cannot pass empty env variables (Win32)
+# and on platforms that cannot unset variables (since we cannot tell
+# the difference between "" and NULL -- Borland and Solaris < 5.10)
+CAN_TEST_EMPTY_FILTER = CAN_PASS_EMPTY_ENV and CAN_UNSET_ENV
+
+
+# The environment variable for specifying the test filters.
+FILTER_ENV_VAR = 'GTEST_FILTER'
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
+
+# The command line flag for specifying the test filters.
+FILTER_FLAG = 'gtest_filter'
+
+# The command line flag for including disabled tests.
+ALSO_RUN_DISABLED_TESTS_FLAG = 'gtest_also_run_disabled_tests'
+
+# Command to run the googletest-filter-unittest_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-filter-unittest_')
+
+# Regex for determining whether parameterized tests are enabled in the binary.
+PARAM_TEST_REGEX = re.compile(r'/ParamTest')
+
+# Regex for parsing test case names from Google Test's output.
+TEST_CASE_REGEX = re.compile(r'^\[\-+\] \d+ tests? from (\w+(/\w+)?)')
+
+# Regex for parsing test names from Google Test's output.
+TEST_REGEX = re.compile(r'^\[\s*RUN\s*\].*\.(\w+(/\w+)?)')
+
+# Regex for parsing disabled banner from Google Test's output
+DISABLED_BANNER_REGEX = re.compile(r'^\[\s*DISABLED\s*\] (.*)')
+
+# The command line flag to tell Google Test to output the list of tests it
+# will run.
+LIST_TESTS_FLAG = '--gtest_list_tests'
+
+# Indicates whether Google Test supports death tests.
+SUPPORTS_DEATH_TESTS = (
+    'HasDeathTest'
+    in gtest_test_utils.Subprocess([COMMAND, LIST_TESTS_FLAG]).output
+)
+
+# Full names of all tests in googletest-filter-unittests_.
+PARAM_TESTS = [
+    'SeqP/ParamTest.TestX/0',
+    'SeqP/ParamTest.TestX/1',
+    'SeqP/ParamTest.TestY/0',
+    'SeqP/ParamTest.TestY/1',
+    'SeqQ/ParamTest.TestX/0',
+    'SeqQ/ParamTest.TestX/1',
+    'SeqQ/ParamTest.TestY/0',
+    'SeqQ/ParamTest.TestY/1',
+]
+
+DISABLED_TESTS = [
+    'BarTest.DISABLED_TestFour',
+    'BarTest.DISABLED_TestFive',
+    'BazTest.DISABLED_TestC',
+    'DISABLED_FoobarTest.Test1',
+    'DISABLED_FoobarTest.DISABLED_Test2',
+    'DISABLED_FoobarbazTest.TestA',
+]
+
+if SUPPORTS_DEATH_TESTS:
+  DEATH_TESTS = [
+      'HasDeathTest.Test1',
+      'HasDeathTest.Test2',
+  ]
+else:
+  DEATH_TESTS = []
+
+# All the non-disabled tests.
+ACTIVE_TESTS = (
+    [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        'BazTest.TestB',
+    ]
+    + DEATH_TESTS
+    + PARAM_TESTS
+)
+
+param_tests_present = None
+
+# Utilities.
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def RunAndReturnOutput(args=None):
+  """Runs the test program and returns its output."""
+
+  return gtest_test_utils.Subprocess(
+      [COMMAND] + (args or []), env=environ
+  ).output
+
+
+def RunAndExtractTestList(args=None):
+  """Runs the test program and returns its exit code and a list of tests run."""
+
+  p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
+  tests_run = []
+  test_case = ''
+  test = ''
+  for line in p.output.split('\n'):
+    match = TEST_CASE_REGEX.match(line)
+    if match is not None:
+      test_case = match.group(1)
+    else:
+      match = TEST_REGEX.match(line)
+      if match is not None:
+        test = match.group(1)
+        tests_run.append(test_case + '.' + test)
+  return (tests_run, p.exit_code)
+
+
+def RunAndExtractDisabledBannerList(args=None):
+  """Runs the test program and returns tests that printed a disabled banner."""
+  p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
+  banners_printed = []
+  for line in p.output.split('\n'):
+    match = DISABLED_BANNER_REGEX.match(line)
+    if match is not None:
+      banners_printed.append(match.group(1))
+  return banners_printed
+
+
+def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
+  """Runs the given function and arguments in a modified environment."""
+  try:
+    original_env = environ.copy()
+    environ.update(extra_env)
+    return function(*args, **kwargs)
+  finally:
+    environ.clear()
+    environ.update(original_env)
+
+
+def RunWithSharding(total_shards, shard_index, command):
+  """Runs a test program shard and returns exit code and a list of tests run."""
+
+  extra_env = {
+      SHARD_INDEX_ENV_VAR: str(shard_index),
+      TOTAL_SHARDS_ENV_VAR: str(total_shards),
+  }
+  return InvokeWithModifiedEnv(extra_env, RunAndExtractTestList, command)
+
+
+# The unit test.
+
+
+class GTestFilterUnitTest(gtest_test_utils.TestCase):
+  """Tests the env variable or the command line flag to filter tests."""
+
+  # Utilities.
+
+  def AssertSetEqual(self, lhs, rhs):
+    """Asserts that two sets are equal."""
+
+    for elem in lhs:
+      self.assertTrue(elem in rhs, '%s in %s' % (elem, rhs))
+
+    for elem in rhs:
+      self.assertTrue(elem in lhs, '%s in %s' % (elem, lhs))
+
+  def AssertPartitionIsValid(self, set_var, list_of_sets):
+    """Asserts that list_of_sets is a valid partition of set_var."""
+
+    full_partition = []
+    for slice_var in list_of_sets:
+      full_partition.extend(slice_var)
+    self.assertEqual(len(set_var), len(full_partition))
+    self.assertEqual(set(set_var), set(full_partition))
+
+  def AdjustForParameterizedTests(self, tests_to_run):
+    """Adjust tests_to_run in case value parameterized tests are disabled."""
+
+    global param_tests_present
+    if not param_tests_present:
+      return list(set(tests_to_run) - set(PARAM_TESTS))
+    else:
+      return tests_to_run
+
+  def RunAndVerify(self, gtest_filter, tests_to_run):
+    """Checks that the binary runs correct set of tests for a given filter."""
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # First, tests using the environment variable.
+
+    # Windows removes empty variables from the environment when passing it
+    # to a new process.  This means it is impossible to pass an empty filter
+    # into a process using the environment variable.  However, we can still
+    # test the case when the variable is not supplied (i.e., gtest_filter is
+    # None).
+    # pylint: disable=g-explicit-bool-comparison
+    if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
+      SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+      tests_run = RunAndExtractTestList()[0]
+      SetEnvVar(FILTER_ENV_VAR, None)
+      self.AssertSetEqual(tests_run, tests_to_run)
+    # pylint: enable=g-explicit-bool-comparison
+
+    # Next, tests using the command line flag.
+
+    if gtest_filter is None:
+      args = []
+    else:
+      args = ['--%s=%s' % (FILTER_FLAG, gtest_filter)]
+
+    tests_run = RunAndExtractTestList(args)[0]
+    self.AssertSetEqual(tests_run, tests_to_run)
+
+  def RunAndVerifyWithSharding(
+      self,
+      gtest_filter,
+      total_shards,
+      tests_to_run,
+      args=None,
+      check_exit_0=False,
+  ):
+    """Checks that binary runs correct tests for the given filter and shard.
+
+    Runs all shards of googletest-filter-unittest_ with the given filter, and
+    verifies that the right set of tests were run. The union of tests run
+    on each shard should be identical to tests_to_run, without duplicates.
+    If check_exit_0, .
+
+    Args:
+      gtest_filter: A filter to apply to the tests.
+      total_shards: A total number of shards to split test run into.
+      tests_to_run: A set of tests expected to run.
+      args: Arguments to pass to the to the test binary.
+      check_exit_0: When set to a true value, make sure that all shards return
+        0.
+    """
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # Windows removes empty variables from the environment when passing it
+    # to a new process.  This means it is impossible to pass an empty filter
+    # into a process using the environment variable.  However, we can still
+    # test the case when the variable is not supplied (i.e., gtest_filter is
+    # None).
+    # pylint: disable=g-explicit-bool-comparison
+    if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
+      SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+      partition = []
+      for i in range(0, total_shards):
+        (tests_run, exit_code) = RunWithSharding(total_shards, i, args)
+        if check_exit_0:
+          self.assertEqual(0, exit_code)
+        partition.append(tests_run)
+
+      self.AssertPartitionIsValid(tests_to_run, partition)
+      SetEnvVar(FILTER_ENV_VAR, None)
+    # pylint: enable=g-explicit-bool-comparison
+
+  def RunAndVerifyAllowingDisabled(self, gtest_filter, tests_to_run):
+    """Checks that the binary runs correct set of tests for the given filter.
+
+    Runs googletest-filter-unittest_ with the given filter, and enables
+    disabled tests. Verifies that the right set of tests were run.
+
+    Args:
+      gtest_filter: A filter to apply to the tests.
+      tests_to_run: A set of tests expected to run.
+    """
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # Construct the command line.
+    args = ['--%s' % ALSO_RUN_DISABLED_TESTS_FLAG]
+    if gtest_filter is not None:
+      args.append('--%s=%s' % (FILTER_FLAG, gtest_filter))
+
+    tests_run = RunAndExtractTestList(args)[0]
+    self.AssertSetEqual(tests_run, tests_to_run)
+
+  def setUp(self):
+    """Sets up test case.
+
+    Determines whether value-parameterized tests are enabled in the binary and
+    sets the flags accordingly.
+    """
+
+    global param_tests_present
+    if param_tests_present is None:
+      param_tests_present = (
+          PARAM_TEST_REGEX.search(RunAndReturnOutput()) is not None
+      )
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of not specifying the filter."""
+
+    self.RunAndVerify(None, ACTIVE_TESTS)
+
+  def testDefaultBehaviorWithShards(self):
+    """Tests the behavior without the filter, with sharding enabled."""
+
+    self.RunAndVerifyWithSharding(None, 1, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, 2, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) - 1, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS), ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) + 1, ACTIVE_TESTS)
+
+  def testEmptyFilter(self):
+    """Tests an empty filter."""
+
+    self.RunAndVerify('', [])
+    self.RunAndVerifyWithSharding('', 1, [])
+    self.RunAndVerifyWithSharding('', 2, [])
+
+  def testBadFilter(self):
+    """Tests a filter that matches nothing."""
+
+    self.RunAndVerify('BadFilter', [])
+    self.RunAndVerifyAllowingDisabled('BadFilter', [])
+
+  def testFullName(self):
+    """Tests filtering by full name."""
+
+    self.RunAndVerify('FooTest.Xyz', ['FooTest.Xyz'])
+    self.RunAndVerifyAllowingDisabled('FooTest.Xyz', ['FooTest.Xyz'])
+    self.RunAndVerifyWithSharding('FooTest.Xyz', 5, ['FooTest.Xyz'])
+
+  def testUniversalFilters(self):
+    """Tests filters that match everything."""
+
+    self.RunAndVerify('*', ACTIVE_TESTS)
+    self.RunAndVerify('*.*', ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding('*.*', len(ACTIVE_TESTS) - 3, ACTIVE_TESTS)
+    self.RunAndVerifyAllowingDisabled('*', ACTIVE_TESTS + DISABLED_TESTS)
+    self.RunAndVerifyAllowingDisabled('*.*', ACTIVE_TESTS + DISABLED_TESTS)
+
+  def testFilterByTestCase(self):
+    """Tests filtering by test case name."""
+
+    self.RunAndVerify('FooTest.*', ['FooTest.Abc', 'FooTest.Xyz'])
+
+    BAZ_TESTS = ['BazTest.TestOne', 'BazTest.TestA', 'BazTest.TestB']
+    self.RunAndVerify('BazTest.*', BAZ_TESTS)
+    self.RunAndVerifyAllowingDisabled(
+        'BazTest.*', BAZ_TESTS + ['BazTest.DISABLED_TestC']
+    )
+
+  def testFilterByTest(self):
+    """Tests filtering by test name."""
+
+    self.RunAndVerify('*.TestOne', ['BarTest.TestOne', 'BazTest.TestOne'])
+
+  def testFilterDisabledTests(self):
+    """Select only the disabled tests to run."""
+
+    self.RunAndVerify('DISABLED_FoobarTest.Test1', [])
+    self.RunAndVerifyAllowingDisabled(
+        'DISABLED_FoobarTest.Test1', ['DISABLED_FoobarTest.Test1']
+    )
+
+    self.RunAndVerify('*DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('*DISABLED_*', DISABLED_TESTS)
+
+    self.RunAndVerify('*.DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled(
+        '*.DISABLED_*',
+        [
+            'BarTest.DISABLED_TestFour',
+            'BarTest.DISABLED_TestFive',
+            'BazTest.DISABLED_TestC',
+            'DISABLED_FoobarTest.DISABLED_Test2',
+        ],
+    )
+
+    self.RunAndVerify('DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled(
+        'DISABLED_*',
+        [
+            'DISABLED_FoobarTest.Test1',
+            'DISABLED_FoobarTest.DISABLED_Test2',
+            'DISABLED_FoobarbazTest.TestA',
+        ],
+    )
+
+  def testWildcardInTestCaseName(self):
+    """Tests using wildcard in the test case name."""
+
+    self.RunAndVerify(
+        '*a*.*',
+        [
+            'BarTest.TestOne',
+            'BarTest.TestTwo',
+            'BarTest.TestThree',
+            'BazTest.TestOne',
+            'BazTest.TestA',
+            'BazTest.TestB',
+        ]
+        + DEATH_TESTS
+        + PARAM_TESTS,
+    )
+
+  def testWildcardInTestName(self):
+    """Tests using wildcard in the test name."""
+
+    self.RunAndVerify('*.*A*', ['FooTest.Abc', 'BazTest.TestA'])
+
+  def testFilterWithoutDot(self):
+    """Tests a filter that has no '.' in it."""
+
+    self.RunAndVerify(
+        '*z*',
+        [
+            'FooTest.Xyz',
+            'BazTest.TestOne',
+            'BazTest.TestA',
+            'BazTest.TestB',
+        ],
+    )
+
+  def testTwoPatterns(self):
+    """Tests filters that consist of two patterns."""
+
+    self.RunAndVerify(
+        'Foo*.*:*A*',
+        [
+            'FooTest.Abc',
+            'FooTest.Xyz',
+            'BazTest.TestA',
+        ],
+    )
+
+    # An empty pattern + a non-empty one
+    self.RunAndVerify(':*A*', ['FooTest.Abc', 'BazTest.TestA'])
+
+  def testThreePatterns(self):
+    """Tests filters that consist of three patterns."""
+
+    self.RunAndVerify(
+        '*oo*:*A*:*One',
+        [
+            'FooTest.Abc',
+            'FooTest.Xyz',
+            'BarTest.TestOne',
+            'BazTest.TestOne',
+            'BazTest.TestA',
+        ],
+    )
+
+    # The 2nd pattern is empty.
+    self.RunAndVerify(
+        '*oo*::*One',
+        [
+            'FooTest.Abc',
+            'FooTest.Xyz',
+            'BarTest.TestOne',
+            'BazTest.TestOne',
+        ],
+    )
+
+    # The last 2 patterns are empty.
+    self.RunAndVerify(
+        '*oo*::',
+        [
+            'FooTest.Abc',
+            'FooTest.Xyz',
+        ],
+    )
+
+  def testNegativeFilters(self):
+    self.RunAndVerify(
+        '*-BazTest.TestOne',
+        [
+            'FooTest.Abc',
+            'FooTest.Xyz',
+            'BarTest.TestOne',
+            'BarTest.TestTwo',
+            'BarTest.TestThree',
+            'BazTest.TestA',
+            'BazTest.TestB',
+        ]
+        + DEATH_TESTS
+        + PARAM_TESTS,
+    )
+
+    self.RunAndVerify(
+        '*-FooTest.Abc:BazTest.*',
+        [
+            'FooTest.Xyz',
+            'BarTest.TestOne',
+            'BarTest.TestTwo',
+            'BarTest.TestThree',
+        ]
+        + DEATH_TESTS
+        + PARAM_TESTS,
+    )
+
+    self.RunAndVerify(
+        'BarTest.*-BarTest.TestOne',
+        [
+            'BarTest.TestTwo',
+            'BarTest.TestThree',
+        ],
+    )
+
+    # Tests without leading '*'.
+    self.RunAndVerify(
+        '-FooTest.Abc:FooTest.Xyz:BazTest.*',
+        [
+            'BarTest.TestOne',
+            'BarTest.TestTwo',
+            'BarTest.TestThree',
+        ]
+        + DEATH_TESTS
+        + PARAM_TESTS,
+    )
+
+    # Value parameterized tests.
+    self.RunAndVerify('*/*', PARAM_TESTS)
+
+    # Value parameterized tests filtering by the sequence name.
+    self.RunAndVerify(
+        'SeqP/*',
+        [
+            'SeqP/ParamTest.TestX/0',
+            'SeqP/ParamTest.TestX/1',
+            'SeqP/ParamTest.TestY/0',
+            'SeqP/ParamTest.TestY/1',
+        ],
+    )
+
+    # Value parameterized tests filtering by the test name.
+    self.RunAndVerify(
+        '*/0',
+        [
+            'SeqP/ParamTest.TestX/0',
+            'SeqP/ParamTest.TestY/0',
+            'SeqQ/ParamTest.TestX/0',
+            'SeqQ/ParamTest.TestY/0',
+        ],
+    )
+
+  def testFlagOverridesEnvVar(self):
+    """Tests that the filter flag overrides the filtering env. variable."""
+
+    SetEnvVar(FILTER_ENV_VAR, 'Foo*')
+    args = ['--%s=%s' % (FILTER_FLAG, '*One')]
+    tests_run = RunAndExtractTestList(args)[0]
+    SetEnvVar(FILTER_ENV_VAR, None)
+
+    self.AssertSetEqual(tests_run, ['BarTest.TestOne', 'BazTest.TestOne'])
+
+  def testShardStatusFileIsCreated(self):
+    """Tests that the shard file is created if specified in the environment."""
+
+    shard_status_file = os.path.join(
+        gtest_test_utils.GetTempDir(), 'shard_status_file'
+    )
+    self.assertTrue(not os.path.exists(shard_status_file))
+
+    extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+    try:
+      InvokeWithModifiedEnv(extra_env, RunAndReturnOutput)
+    finally:
+      self.assertTrue(os.path.exists(shard_status_file))
+      os.remove(shard_status_file)
+
+  def testShardStatusFileIsCreatedWithListTests(self):
+    """Tests that the shard file is created with the "list_tests" flag."""
+
+    shard_status_file = os.path.join(
+        gtest_test_utils.GetTempDir(), 'shard_status_file2'
+    )
+    self.assertTrue(not os.path.exists(shard_status_file))
+
+    extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+    try:
+      output = InvokeWithModifiedEnv(
+          extra_env, RunAndReturnOutput, [LIST_TESTS_FLAG]
+      )
+    finally:
+      # This assertion ensures that Google Test enumerated the tests as
+      # opposed to running them.
+      self.assertTrue(
+          '[==========]' not in output,
+          (
+              'Unexpected output during test enumeration.\n'
+              'Please ensure that LIST_TESTS_FLAG is assigned the\n'
+              'correct flag value for listing Google Test tests.'
+          ),
+      )
+
+      self.assertTrue(os.path.exists(shard_status_file))
+      os.remove(shard_status_file)
+
+  def testDisabledBanner(self):
+    """Tests that the disabled banner prints only tests that match filter."""
+    make_filter = lambda s: ['--%s=%s' % (FILTER_FLAG, s)]
+
+    banners = RunAndExtractDisabledBannerList(make_filter('*'))
+    self.AssertSetEqual(
+        banners,
+        [
+            'BarTest.DISABLED_TestFour',
+            'BarTest.DISABLED_TestFive',
+            'BazTest.DISABLED_TestC',
+        ],
+    )
+
+    banners = RunAndExtractDisabledBannerList(make_filter('Bar*'))
+    self.AssertSetEqual(
+        banners, ['BarTest.DISABLED_TestFour', 'BarTest.DISABLED_TestFive']
+    )
+
+    banners = RunAndExtractDisabledBannerList(make_filter('*-Bar*'))
+    self.AssertSetEqual(banners, ['BazTest.DISABLED_TestC'])
+
+  if SUPPORTS_DEATH_TESTS:
+
+    def testShardingWorksWithDeathTests(self):
+      """Tests integration with death tests and sharding."""
+
+      gtest_filter = 'HasDeathTest.*:SeqP/*'
+      expected_tests = [
+          'HasDeathTest.Test1',
+          'HasDeathTest.Test2',
+          'SeqP/ParamTest.TestX/0',
+          'SeqP/ParamTest.TestX/1',
+          'SeqP/ParamTest.TestY/0',
+          'SeqP/ParamTest.TestY/1',
+      ]
+
+      for flag in [
+          '--gtest_death_test_style=threadsafe',
+          '--gtest_death_test_style=fast',
+      ]:
+        self.RunAndVerifyWithSharding(
+            gtest_filter, 3, expected_tests, check_exit_0=True, args=[flag]
+        )
+        self.RunAndVerifyWithSharding(
+            gtest_filter, 5, expected_tests, check_exit_0=True, args=[flag]
+        )
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-filter-unittest_.cc b/3rd-party/googletest/googletest/test/googletest-filter-unittest_.cc
new file mode 100644
index 0000000..bc7aa59
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-filter-unittest_.cc
@@ -0,0 +1,106 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test test filters.
+//
+// A user can specify which test(s) in a Google Test program to run via
+// either the GTEST_FILTER environment variable or the --gtest_filter
+// flag.  This is used for testing such functionality.
+//
+// The program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// Test case FooTest.
+
+class FooTest : public testing::Test {};
+
+TEST_F(FooTest, Abc) {}
+
+TEST_F(FooTest, Xyz) { FAIL() << "Expected failure."; }
+
+// Test case BarTest.
+
+TEST(BarTest, TestOne) {}
+
+TEST(BarTest, TestTwo) {}
+
+TEST(BarTest, TestThree) {}
+
+TEST(BarTest, DISABLED_TestFour) { FAIL() << "Expected failure."; }
+
+TEST(BarTest, DISABLED_TestFive) { FAIL() << "Expected failure."; }
+
+// Test case BazTest.
+
+TEST(BazTest, TestOne) { FAIL() << "Expected failure."; }
+
+TEST(BazTest, TestA) {}
+
+TEST(BazTest, TestB) {}
+
+TEST(BazTest, DISABLED_TestC) { FAIL() << "Expected failure."; }
+
+// Test case HasDeathTest
+
+TEST(HasDeathTest, Test1) { EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*"); }
+
+// We need at least two death tests to make sure that the all death tests
+// aren't on the first shard.
+TEST(HasDeathTest, Test2) { EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*"); }
+
+// Test case FoobarTest
+
+TEST(DISABLED_FoobarTest, Test1) { FAIL() << "Expected failure."; }
+
+TEST(DISABLED_FoobarTest, DISABLED_Test2) { FAIL() << "Expected failure."; }
+
+// Test case FoobarbazTest
+
+TEST(DISABLED_FoobarbazTest, TestA) { FAIL() << "Expected failure."; }
+
+class ParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(ParamTest, TestX) {}
+
+TEST_P(ParamTest, TestY) {}
+
+INSTANTIATE_TEST_SUITE_P(SeqP, ParamTest, testing::Values(1, 2));
+INSTANTIATE_TEST_SUITE_P(SeqQ, ParamTest, testing::Values(5, 6));
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-global-environment-unittest.py b/3rd-party/googletest/googletest/test/googletest-global-environment-unittest.py
new file mode 100644
index 0000000..bd73a2e
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-global-environment-unittest.py
@@ -0,0 +1,141 @@
+# Copyright 2021 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Unit test for Google Test's global test environment behavior.
+
+A user can specify a global test environment via
+testing::AddGlobalTestEnvironment. Failures in the global environment should
+result in all unit tests being skipped.
+
+This script tests such functionality by invoking
+googletest-global-environment-unittest_ (a program written with Google Test).
+"""
+
+import re
+from googletest.test import gtest_test_utils
+
+
+def RunAndReturnOutput(args=None):
+  """Runs the test program and returns its output."""
+
+  return gtest_test_utils.Subprocess(
+      [
+          gtest_test_utils.GetTestExecutablePath(
+              'googletest-global-environment-unittest_'
+          )
+      ]
+      + (args or [])
+  ).output
+
+
+class GTestGlobalEnvironmentUnitTest(gtest_test_utils.TestCase):
+  """Tests global test environment failures."""
+
+  def testEnvironmentSetUpFails(self):
+    """Tests the behavior of not specifying the fail_fast."""
+
+    # Run the test.
+    txt = RunAndReturnOutput()
+
+    # We should see the text of the global environment setup error.
+    self.assertIn('Canned environment setup error', txt)
+
+    # Our test should have been skipped due to the error, and not treated as a
+    # pass.
+    self.assertIn('[  SKIPPED ] 1 test', txt)
+    self.assertIn('[  PASSED  ] 0 tests', txt)
+
+    # The test case shouldn't have been run.
+    self.assertNotIn('Unexpected call', txt)
+
+  def testEnvironmentSetUpAndTornDownForEachRepeat(self):
+    """Tests the behavior of test environments and gtest_repeat."""
+
+    # When --gtest_recreate_environments_when_repeating is true, the global test
+    # environment should be set up and torn down for each iteration.
+    txt = RunAndReturnOutput([
+        '--gtest_repeat=2',
+        '--gtest_recreate_environments_when_repeating=true',
+    ])
+
+    expected_pattern = (
+        '(.|\n)*'
+        r'Repeating all tests \(iteration 1\)'
+        '(.|\n)*'
+        'Global test environment set-up.'
+        '(.|\n)*'
+        'SomeTest.DoesFoo'
+        '(.|\n)*'
+        'Global test environment tear-down'
+        '(.|\n)*'
+        r'Repeating all tests \(iteration 2\)'
+        '(.|\n)*'
+        'Global test environment set-up.'
+        '(.|\n)*'
+        'SomeTest.DoesFoo'
+        '(.|\n)*'
+        'Global test environment tear-down'
+        '(.|\n)*'
+    )
+    self.assertRegex(txt, expected_pattern)
+
+  def testEnvironmentSetUpAndTornDownOnce(self):
+    """Tests environment and --gtest_recreate_environments_when_repeating."""
+
+    # By default the environment should only be set up and torn down once, at
+    # the start and end of the test respectively.
+    txt = RunAndReturnOutput(
+        [
+            '--gtest_repeat=2',
+        ]
+    )
+
+    expected_pattern = (
+        '(.|\n)*'
+        r'Repeating all tests \(iteration 1\)'
+        '(.|\n)*'
+        'Global test environment set-up.'
+        '(.|\n)*'
+        'SomeTest.DoesFoo'
+        '(.|\n)*'
+        r'Repeating all tests \(iteration 2\)'
+        '(.|\n)*'
+        'SomeTest.DoesFoo'
+        '(.|\n)*'
+        'Global test environment tear-down'
+        '(.|\n)*'
+    )
+    self.assertRegex(txt, expected_pattern)
+
+    self.assertEqual(len(re.findall('Global test environment set-up', txt)), 1)
+    self.assertEqual(
+        len(re.findall('Global test environment tear-down', txt)), 1
+    )
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-global-environment-unittest_.cc b/3rd-party/googletest/googletest/test/googletest-global-environment-unittest_.cc
new file mode 100644
index 0000000..f401b2f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-global-environment-unittest_.cc
@@ -0,0 +1,58 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test global test environments.
+//
+// The program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// An environment that always fails in its SetUp method.
+class FailingEnvironment final : public ::testing::Environment {
+ public:
+  void SetUp() override { FAIL() << "Canned environment setup error"; }
+};
+
+// Register the environment.
+auto* const g_environment_ =
+    ::testing::AddGlobalTestEnvironment(new FailingEnvironment);
+
+// A test that doesn't actually run.
+TEST(SomeTest, DoesFoo) { FAIL() << "Unexpected call"; }
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-json-outfiles-test.py b/3rd-party/googletest/googletest/test/googletest-json-outfiles-test.py
new file mode 100644
index 0000000..5626004
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-json-outfiles-test.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+# Copyright 2018, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for the gtest_json_output module."""
+
+import json
+import os
+from googletest.test import gtest_json_test_utils
+from googletest.test import gtest_test_utils
+
+GTEST_OUTPUT_SUBDIR = 'json_outfiles'
+GTEST_OUTPUT_1_TEST = 'gtest_xml_outfile1_test_'
+GTEST_OUTPUT_2_TEST = 'gtest_xml_outfile2_test_'
+
+EXPECTED_1 = {
+    'tests': 1,
+    'failures': 0,
+    'disabled': 0,
+    'errors': 0,
+    'time': '*',
+    'timestamp': '*',
+    'name': 'AllTests',
+    'testsuites': [{
+        'name': 'PropertyOne',
+        'tests': 1,
+        'failures': 0,
+        'disabled': 0,
+        'errors': 0,
+        'time': '*',
+        'timestamp': '*',
+        'testsuite': [{
+            'name': 'TestSomeProperties',
+            'file': 'gtest_xml_outfile1_test_.cc',
+            'line': 41,
+            'status': 'RUN',
+            'result': 'COMPLETED',
+            'time': '*',
+            'timestamp': '*',
+            'classname': 'PropertyOne',
+            'SetUpProp': '1',
+            'TestSomeProperty': '1',
+            'TearDownProp': '1',
+        }],
+    }],
+}
+
+EXPECTED_2 = {
+    'tests': 1,
+    'failures': 0,
+    'disabled': 0,
+    'errors': 0,
+    'time': '*',
+    'timestamp': '*',
+    'name': 'AllTests',
+    'testsuites': [{
+        'name': 'PropertyTwo',
+        'tests': 1,
+        'failures': 0,
+        'disabled': 0,
+        'errors': 0,
+        'time': '*',
+        'timestamp': '*',
+        'testsuite': [{
+            'name': 'TestInt64ConvertibleProperties',
+            'file': 'gtest_xml_outfile2_test_.cc',
+            'line': 43,
+            'status': 'RUN',
+            'result': 'COMPLETED',
+            'timestamp': '*',
+            'time': '*',
+            'classname': 'PropertyTwo',
+            'SetUpProp': '2',
+            'TestFloatProperty': '3.25',
+            'TestDoubleProperty': '4.75',
+            'TestSizetProperty': '5',
+            'TestBoolProperty': 'true',
+            'TestCharProperty': 'A',
+            'TestInt16Property': '6',
+            'TestInt32Property': '7',
+            'TestInt64Property': '8',
+            'TestEnumProperty': '9',
+            'TestAtomicIntProperty': '10',
+            'TearDownProp': '2',
+        }],
+    }],
+}
+
+
+class GTestJsonOutFilesTest(gtest_test_utils.TestCase):
+  """Unit test for Google Test's JSON output functionality."""
+
+  def setUp(self):
+    # We want the trailing '/' that the last "" provides in os.path.join, for
+    # telling Google Test to create an output directory instead of a single file
+    # for xml output.
+    self.output_dir_ = os.path.join(
+        gtest_test_utils.GetTempDir(), GTEST_OUTPUT_SUBDIR, ''
+    )
+    self.DeleteFilesAndDir()
+
+  def tearDown(self):
+    self.DeleteFilesAndDir()
+
+  def DeleteFilesAndDir(self):
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + '.json'))
+    except os.error:
+      pass
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + '.json'))
+    except os.error:
+      pass
+    try:
+      os.rmdir(self.output_dir_)
+    except os.error:
+      pass
+
+  def testOutfile1(self):
+    self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_1)
+
+  def testOutfile2(self):
+    self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_2)
+
+  def _TestOutFile(self, test_name, expected):
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
+    command = [gtest_prog_path, '--gtest_output=json:%s' % self.output_dir_]
+    p = gtest_test_utils.Subprocess(
+        command, working_dir=gtest_test_utils.GetTempDir()
+    )
+    self.assertTrue(p.exited)
+    self.assertEqual(0, p.exit_code)
+
+    output_file_name1 = test_name + '.json'
+    output_file1 = os.path.join(self.output_dir_, output_file_name1)
+    output_file_name2 = 'lt-' + output_file_name1
+    output_file2 = os.path.join(self.output_dir_, output_file_name2)
+    self.assertTrue(
+        os.path.isfile(output_file1) or os.path.isfile(output_file2),
+        output_file1,
+    )
+
+    if os.path.isfile(output_file1):
+      with open(output_file1) as f:
+        actual = json.load(f)
+    else:
+      with open(output_file2) as f:
+        actual = json.load(f)
+    self.assertEqual(expected, gtest_json_test_utils.normalize(actual))
+
+
+if __name__ == '__main__':
+  os.environ['GTEST_STACK_TRACE_DEPTH'] = '0'
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-json-output-unittest.py b/3rd-party/googletest/googletest/test/googletest-json-output-unittest.py
new file mode 100644
index 0000000..d3338e3
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-json-output-unittest.py
@@ -0,0 +1,835 @@
+#!/usr/bin/env python
+# Copyright 2018, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for the gtest_json_output module."""
+
+import datetime
+import errno
+import json
+import os
+import re
+import sys
+
+from googletest.test import gtest_json_test_utils
+from googletest.test import gtest_test_utils
+
+GTEST_FILTER_FLAG = '--gtest_filter'
+GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
+GTEST_OUTPUT_FLAG = '--gtest_output'
+GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.json'
+GTEST_PROGRAM_NAME = 'gtest_xml_output_unittest_'
+
+# The flag indicating stacktraces are not supported
+NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support'
+
+SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv
+
+if SUPPORTS_STACK_TRACES:
+  STACK_TRACE_TEMPLATE = '\nStack trace:\n*'
+else:
+  STACK_TRACE_TEMPLATE = '\n'
+
+EXPECTED_NON_EMPTY = {
+    'tests': 26,
+    'failures': 5,
+    'disabled': 2,
+    'errors': 0,
+    'timestamp': '*',
+    'time': '*',
+    'ad_hoc_property': '42',
+    'name': 'AllTests',
+    'testsuites': [
+        {
+            'name': 'SuccessfulTest',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'Succeeds',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 53,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'SuccessfulTest',
+            }],
+        },
+        {
+            'name': 'FailedTest',
+            'tests': 1,
+            'failures': 1,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'Fails',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 61,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'FailedTest',
+                'failures': [{
+                    'failure': (
+                        'gtest_xml_output_unittest_.cc:*\n'
+                        'Expected equality of these values:\n'
+                        '  1\n  2'
+                        + STACK_TRACE_TEMPLATE
+                    ),
+                    'type': '',
+                }],
+            }],
+        },
+        {
+            'name': 'DisabledTest',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 1,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'DISABLED_test_not_run',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 68,
+                'status': 'NOTRUN',
+                'result': 'SUPPRESSED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'DisabledTest',
+            }],
+        },
+        {
+            'name': 'SkippedTest',
+            'tests': 3,
+            'failures': 1,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [
+                {
+                    'name': 'Skipped',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 75,
+                    'status': 'RUN',
+                    'result': 'SKIPPED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'SkippedTest',
+                    'skipped': [
+                        {'message': 'gtest_xml_output_unittest_.cc:*\n\n'}
+                    ],
+                },
+                {
+                    'name': 'SkippedWithMessage',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 79,
+                    'status': 'RUN',
+                    'result': 'SKIPPED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'SkippedTest',
+                    'skipped': [{
+                        'message': (
+                            'gtest_xml_output_unittest_.cc:*\n'
+                            'It is good practice to tell why you skip a test.\n'
+                        )
+                    }],
+                },
+                {
+                    'name': 'SkippedAfterFailure',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 83,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'SkippedTest',
+                    'failures': [{
+                        'failure': (
+                            'gtest_xml_output_unittest_.cc:*\n'
+                            'Expected equality of these values:\n'
+                            '  1\n  2'
+                            + STACK_TRACE_TEMPLATE
+                        ),
+                        'type': '',
+                    }],
+                    'skipped': [{
+                        'message': (
+                            'gtest_xml_output_unittest_.cc:*\n'
+                            'It is good practice to tell why you skip a test.\n'
+                        )
+                    }],
+                },
+            ],
+        },
+        {
+            'name': 'MixedResultTest',
+            'tests': 3,
+            'failures': 1,
+            'disabled': 1,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [
+                {
+                    'name': 'Succeeds',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 88,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'MixedResultTest',
+                },
+                {
+                    'name': 'Fails',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 93,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'MixedResultTest',
+                    'failures': [
+                        {
+                            'failure': (
+                                'gtest_xml_output_unittest_.cc:*\n'
+                                'Expected equality of these values:\n'
+                                '  1\n  2'
+                                + STACK_TRACE_TEMPLATE
+                            ),
+                            'type': '',
+                        },
+                        {
+                            'failure': (
+                                'gtest_xml_output_unittest_.cc:*\n'
+                                'Expected equality of these values:\n'
+                                '  2\n  3'
+                                + STACK_TRACE_TEMPLATE
+                            ),
+                            'type': '',
+                        },
+                    ],
+                },
+                {
+                    'name': 'DISABLED_test',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 98,
+                    'status': 'NOTRUN',
+                    'result': 'SUPPRESSED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'MixedResultTest',
+                },
+            ],
+        },
+        {
+            'name': 'XmlQuotingTest',
+            'tests': 1,
+            'failures': 1,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'OutputsCData',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 102,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'XmlQuotingTest',
+                'failures': [{
+                    'failure': (
+                        'gtest_xml_output_unittest_.cc:*\n'
+                        'Failed\nXML output: <?xml encoding="utf-8">'
+                        '<top><![CDATA[cdata text]]></top>'
+                        + STACK_TRACE_TEMPLATE
+                    ),
+                    'type': '',
+                }],
+            }],
+        },
+        {
+            'name': 'InvalidCharactersTest',
+            'tests': 1,
+            'failures': 1,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'InvalidCharactersInMessage',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 109,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'InvalidCharactersTest',
+                'failures': [{
+                    'failure': (
+                        'gtest_xml_output_unittest_.cc:*\n'
+                        'Failed\nInvalid characters in brackets'
+                        ' [\x01\x02]'
+                        + STACK_TRACE_TEMPLATE
+                    ),
+                    'type': '',
+                }],
+            }],
+        },
+        {
+            'name': 'PropertyRecordingTest',
+            'tests': 4,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'SetUpTestSuite': 'yes',
+            'TearDownTestSuite': 'aye',
+            'testsuite': [
+                {
+                    'name': 'OneProperty',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 121,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'PropertyRecordingTest',
+                    'key_1': '1',
+                },
+                {
+                    'name': 'IntValuedProperty',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 125,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'PropertyRecordingTest',
+                    'key_int': '1',
+                },
+                {
+                    'name': 'ThreeProperties',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 129,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'PropertyRecordingTest',
+                    'key_1': '1',
+                    'key_2': '2',
+                    'key_3': '3',
+                },
+                {
+                    'name': 'TwoValuesForOneKeyUsesLastValue',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 135,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'PropertyRecordingTest',
+                    'key_1': '2',
+                },
+            ],
+        },
+        {
+            'name': 'NoFixtureTest',
+            'tests': 3,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [
+                {
+                    'name': 'RecordProperty',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 140,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'NoFixtureTest',
+                    'key': '1',
+                },
+                {
+                    'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 153,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'NoFixtureTest',
+                    'key_for_utility_int': '1',
+                },
+                {
+                    'name': (
+                        'ExternalUtilityThatCallsRecordStringValuedProperty'
+                    ),
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 157,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'NoFixtureTest',
+                    'key_for_utility_string': '1',
+                },
+            ],
+        },
+        {
+            'name': 'TypedTest/0',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'HasTypeParamAttribute',
+                'type_param': 'int',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 173,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'TypedTest/0',
+            }],
+        },
+        {
+            'name': 'TypedTest/1',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'HasTypeParamAttribute',
+                'type_param': 'long',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 173,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'TypedTest/1',
+            }],
+        },
+        {
+            'name': 'Single/TypeParameterizedTestSuite/0',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'HasTypeParamAttribute',
+                'type_param': 'int',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 180,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'Single/TypeParameterizedTestSuite/0',
+            }],
+        },
+        {
+            'name': 'Single/TypeParameterizedTestSuite/1',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [{
+                'name': 'HasTypeParamAttribute',
+                'type_param': 'long',
+                'file': 'gtest_xml_output_unittest_.cc',
+                'line': 180,
+                'status': 'RUN',
+                'result': 'COMPLETED',
+                'time': '*',
+                'timestamp': '*',
+                'classname': 'Single/TypeParameterizedTestSuite/1',
+            }],
+        },
+        {
+            'name': 'Single/ValueParamTest',
+            'tests': 4,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [
+                {
+                    'name': 'HasValueParamAttribute/0',
+                    'value_param': '33',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 164,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'Single/ValueParamTest',
+                },
+                {
+                    'name': 'HasValueParamAttribute/1',
+                    'value_param': '42',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 164,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'Single/ValueParamTest',
+                },
+                {
+                    'name': 'AnotherTestThatHasValueParamAttribute/0',
+                    'value_param': '33',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 165,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'Single/ValueParamTest',
+                },
+                {
+                    'name': 'AnotherTestThatHasValueParamAttribute/1',
+                    'value_param': '42',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 165,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'time': '*',
+                    'timestamp': '*',
+                    'classname': 'Single/ValueParamTest',
+                },
+            ],
+        },
+    ],
+}
+
+EXPECTED_FILTERED = {
+    'tests': 1,
+    'failures': 0,
+    'disabled': 0,
+    'errors': 0,
+    'time': '*',
+    'timestamp': '*',
+    'name': 'AllTests',
+    'ad_hoc_property': '42',
+    'testsuites': [{
+        'name': 'SuccessfulTest',
+        'tests': 1,
+        'failures': 0,
+        'disabled': 0,
+        'errors': 0,
+        'time': '*',
+        'timestamp': '*',
+        'testsuite': [{
+            'name': 'Succeeds',
+            'file': 'gtest_xml_output_unittest_.cc',
+            'line': 53,
+            'status': 'RUN',
+            'result': 'COMPLETED',
+            'time': '*',
+            'timestamp': '*',
+            'classname': 'SuccessfulTest',
+        }],
+    }],
+}
+
+EXPECTED_NO_TEST = {
+    'tests': 0,
+    'failures': 0,
+    'disabled': 0,
+    'errors': 0,
+    'time': '*',
+    'timestamp': '*',
+    'name': 'AllTests',
+    'testsuites': [{
+        'name': 'NonTestSuiteFailure',
+        'tests': 1,
+        'failures': 1,
+        'disabled': 0,
+        'skipped': 0,
+        'errors': 0,
+        'time': '*',
+        'timestamp': '*',
+        'testsuite': [{
+            'name': '',
+            'status': 'RUN',
+            'result': 'COMPLETED',
+            'time': '*',
+            'timestamp': '*',
+            'classname': '',
+            'failures': [{
+                'failure': (
+                    'gtest_no_test_unittest.cc:*\n'
+                    'Expected equality of these values:\n'
+                    '  1\n  2'
+                    + STACK_TRACE_TEMPLATE
+                ),
+                'type': '',
+            }],
+        }],
+    }],
+}
+
+GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
+
+SUPPORTS_TYPED_TESTS = (
+    'TypedTest'
+    in gtest_test_utils.Subprocess(
+        [GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False
+    ).output
+)
+
+
+class GTestJsonOutputUnitTest(gtest_test_utils.TestCase):
+  """Unit test for Google Test's JSON output functionality."""
+
+  # This test currently breaks on platforms that do not support typed and
+  # type-parameterized tests, so we don't run it under them.
+  if SUPPORTS_TYPED_TESTS:
+
+    def testNonEmptyJsonOutput(self):
+      """Verifies JSON output for a Google Test binary with non-empty output.
+
+      Runs a test program that generates a non-empty JSON output, and
+      tests that the JSON output is expected.
+      """
+      self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY, 1)
+
+  def testNoTestJsonOutput(self):
+    """Verifies JSON output for a Google Test binary without actual tests.
+
+    Runs a test program that generates an JSON output for a binary with no
+    tests, and tests that the JSON output is expected.
+    """
+
+    self._TestJsonOutput('gtest_no_test_unittest', EXPECTED_NO_TEST, 0)
+
+  def testTimestampValue(self):
+    """Checks whether the timestamp attribute in the JSON output is valid.
+
+    Runs a test program that generates an empty JSON output, and checks if
+    the timestamp attribute in the testsuites tag is valid.
+    """
+    actual = self._GetJsonOutput('gtest_no_test_unittest', [], 0)
+    date_time_str = actual['timestamp']
+    # datetime.strptime() is only available in Python 2.5+ so we have to
+    # parse the expected datetime manually.
+    match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str)
+    self.assertTrue(
+        re.match,
+        'JSON datettime string %s has incorrect format' % date_time_str,
+    )
+    date_time_from_json = datetime.datetime(
+        year=int(match.group(1)),
+        month=int(match.group(2)),
+        day=int(match.group(3)),
+        hour=int(match.group(4)),
+        minute=int(match.group(5)),
+        second=int(match.group(6)),
+    )
+
+    time_delta = abs(datetime.datetime.now() - date_time_from_json)
+    # timestamp value should be near the current local time
+    self.assertTrue(
+        time_delta < datetime.timedelta(seconds=600),
+        'time_delta is %s' % time_delta,
+    )
+
+  def testDefaultOutputFile(self):
+    """Verifies the default output file name.
+
+    Confirms that Google Test produces an JSON output file with the expected
+    default name if no name is explicitly specified.
+    """
+    output_file = os.path.join(
+        gtest_test_utils.GetTempDir(), GTEST_DEFAULT_OUTPUT_FILE
+    )
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
+        'gtest_no_test_unittest'
+    )
+    try:
+      os.remove(output_file)
+    except OSError:
+      e = sys.exc_info()[1]
+      if e.errno != errno.ENOENT:
+        raise
+
+    p = gtest_test_utils.Subprocess(
+        [gtest_prog_path, '%s=json' % GTEST_OUTPUT_FLAG],
+        working_dir=gtest_test_utils.GetTempDir(),
+    )
+    self.assertTrue(p.exited)
+    self.assertEqual(0, p.exit_code)
+    self.assertTrue(os.path.isfile(output_file))
+
+  def testSuppressedJsonOutput(self):
+    """Verifies that no JSON output is generated.
+
+    Tests that no JSON file is generated if the default JSON listener is
+    shut down before RUN_ALL_TESTS is invoked.
+    """
+
+    json_path = os.path.join(
+        gtest_test_utils.GetTempDir(), GTEST_PROGRAM_NAME + 'out.json'
+    )
+    if os.path.isfile(json_path):
+      os.remove(json_path)
+
+    command = [
+        GTEST_PROGRAM_PATH,
+        '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path),
+        '--shut_down_xml',
+    ]
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      # p.signal is available only if p.terminated_by_signal is True.
+      self.assertFalse(
+          p.terminated_by_signal,
+          '%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal),
+      )
+    else:
+      self.assertTrue(p.exited)
+      self.assertEqual(
+          1,
+          p.exit_code,
+          "'%s' exited with code %s, which doesn't match "
+          'the expected exit code %s.' % (command, p.exit_code, 1),
+      )
+
+    self.assertTrue(not os.path.isfile(json_path))
+
+  def testFilteredTestJsonOutput(self):
+    """Verifies JSON output when a filter is applied.
+
+    Runs a test program that executes only some tests and verifies that
+    non-selected tests do not show up in the JSON output.
+    """
+
+    self._TestJsonOutput(
+        GTEST_PROGRAM_NAME,
+        EXPECTED_FILTERED,
+        0,
+        extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG],
+    )
+
+  def _GetJsonOutput(self, gtest_prog_name, extra_args, expected_exit_code):
+    """Returns the JSON output generated by running the program gtest_prog_name.
+
+    Furthermore, the program's exit code must be expected_exit_code.
+
+    Args:
+      gtest_prog_name: Google Test binary name.
+      extra_args: extra arguments to binary invocation.
+      expected_exit_code: program's exit code.
+    """
+    json_path = os.path.join(
+        gtest_test_utils.GetTempDir(), gtest_prog_name + 'out.json'
+    )
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
+
+    command = [
+        gtest_prog_path,
+        '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path),
+    ] + extra_args
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      self.assertTrue(
+          False, '%s was killed by signal %d' % (gtest_prog_name, p.signal)
+      )
+    else:
+      self.assertTrue(p.exited)
+      self.assertEqual(
+          expected_exit_code,
+          p.exit_code,
+          "'%s' exited with code %s, which doesn't match "
+          'the expected exit code %s.'
+          % (command, p.exit_code, expected_exit_code),
+      )
+    with open(json_path) as f:
+      actual = json.load(f)
+    return actual
+
+  def _TestJsonOutput(
+      self, gtest_prog_name, expected, expected_exit_code, extra_args=None
+  ):
+    """Checks the JSON output generated by the Google Test binary.
+
+    Asserts that the JSON document generated by running the program
+    gtest_prog_name matches expected_json, a string containing another
+    JSON document.  Furthermore, the program's exit code must be
+    expected_exit_code.
+
+    Args:
+      gtest_prog_name: Google Test binary name.
+      expected: expected output.
+      expected_exit_code: program's exit code.
+      extra_args: extra arguments to binary invocation.
+    """
+
+    actual = self._GetJsonOutput(
+        gtest_prog_name, extra_args or [], expected_exit_code
+    )
+    self.assertEqual(expected, gtest_json_test_utils.normalize(actual))
+
+
+if __name__ == '__main__':
+  if NO_STACKTRACE_SUPPORT_FLAG in sys.argv:
+    # unittest.main() can't handle unknown flags
+    sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
+
+  os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-list-tests-unittest.py b/3rd-party/googletest/googletest/test/googletest-list-tests-unittest.py
new file mode 100755
index 0000000..977e57f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-list-tests-unittest.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test's --gtest_list_tests flag.
+
+A user can ask Google Test to list all tests by specifying the
+--gtest_list_tests flag.  This script tests such functionality
+by invoking googletest-list-tests-unittest_ (a program written with
+Google Test) the command line flags.
+"""
+
+import re
+from googletest.test import gtest_test_utils
+
+# Constants.
+
+# The command line flag for enabling/disabling listing all tests.
+LIST_TESTS_FLAG = 'gtest_list_tests'
+
+# Path to the googletest-list-tests-unittest_ program.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'googletest-list-tests-unittest_'
+)
+
+# The expected output when running googletest-list-tests-unittest_ with
+# --gtest_list_tests
+EXPECTED_OUTPUT_NO_FILTER_RE = re.compile(
+    r"""FooDeathTest\.
+  Test1
+Foo\.
+  Bar1
+  Bar2
+  DISABLED_Bar3
+Abc\.
+  Xyz
+  Def
+FooBar\.
+  Baz
+FooTest\.
+  Test1
+  DISABLED_Test2
+  Test3
+TypedTest/0\.  # TypeParam = (VeryLo{245}|class VeryLo{239})\.\.\.
+  TestA
+  TestB
+TypedTest/1\.  # TypeParam = int\s*\*( __ptr64)?
+  TestA
+  TestB
+TypedTest/2\.  # TypeParam = .*MyArray<bool,\s*42>
+  TestA
+  TestB
+My/TypeParamTest/0\.  # TypeParam = (VeryLo{245}|class VeryLo{239})\.\.\.
+  TestA
+  TestB
+My/TypeParamTest/1\.  # TypeParam = int\s*\*( __ptr64)?
+  TestA
+  TestB
+My/TypeParamTest/2\.  # TypeParam = .*MyArray<bool,\s*42>
+  TestA
+  TestB
+MyInstantiation/ValueParamTest\.
+  TestA/0  # GetParam\(\) = one line
+  TestA/1  # GetParam\(\) = two\\nlines
+  TestA/2  # GetParam\(\) = a very\\nlo{241}\.\.\.
+  TestB/0  # GetParam\(\) = one line
+  TestB/1  # GetParam\(\) = two\\nlines
+  TestB/2  # GetParam\(\) = a very\\nlo{241}\.\.\.
+"""
+)
+
+# The expected output when running googletest-list-tests-unittest_ with
+# --gtest_list_tests and --gtest_filter=Foo*.
+EXPECTED_OUTPUT_FILTER_FOO_RE = re.compile(
+    r"""FooDeathTest\.
+  Test1
+Foo\.
+  Bar1
+  Bar2
+  DISABLED_Bar3
+FooBar\.
+  Baz
+FooTest\.
+  Test1
+  DISABLED_Test2
+  Test3
+"""
+)
+
+# Utilities.
+
+
+def Run(args):
+  """Runs googletest-list-tests-unittest_ and returns the list of tests printed."""
+
+  return gtest_test_utils.Subprocess(
+      [EXE_PATH] + args, capture_stderr=False
+  ).output
+
+
+# The unit test.
+
+
+class GTestListTestsUnitTest(gtest_test_utils.TestCase):
+  """Tests using the --gtest_list_tests flag to list all tests."""
+
+  def RunAndVerify(self, flag_value, expected_output_re, other_flag):
+    """Run googletest-list-tests-unittest_ and verify the output.
+
+    Runs googletest-list-tests-unittest_ and verifies that it prints
+    the correct tests.
+
+    Args:
+      flag_value:         value of the --gtest_list_tests flag; None if the flag
+        should not be present.
+      expected_output_re: regular expression that matches the expected output
+        after running command;
+      other_flag:         a different flag to be passed to command along with
+        gtest_list_tests; None if the flag should not be present.
+    """
+
+    if flag_value is None:
+      flag = ''
+      flag_expression = 'not set'
+    elif flag_value == '0':
+      flag = '--%s=0' % LIST_TESTS_FLAG
+      flag_expression = '0'
+    else:
+      flag = '--%s' % LIST_TESTS_FLAG
+      flag_expression = '1'
+
+    args = [flag]
+
+    if other_flag is not None:
+      args += [other_flag]
+
+    output = Run(args)
+
+    if expected_output_re:
+      self.assertTrue(
+          expected_output_re.match(output),
+          'when %s is %s, the output of "%s" is "%s",\n'
+          'which does not match regex "%s"'
+          % (
+              LIST_TESTS_FLAG,
+              flag_expression,
+              ' '.join(args),
+              output,
+              expected_output_re.pattern,
+          ),
+      )
+    else:
+      self.assertTrue(
+          not EXPECTED_OUTPUT_NO_FILTER_RE.match(output),
+          'when %s is %s, the output of "%s" is "%s"'
+          % (LIST_TESTS_FLAG, flag_expression, ' '.join(args), output),
+      )
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(flag_value=None, expected_output_re=None, other_flag=None)
+
+  def testFlag(self):
+    """Tests using the --gtest_list_tests flag."""
+
+    self.RunAndVerify(flag_value='0', expected_output_re=None, other_flag=None)
+    self.RunAndVerify(
+        flag_value='1',
+        expected_output_re=EXPECTED_OUTPUT_NO_FILTER_RE,
+        other_flag=None,
+    )
+
+  def testOverrideNonFilterFlags(self):
+    """Tests that --gtest_list_tests overrides the non-filter flags."""
+
+    self.RunAndVerify(
+        flag_value='1',
+        expected_output_re=EXPECTED_OUTPUT_NO_FILTER_RE,
+        other_flag='--gtest_break_on_failure',
+    )
+
+  def testWithFilterFlags(self):
+    """Tests that --gtest_list_tests takes into account the filter flags.
+
+    Tests that --gtest_list_tests takes into account the
+    --gtest_filter flag.
+    """
+
+    self.RunAndVerify(
+        flag_value='1',
+        expected_output_re=EXPECTED_OUTPUT_FILTER_FOO_RE,
+        other_flag='--gtest_filter=Foo*',
+    )
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-list-tests-unittest_.cc b/3rd-party/googletest/googletest/test/googletest-list-tests-unittest_.cc
new file mode 100644
index 0000000..a1ea6cf
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-list-tests-unittest_.cc
@@ -0,0 +1,143 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test's --gtest_list_tests flag.
+//
+// A user can ask Google Test to list all tests that will run
+// so that when using a filter, a user will know what
+// tests to look for. The tests will not be run after listing.
+//
+// This program will be invoked from a Python unit test.
+// Don't run it directly.
+
+#include <ostream>
+#include <string>
+
+#include "gtest/gtest.h"
+
+// Several different test cases and tests that will be listed.
+TEST(Foo, Bar1) {}
+
+TEST(Foo, Bar2) {}
+
+TEST(Foo, DISABLED_Bar3) {}
+
+TEST(Abc, Xyz) {}
+
+TEST(Abc, Def) {}
+
+TEST(FooBar, Baz) {}
+
+class FooTest : public testing::Test {};
+
+TEST_F(FooTest, Test1) {}
+
+TEST_F(FooTest, DISABLED_Test2) {}
+
+TEST_F(FooTest, Test3) {}
+
+TEST(FooDeathTest, Test1) {}
+
+// A group of value-parameterized tests.
+
+class MyType {
+ public:
+  explicit MyType(const std::string& a_value) : value_(a_value) {}
+
+  const std::string& value() const { return value_; }
+
+ private:
+  std::string value_;
+};
+
+// Teaches Google Test how to print a MyType.
+void PrintTo(const MyType& x, std::ostream* os) { *os << x.value(); }
+
+class ValueParamTest : public testing::TestWithParam<MyType> {};
+
+TEST_P(ValueParamTest, TestA) {}
+
+TEST_P(ValueParamTest, TestB) {}
+
+INSTANTIATE_TEST_SUITE_P(
+    MyInstantiation, ValueParamTest,
+    testing::Values(
+        MyType("one line"), MyType("two\nlines"),
+        MyType("a "
+               "very\nloooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
+               "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
+               "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
+               "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
+               "ooooong line")));  // NOLINT
+
+// A group of typed tests.
+
+// A deliberately long type name for testing the line-truncating
+// behavior when printing a type parameter.
+class
+    VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName {  // NOLINT
+};
+
+template <typename T>
+class TypedTest : public testing::Test {};
+
+template <typename T, int kSize>
+class MyArray {};
+
+typedef testing::Types<
+    VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName,  // NOLINT
+    int*, MyArray<bool, 42> >
+    MyTypes;
+
+TYPED_TEST_SUITE(TypedTest, MyTypes);
+
+TYPED_TEST(TypedTest, TestA) {}
+
+TYPED_TEST(TypedTest, TestB) {}
+
+// A group of type-parameterized tests.
+
+template <typename T>
+class TypeParamTest : public testing::Test {};
+
+TYPED_TEST_SUITE_P(TypeParamTest);
+
+TYPED_TEST_P(TypeParamTest, TestA) {}
+
+TYPED_TEST_P(TypeParamTest, TestB) {}
+
+REGISTER_TYPED_TEST_SUITE_P(TypeParamTest, TestA, TestB);
+
+INSTANTIATE_TYPED_TEST_SUITE_P(My, TypeParamTest, MyTypes);
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-listener-test.cc b/3rd-party/googletest/googletest/test/googletest-listener-test.cc
new file mode 100644
index 0000000..d7c47c2
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-listener-test.cc
@@ -0,0 +1,509 @@
+// Copyright 2009 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file verifies Google Test event listeners receive events at the
+// right times.
+
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "gtest/internal/custom/gtest.h"
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::InitGoogleTest;
+using ::testing::UnitTest;
+
+// Used by tests to register their events.
+std::vector<std::string>* g_events = nullptr;
+
+namespace testing {
+namespace internal {
+
+class EventRecordingListener : public TestEventListener {
+ public:
+  explicit EventRecordingListener(const char* name) : name_(name) {}
+
+ protected:
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnTestProgramStart"));
+  }
+
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int iteration) override {
+    Message message;
+    message << GetFullMethodName("OnTestIterationStart") << "(" << iteration
+            << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
+  }
+
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
+  }
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& /*test_case*/) override {
+    g_events->push_back(GetFullMethodName("OnTestCaseStart"));
+  }
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnTestStart(const TestInfo& /*test_info*/) override {
+    g_events->push_back(GetFullMethodName("OnTestStart"));
+  }
+
+  void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {
+    g_events->push_back(GetFullMethodName("OnTestPartResult"));
+  }
+
+  void OnTestEnd(const TestInfo& /*test_info*/) override {
+    g_events->push_back(GetFullMethodName("OnTestEnd"));
+  }
+
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& /*test_case*/) override {
+    g_events->push_back(GetFullMethodName("OnTestCaseEnd"));
+  }
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
+  }
+
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
+  }
+
+  void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                          int iteration) override {
+    Message message;
+    message << GetFullMethodName("OnTestIterationEnd") << "(" << iteration
+            << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
+  }
+
+ private:
+  std::string GetFullMethodName(const char* name) { return name_ + "." + name; }
+
+  std::string name_;
+};
+
+// This listener is using OnTestSuiteStart, OnTestSuiteEnd API
+class EventRecordingListener2 : public TestEventListener {
+ public:
+  explicit EventRecordingListener2(const char* name) : name_(name) {}
+
+ protected:
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnTestProgramStart"));
+  }
+
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int iteration) override {
+    Message message;
+    message << GetFullMethodName("OnTestIterationStart") << "(" << iteration
+            << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
+  }
+
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
+  }
+
+  void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {
+    g_events->push_back(GetFullMethodName("OnTestSuiteStart"));
+  }
+
+  void OnTestStart(const TestInfo& /*test_info*/) override {
+    g_events->push_back(GetFullMethodName("OnTestStart"));
+  }
+
+  void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {
+    g_events->push_back(GetFullMethodName("OnTestPartResult"));
+  }
+
+  void OnTestEnd(const TestInfo& /*test_info*/) override {
+    g_events->push_back(GetFullMethodName("OnTestEnd"));
+  }
+
+  void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {
+    g_events->push_back(GetFullMethodName("OnTestSuiteEnd"));
+  }
+
+  void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
+  }
+
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
+  }
+
+  void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                          int iteration) override {
+    Message message;
+    message << GetFullMethodName("OnTestIterationEnd") << "(" << iteration
+            << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {
+    g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
+  }
+
+ private:
+  std::string GetFullMethodName(const char* name) { return name_ + "." + name; }
+
+  std::string name_;
+};
+
+class EnvironmentInvocationCatcher : public Environment {
+ protected:
+  void SetUp() override { g_events->push_back("Environment::SetUp"); }
+
+  void TearDown() override { g_events->push_back("Environment::TearDown"); }
+};
+
+class ListenerTest : public Test {
+ protected:
+  static void SetUpTestSuite() {
+    g_events->push_back("ListenerTest::SetUpTestSuite");
+  }
+
+  static void TearDownTestSuite() {
+    g_events->push_back("ListenerTest::TearDownTestSuite");
+  }
+
+  void SetUp() override { g_events->push_back("ListenerTest::SetUp"); }
+
+  void TearDown() override { g_events->push_back("ListenerTest::TearDown"); }
+};
+
+TEST_F(ListenerTest, DoesFoo) {
+  // Test execution order within a test case is not guaranteed so we are not
+  // recording the test name.
+  g_events->push_back("ListenerTest::* Test Body");
+  SUCCEED();  // Triggers OnTestPartResult.
+}
+
+TEST_F(ListenerTest, DoesBar) {
+  g_events->push_back("ListenerTest::* Test Body");
+  SUCCEED();  // Triggers OnTestPartResult.
+}
+
+}  // namespace internal
+
+}  // namespace testing
+
+using ::testing::internal::EnvironmentInvocationCatcher;
+using ::testing::internal::EventRecordingListener;
+using ::testing::internal::EventRecordingListener2;
+
+void VerifyResults(const std::vector<std::string>& data,
+                   const char* const* expected_data,
+                   size_t expected_data_size) {
+  const size_t actual_size = data.size();
+  // If the following assertion fails, a new entry will be appended to
+  // data.  Hence we save data.size() first.
+  EXPECT_EQ(expected_data_size, actual_size);
+
+  // Compares the common prefix.
+  const size_t shorter_size =
+      expected_data_size <= actual_size ? expected_data_size : actual_size;
+  size_t i = 0;
+  for (; i < shorter_size; ++i) {
+    ASSERT_STREQ(expected_data[i], data[i].c_str()) << "at position " << i;
+  }
+
+  // Prints extra elements in the actual data.
+  for (; i < actual_size; ++i) {
+    printf("  Actual event #%lu: %s\n", static_cast<unsigned long>(i),
+           data[i].c_str());
+  }
+}
+
+int main(int argc, char** argv) {
+  std::vector<std::string> events;
+  g_events = &events;
+  InitGoogleTest(&argc, argv);
+
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener("1st"));
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener("2nd"));
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener2("3rd"));
+
+  AddGlobalTestEnvironment(new EnvironmentInvocationCatcher);
+
+  GTEST_CHECK_(events.empty())
+      << "AddGlobalTestEnvironment should not generate any events itself.";
+
+  GTEST_FLAG_SET(repeat, 2);
+  GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+  int ret_val = RUN_ALL_TESTS();
+
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // The deprecated OnTestSuiteStart/OnTestCaseStart events are included
+  const char* const expected_events[] = {"1st.OnTestProgramStart",
+                                         "2nd.OnTestProgramStart",
+                                         "3rd.OnTestProgramStart",
+                                         "1st.OnTestIterationStart(0)",
+                                         "2nd.OnTestIterationStart(0)",
+                                         "3rd.OnTestIterationStart(0)",
+                                         "1st.OnEnvironmentsSetUpStart",
+                                         "2nd.OnEnvironmentsSetUpStart",
+                                         "3rd.OnEnvironmentsSetUpStart",
+                                         "Environment::SetUp",
+                                         "3rd.OnEnvironmentsSetUpEnd",
+                                         "2nd.OnEnvironmentsSetUpEnd",
+                                         "1st.OnEnvironmentsSetUpEnd",
+                                         "3rd.OnTestSuiteStart",
+                                         "1st.OnTestCaseStart",
+                                         "2nd.OnTestCaseStart",
+                                         "ListenerTest::SetUpTestSuite",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "ListenerTest::TearDownTestSuite",
+                                         "3rd.OnTestSuiteEnd",
+                                         "2nd.OnTestCaseEnd",
+                                         "1st.OnTestCaseEnd",
+                                         "1st.OnEnvironmentsTearDownStart",
+                                         "2nd.OnEnvironmentsTearDownStart",
+                                         "3rd.OnEnvironmentsTearDownStart",
+                                         "Environment::TearDown",
+                                         "3rd.OnEnvironmentsTearDownEnd",
+                                         "2nd.OnEnvironmentsTearDownEnd",
+                                         "1st.OnEnvironmentsTearDownEnd",
+                                         "3rd.OnTestIterationEnd(0)",
+                                         "2nd.OnTestIterationEnd(0)",
+                                         "1st.OnTestIterationEnd(0)",
+                                         "1st.OnTestIterationStart(1)",
+                                         "2nd.OnTestIterationStart(1)",
+                                         "3rd.OnTestIterationStart(1)",
+                                         "1st.OnEnvironmentsSetUpStart",
+                                         "2nd.OnEnvironmentsSetUpStart",
+                                         "3rd.OnEnvironmentsSetUpStart",
+                                         "Environment::SetUp",
+                                         "3rd.OnEnvironmentsSetUpEnd",
+                                         "2nd.OnEnvironmentsSetUpEnd",
+                                         "1st.OnEnvironmentsSetUpEnd",
+                                         "3rd.OnTestSuiteStart",
+                                         "1st.OnTestCaseStart",
+                                         "2nd.OnTestCaseStart",
+                                         "ListenerTest::SetUpTestSuite",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "ListenerTest::TearDownTestSuite",
+                                         "3rd.OnTestSuiteEnd",
+                                         "2nd.OnTestCaseEnd",
+                                         "1st.OnTestCaseEnd",
+                                         "1st.OnEnvironmentsTearDownStart",
+                                         "2nd.OnEnvironmentsTearDownStart",
+                                         "3rd.OnEnvironmentsTearDownStart",
+                                         "Environment::TearDown",
+                                         "3rd.OnEnvironmentsTearDownEnd",
+                                         "2nd.OnEnvironmentsTearDownEnd",
+                                         "1st.OnEnvironmentsTearDownEnd",
+                                         "3rd.OnTestIterationEnd(1)",
+                                         "2nd.OnTestIterationEnd(1)",
+                                         "1st.OnTestIterationEnd(1)",
+                                         "3rd.OnTestProgramEnd",
+                                         "2nd.OnTestProgramEnd",
+                                         "1st.OnTestProgramEnd"};
+#else
+  const char* const expected_events[] = {"1st.OnTestProgramStart",
+                                         "2nd.OnTestProgramStart",
+                                         "3rd.OnTestProgramStart",
+                                         "1st.OnTestIterationStart(0)",
+                                         "2nd.OnTestIterationStart(0)",
+                                         "3rd.OnTestIterationStart(0)",
+                                         "1st.OnEnvironmentsSetUpStart",
+                                         "2nd.OnEnvironmentsSetUpStart",
+                                         "3rd.OnEnvironmentsSetUpStart",
+                                         "Environment::SetUp",
+                                         "3rd.OnEnvironmentsSetUpEnd",
+                                         "2nd.OnEnvironmentsSetUpEnd",
+                                         "1st.OnEnvironmentsSetUpEnd",
+                                         "3rd.OnTestSuiteStart",
+                                         "ListenerTest::SetUpTestSuite",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "ListenerTest::TearDownTestSuite",
+                                         "3rd.OnTestSuiteEnd",
+                                         "1st.OnEnvironmentsTearDownStart",
+                                         "2nd.OnEnvironmentsTearDownStart",
+                                         "3rd.OnEnvironmentsTearDownStart",
+                                         "Environment::TearDown",
+                                         "3rd.OnEnvironmentsTearDownEnd",
+                                         "2nd.OnEnvironmentsTearDownEnd",
+                                         "1st.OnEnvironmentsTearDownEnd",
+                                         "3rd.OnTestIterationEnd(0)",
+                                         "2nd.OnTestIterationEnd(0)",
+                                         "1st.OnTestIterationEnd(0)",
+                                         "1st.OnTestIterationStart(1)",
+                                         "2nd.OnTestIterationStart(1)",
+                                         "3rd.OnTestIterationStart(1)",
+                                         "1st.OnEnvironmentsSetUpStart",
+                                         "2nd.OnEnvironmentsSetUpStart",
+                                         "3rd.OnEnvironmentsSetUpStart",
+                                         "Environment::SetUp",
+                                         "3rd.OnEnvironmentsSetUpEnd",
+                                         "2nd.OnEnvironmentsSetUpEnd",
+                                         "1st.OnEnvironmentsSetUpEnd",
+                                         "3rd.OnTestSuiteStart",
+                                         "ListenerTest::SetUpTestSuite",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "1st.OnTestStart",
+                                         "2nd.OnTestStart",
+                                         "3rd.OnTestStart",
+                                         "ListenerTest::SetUp",
+                                         "ListenerTest::* Test Body",
+                                         "1st.OnTestPartResult",
+                                         "2nd.OnTestPartResult",
+                                         "3rd.OnTestPartResult",
+                                         "ListenerTest::TearDown",
+                                         "3rd.OnTestEnd",
+                                         "2nd.OnTestEnd",
+                                         "1st.OnTestEnd",
+                                         "ListenerTest::TearDownTestSuite",
+                                         "3rd.OnTestSuiteEnd",
+                                         "1st.OnEnvironmentsTearDownStart",
+                                         "2nd.OnEnvironmentsTearDownStart",
+                                         "3rd.OnEnvironmentsTearDownStart",
+                                         "Environment::TearDown",
+                                         "3rd.OnEnvironmentsTearDownEnd",
+                                         "2nd.OnEnvironmentsTearDownEnd",
+                                         "1st.OnEnvironmentsTearDownEnd",
+                                         "3rd.OnTestIterationEnd(1)",
+                                         "2nd.OnTestIterationEnd(1)",
+                                         "1st.OnTestIterationEnd(1)",
+                                         "3rd.OnTestProgramEnd",
+                                         "2nd.OnTestProgramEnd",
+                                         "1st.OnTestProgramEnd"};
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  VerifyResults(events, expected_events,
+                sizeof(expected_events) / sizeof(expected_events[0]));
+
+  // We need to check manually for ad hoc test failures that happen after
+  // RUN_ALL_TESTS finishes.
+  if (UnitTest::GetInstance()->Failed()) ret_val = 1;
+
+  return ret_val;
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-message-test.cc b/3rd-party/googletest/googletest/test/googletest-message-test.cc
new file mode 100644
index 0000000..bf1f094
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-message-test.cc
@@ -0,0 +1,184 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for the Message class.
+
+#include <sstream>
+#include <string>
+
+#include "gtest/gtest-message.h"
+#include "gtest/gtest.h"
+
+#ifdef GTEST_HAS_ABSL
+#include "absl/strings/str_format.h"
+#endif  // GTEST_HAS_ABSL
+
+namespace {
+
+using ::testing::Message;
+
+#ifdef GTEST_HAS_ABSL
+struct AbslStringifiablePoint {
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const AbslStringifiablePoint& p) {
+    absl::Format(&sink, "(%d, %d)", p.x, p.y);
+  }
+
+  int x;
+  int y;
+};
+#endif  // GTEST_HAS_ABSL
+
+// Tests the testing::Message class
+
+// Tests the default constructor.
+TEST(MessageTest, DefaultConstructor) {
+  const Message msg;
+  EXPECT_EQ("", msg.GetString());
+}
+
+// Tests the copy constructor.
+TEST(MessageTest, CopyConstructor) {
+  const Message msg1("Hello");
+  const Message msg2(msg1);
+  EXPECT_EQ("Hello", msg2.GetString());
+}
+
+// Tests constructing a Message from a C-string.
+TEST(MessageTest, ConstructsFromCString) {
+  Message msg("Hello");
+  EXPECT_EQ("Hello", msg.GetString());
+}
+
+// Tests streaming a float.
+TEST(MessageTest, StreamsFloat) {
+  const std::string s = (Message() << 1.23456F << " " << 2.34567F).GetString();
+  // Both numbers should be printed with enough precision.
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "1.234560", s.c_str());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, " 2.345669", s.c_str());
+}
+
+// Tests streaming a double.
+TEST(MessageTest, StreamsDouble) {
+  const std::string s =
+      (Message() << 1260570880.4555497 << " " << 1260572265.1954534)
+          .GetString();
+  // Both numbers should be printed with enough precision.
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "1260570880.45", s.c_str());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, " 1260572265.19", s.c_str());
+}
+
+// Tests streaming a non-char pointer.
+TEST(MessageTest, StreamsPointer) {
+  int n = 0;
+  int* p = &n;
+  EXPECT_NE("(null)", (Message() << p).GetString());
+}
+
+// Tests streaming a NULL non-char pointer.
+TEST(MessageTest, StreamsNullPointer) {
+  int* p = nullptr;
+  EXPECT_EQ("(null)", (Message() << p).GetString());
+}
+
+// Tests streaming a C string.
+TEST(MessageTest, StreamsCString) {
+  EXPECT_EQ("Foo", (Message() << "Foo").GetString());
+}
+
+// Tests streaming a NULL C string.
+TEST(MessageTest, StreamsNullCString) {
+  char* p = nullptr;
+  EXPECT_EQ("(null)", (Message() << p).GetString());
+}
+
+// Tests streaming std::string.
+TEST(MessageTest, StreamsString) {
+  const ::std::string str("Hello");
+  EXPECT_EQ("Hello", (Message() << str).GetString());
+}
+
+// Tests that we can output strings containing embedded NULs.
+TEST(MessageTest, StreamsStringWithEmbeddedNUL) {
+  const char char_array_with_nul[] = "Here's a NUL\0 and some more string";
+  const ::std::string string_with_nul(char_array_with_nul,
+                                      sizeof(char_array_with_nul) - 1);
+  EXPECT_EQ("Here's a NUL\\0 and some more string",
+            (Message() << string_with_nul).GetString());
+}
+
+// Tests streaming a NUL char.
+TEST(MessageTest, StreamsNULChar) {
+  EXPECT_EQ("\\0", (Message() << '\0').GetString());
+}
+
+// Tests streaming int.
+TEST(MessageTest, StreamsInt) {
+  EXPECT_EQ("123", (Message() << 123).GetString());
+}
+
+#ifdef GTEST_HAS_ABSL
+// Tests streaming a type with an AbslStringify definition.
+TEST(MessageTest, StreamsAbslStringify) {
+  EXPECT_EQ("(1, 2)", (Message() << AbslStringifiablePoint{1, 2}).GetString());
+}
+#endif  // GTEST_HAS_ABSL
+
+// Tests that basic IO manipulators (endl, ends, and flush) can be
+// streamed to Message.
+TEST(MessageTest, StreamsBasicIoManip) {
+  EXPECT_EQ(
+      "Line 1.\nA NUL char \\0 in line 2.",
+      (Message() << "Line 1." << std::endl
+                 << "A NUL char " << std::ends << std::flush << " in line 2.")
+          .GetString());
+}
+
+// Tests Message::GetString()
+TEST(MessageTest, GetString) {
+  Message msg;
+  msg << 1 << " lamb";
+  EXPECT_EQ("1 lamb", msg.GetString());
+}
+
+// Tests streaming a Message object to an ostream.
+TEST(MessageTest, StreamsToOStream) {
+  Message msg("Hello");
+  ::std::stringstream ss;
+  ss << msg;
+  EXPECT_EQ("Hello", testing::internal::StringStreamToString(&ss));
+}
+
+// Tests that a Message object doesn't take up too much stack space.
+TEST(MessageTest, DoesNotTakeUpMuchStackSpace) {
+  EXPECT_LE(sizeof(Message), 16U);
+}
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/test/googletest-options-test.cc b/3rd-party/googletest/googletest/test/googletest-options-test.cc
new file mode 100644
index 0000000..91d06a5
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-options-test.cc
@@ -0,0 +1,225 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Google Test UnitTestOptions tests
+//
+// This file tests classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included from gtest.cc, to avoid changing build or
+// make-files on Windows and other platforms. Do not #include this file
+// anywhere else!
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+#include <windows.h>
+#elif defined(GTEST_OS_WINDOWS)
+#include <direct.h>
+#elif defined(GTEST_OS_OS2)
+// For strcasecmp on OS/2
+#include <strings.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#include "src/gtest-internal-inl.h"
+
+namespace testing {
+namespace internal {
+namespace {
+
+// Turns the given relative path into an absolute path.
+FilePath GetAbsolutePathOf(const FilePath& relative_path) {
+  return FilePath::ConcatPaths(FilePath::GetCurrentDir(), relative_path);
+}
+
+// Testing UnitTestOptions::GetOutputFormat/GetOutputFile.
+
+TEST(XmlOutputTest, GetOutputFormatDefault) {
+  GTEST_FLAG_SET(output, "");
+  EXPECT_STREQ("", UnitTestOptions::GetOutputFormat().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFormat) {
+  GTEST_FLAG_SET(output, "xml:filename");
+  EXPECT_STREQ("xml", UnitTestOptions::GetOutputFormat().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFileDefault) {
+  GTEST_FLAG_SET(output, "");
+  EXPECT_EQ(GetAbsolutePathOf(FilePath("test_detail.xml")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST(XmlOutputTest, GetOutputFileSingleFile) {
+  GTEST_FLAG_SET(output, "xml:filename.abc");
+  EXPECT_EQ(GetAbsolutePathOf(FilePath("filename.abc")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST(XmlOutputTest, GetOutputFileFromDirectoryPath) {
+  GTEST_FLAG_SET(output, "xml:path" GTEST_PATH_SEP_);
+  const std::string expected_output_file =
+      GetAbsolutePathOf(FilePath(std::string("path") + GTEST_PATH_SEP_ +
+                                 GetCurrentExecutableName().string() + ".xml"))
+          .string();
+  const std::string& output_file =
+      UnitTestOptions::GetAbsolutePathToOutputFile();
+#ifdef GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
+  const std::string exe_str = GetCurrentExecutableName().string();
+#ifdef GTEST_OS_WINDOWS
+  const bool success =
+      _strcmpi("googletest-options-test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest-options-ex_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest_all_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest_dll_test", exe_str.c_str()) == 0;
+#elif defined(GTEST_OS_OS2)
+  const bool success =
+      strcasecmp("googletest-options-test", exe_str.c_str()) == 0 ||
+      strcasecmp("gtest-options-ex_test", exe_str.c_str()) == 0 ||
+      strcasecmp("gtest_all_test", exe_str.c_str()) == 0 ||
+      strcasecmp("gtest_dll_test", exe_str.c_str()) == 0;
+#elif defined(GTEST_OS_FUCHSIA)
+  const bool success = exe_str == "app";
+#elif defined(__EMSCRIPTEN__)
+  const bool success = exe_str == "patched_googletest-options-test.js";
+#else
+  const bool success =
+      exe_str == "googletest-options-test" || exe_str == "gtest_all_test" ||
+      exe_str == "lt-gtest_all_test" || exe_str == "gtest_dll_test";
+#endif  // platform ifdefs
+
+  if (!success) FAIL() << "GetCurrentExecutableName() returns " << exe_str;
+}
+
+#ifndef GTEST_OS_FUCHSIA
+
+class XmlOutputChangeDirTest : public Test {
+ protected:
+  void SetUp() override {
+    original_working_dir_ = FilePath::GetCurrentDir();
+    posix::ChDir("..");
+    // This will make the test fail if run from the root directory.
+    EXPECT_NE(original_working_dir_.string(),
+              FilePath::GetCurrentDir().string());
+  }
+
+  void TearDown() override {
+    posix::ChDir(original_working_dir_.string().c_str());
+  }
+
+  FilePath original_working_dir_;
+};
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefault) {
+  GTEST_FLAG_SET(output, "");
+  EXPECT_EQ(
+      FilePath::ConcatPaths(original_working_dir_, FilePath("test_detail.xml"))
+          .string(),
+      UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefaultXML) {
+  GTEST_FLAG_SET(output, "xml");
+  EXPECT_EQ(
+      FilePath::ConcatPaths(original_working_dir_, FilePath("test_detail.xml"))
+          .string(),
+      UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativeFile) {
+  GTEST_FLAG_SET(output, "xml:filename.abc");
+  EXPECT_EQ(
+      FilePath::ConcatPaths(original_working_dir_, FilePath("filename.abc"))
+          .string(),
+      UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
+  GTEST_FLAG_SET(output, "xml:path" GTEST_PATH_SEP_);
+  const std::string expected_output_file =
+      FilePath::ConcatPaths(
+          original_working_dir_,
+          FilePath(std::string("path") + GTEST_PATH_SEP_ +
+                   GetCurrentExecutableName().string() + ".xml"))
+          .string();
+  const std::string& output_file =
+      UnitTestOptions::GetAbsolutePathToOutputFile();
+#ifdef GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsoluteFile) {
+#ifdef GTEST_OS_WINDOWS
+  GTEST_FLAG_SET(output, "xml:c:\\tmp\\filename.abc");
+  EXPECT_EQ(FilePath("c:\\tmp\\filename.abc").string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+#else
+  GTEST_FLAG_SET(output, "xml:/tmp/filename.abc");
+  EXPECT_EQ(FilePath("/tmp/filename.abc").string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+#endif
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsolutePath) {
+#ifdef GTEST_OS_WINDOWS
+  const std::string path = "c:\\tmp\\";
+#else
+  const std::string path = "/tmp/";
+#endif
+
+  GTEST_FLAG_SET(output, "xml:" + path);
+  const std::string expected_output_file =
+      path + GetCurrentExecutableName().string() + ".xml";
+  const std::string& output_file =
+      UnitTestOptions::GetAbsolutePathToOutputFile();
+
+#ifdef GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+#endif  // !GTEST_OS_FUCHSIA
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/test/googletest-output-test-golden-lin.txt b/3rd-party/googletest/googletest/test/googletest-output-test-golden-lin.txt
new file mode 100644
index 0000000..533eb8c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-output-test-golden-lin.txt
@@ -0,0 +1,1201 @@
+The non-test part of the code is expected to have 2 failures.
+
+googletest-output-test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  2
+  3
+Stack trace: (omitted)
+
+[==========] Running 90 tests from 43 test suites.
+[----------] Global test environment set-up.
+FooEnvironment::SetUp() called.
+BarEnvironment::SetUp() called.
+[----------] 1 test from ADeathTest
+[ RUN      ] ADeathTest.ShouldRunFirst
+[       OK ] ADeathTest.ShouldRunFirst
+[----------] 1 test from ATypedDeathTest/0, where TypeParam = int
+[ RUN      ] ATypedDeathTest/0.ShouldRunFirst
+[       OK ] ATypedDeathTest/0.ShouldRunFirst
+[----------] 1 test from ATypedDeathTest/1, where TypeParam = double
+[ RUN      ] ATypedDeathTest/1.ShouldRunFirst
+[       OK ] ATypedDeathTest/1.ShouldRunFirst
+[----------] 1 test from My/ATypeParamDeathTest/0, where TypeParam = int
+[ RUN      ] My/ATypeParamDeathTest/0.ShouldRunFirst
+[       OK ] My/ATypeParamDeathTest/0.ShouldRunFirst
+[----------] 1 test from My/ATypeParamDeathTest/1, where TypeParam = double
+[ RUN      ] My/ATypeParamDeathTest/1.ShouldRunFirst
+[       OK ] My/ATypeParamDeathTest/1.ShouldRunFirst
+[----------] 2 tests from PassingTest
+[ RUN      ] PassingTest.PassingTest1
+[       OK ] PassingTest.PassingTest1
+[ RUN      ] PassingTest.PassingTest2
+[       OK ] PassingTest.PassingTest2
+[----------] 2 tests from NonfatalFailureTest
+[ RUN      ] NonfatalFailureTest.EscapesStringOperands
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  kGoldenString
+    Which is: "\"Line"
+  actual
+    Which is: "actual \"string\""
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  golden
+    Which is: "\"Line"
+  actual
+    Which is: "actual \"string\""
+Stack trace: (omitted)
+
+[  FAILED  ] NonfatalFailureTest.EscapesStringOperands
+[ RUN      ] NonfatalFailureTest.DiffForLongStrings
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  golden_str
+    Which is: "\"Line\0 1\"\nLine 2"
+  "Line 2"
+With diff:
+@@ -1,2 @@
+-\"Line\0 1\"
+ Line 2
+
+Stack trace: (omitted)
+
+[  FAILED  ] NonfatalFailureTest.DiffForLongStrings
+[----------] 3 tests from FatalFailureTest
+[ RUN      ] FatalFailureTest.FatalFailureInSubroutine
+(expecting a failure that x should be 1)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  x
+    Which is: 2
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[ RUN      ] FatalFailureTest.FatalFailureInNestedSubroutine
+(expecting a failure that x should be 1)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  x
+    Which is: 2
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[ RUN      ] FatalFailureTest.NonfatalFailureInSubroutine
+(expecting a failure on false)
+googletest-output-test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[----------] 1 test from LoggingTest
+[ RUN      ] LoggingTest.InterleavingLoggingAndAssertions
+(expecting 2 failures on (3) >= (a[i]))
+i == 0
+i == 1
+googletest-output-test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 9
+Stack trace: (omitted)
+
+i == 2
+i == 3
+googletest-output-test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 6
+Stack trace: (omitted)
+
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+[----------] 7 tests from SCOPED_TRACETest
+[ RUN      ] SCOPED_TRACETest.AcceptedValues
+googletest-output-test_.cc:#: Failure
+Failed
+Just checking that all these values work fine.
+Google Test trace:
+googletest-output-test_.cc:#: (null)
+googletest-output-test_.cc:#: 1337
+googletest-output-test_.cc:#: std::string
+googletest-output-test_.cc:#: literal string
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.AcceptedValues
+[ RUN      ] SCOPED_TRACETest.ObeysScopes
+(expected to fail)
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and shouldn't have a trace.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and should have a trace.
+Google Test trace:
+googletest-output-test_.cc:#: Expected trace
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and shouldn't have a trace.
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.ObeysScopes
+[ RUN      ] SCOPED_TRACETest.WorksInLoop
+(expected to fail)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  2
+  n
+    Which is: 1
+Google Test trace:
+googletest-output-test_.cc:#: i = 1
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  n
+    Which is: 2
+Google Test trace:
+googletest-output-test_.cc:#: i = 2
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.WorksInLoop
+[ RUN      ] SCOPED_TRACETest.WorksInSubroutine
+(expected to fail)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  2
+  n
+    Which is: 1
+Google Test trace:
+googletest-output-test_.cc:#: n = 1
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  n
+    Which is: 2
+Google Test trace:
+googletest-output-test_.cc:#: n = 2
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.WorksInSubroutine
+[ RUN      ] SCOPED_TRACETest.CanBeNested
+(expected to fail)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  n
+    Which is: 2
+Google Test trace:
+googletest-output-test_.cc:#: n = 2
+googletest-output-test_.cc:#: 
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.CanBeNested
+[ RUN      ] SCOPED_TRACETest.CanBeRepeated
+(expected to fail)
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A.
+Google Test trace:
+googletest-output-test_.cc:#: A
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A and B.
+Google Test trace:
+googletest-output-test_.cc:#: B
+googletest-output-test_.cc:#: A
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A, B, and C.
+Google Test trace:
+googletest-output-test_.cc:#: C
+googletest-output-test_.cc:#: B
+googletest-output-test_.cc:#: A
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A, B, and D.
+Google Test trace:
+googletest-output-test_.cc:#: D
+googletest-output-test_.cc:#: B
+googletest-output-test_.cc:#: A
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.CanBeRepeated
+[ RUN      ] SCOPED_TRACETest.WorksConcurrently
+(expecting 6 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #1 (in thread B, only trace B alive).
+Google Test trace:
+googletest-output-test_.cc:#: Trace B
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #2 (in thread A, trace A & B both alive).
+Google Test trace:
+googletest-output-test_.cc:#: Trace A
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #3 (in thread B, trace A & B both alive).
+Google Test trace:
+googletest-output-test_.cc:#: Trace B
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #4 (in thread B, only trace A alive).
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #5 (in thread A, only trace A alive).
+Google Test trace:
+googletest-output-test_.cc:#: Trace A
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #6 (in thread A, no trace alive).
+Stack trace: (omitted)
+
+[  FAILED  ] SCOPED_TRACETest.WorksConcurrently
+[----------] 1 test from ScopedTraceTest
+[ RUN      ] ScopedTraceTest.WithExplicitFileAndLine
+googletest-output-test_.cc:#: Failure
+Failed
+Check that the trace is attached to a particular location.
+Google Test trace:
+explicit_file.cc:123: expected trace message
+Stack trace: (omitted)
+
+[  FAILED  ] ScopedTraceTest.WithExplicitFileAndLine
+[----------] 1 test from NonFatalFailureInFixtureConstructorTest
+[ RUN      ] NonFatalFailureInFixtureConstructorTest.FailureInConstructor
+(expecting 5 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #1, in the test fixture c'tor.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #2, in SetUp().
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #3, in the test body.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #4, in TearDown.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #5, in the test fixture d'tor.
+Stack trace: (omitted)
+
+[  FAILED  ] NonFatalFailureInFixtureConstructorTest.FailureInConstructor
+[----------] 1 test from FatalFailureInFixtureConstructorTest
+[ RUN      ] FatalFailureInFixtureConstructorTest.FailureInConstructor
+(expecting 2 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #1, in the test fixture c'tor.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #2, in the test fixture d'tor.
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureInFixtureConstructorTest.FailureInConstructor
+[----------] 1 test from NonFatalFailureInSetUpTest
+[ RUN      ] NonFatalFailureInSetUpTest.FailureInSetUp
+(expecting 4 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #1, in SetUp().
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #2, in the test function.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #3, in TearDown().
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #4, in the test fixture d'tor.
+Stack trace: (omitted)
+
+[  FAILED  ] NonFatalFailureInSetUpTest.FailureInSetUp
+[----------] 1 test from FatalFailureInSetUpTest
+[ RUN      ] FatalFailureInSetUpTest.FailureInSetUp
+(expecting 3 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #1, in SetUp().
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #2, in TearDown().
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected failure #3, in the test fixture d'tor.
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureInSetUpTest.FailureInSetUp
+[----------] 1 test from AddFailureAtTest
+[ RUN      ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+foo.cc:42: Failure
+Failed
+Expected nonfatal failure in foo.cc
+Stack trace: (omitted)
+
+[  FAILED  ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+[----------] 1 test from GtestFailAtTest
+[ RUN      ] GtestFailAtTest.MessageContainsSpecifiedFileAndLineNumber
+foo.cc:42: Failure
+Failed
+Expected fatal failure in foo.cc
+Stack trace: (omitted)
+
+[  FAILED  ] GtestFailAtTest.MessageContainsSpecifiedFileAndLineNumber
+[----------] 4 tests from MixedUpTestSuiteTest
+[ RUN      ] MixedUpTestSuiteTest.FirstTestFromNamespaceFoo
+[       OK ] MixedUpTestSuiteTest.FirstTestFromNamespaceFoo
+[ RUN      ] MixedUpTestSuiteTest.SecondTestFromNamespaceFoo
+[       OK ] MixedUpTestSuiteTest.SecondTestFromNamespaceFoo
+[ RUN      ] MixedUpTestSuiteTest.ThisShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class.  However, in test suite MixedUpTestSuiteTest,
+you defined test FirstTestFromNamespaceFoo and test ThisShouldFail
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test suites.
+Stack trace: (omitted)
+
+[  FAILED  ] MixedUpTestSuiteTest.ThisShouldFail
+[ RUN      ] MixedUpTestSuiteTest.ThisShouldFailToo
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class.  However, in test suite MixedUpTestSuiteTest,
+you defined test FirstTestFromNamespaceFoo and test ThisShouldFailToo
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test suites.
+Stack trace: (omitted)
+
+[  FAILED  ] MixedUpTestSuiteTest.ThisShouldFailToo
+[----------] 2 tests from MixedUpTestSuiteWithSameTestNameTest
+[ RUN      ] MixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[       OK ] MixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[ RUN      ] MixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class.  However, in test suite MixedUpTestSuiteWithSameTestNameTest,
+you defined test TheSecondTestWithThisNameShouldFail and test TheSecondTestWithThisNameShouldFail
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test suites.
+Stack trace: (omitted)
+
+[  FAILED  ] MixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[----------] 2 tests from TEST_F_before_TEST_in_same_test_case
+[ RUN      ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
+[       OK ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
+[ RUN      ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class, so mixing TEST_F and TEST in the same test suite is
+illegal.  In test suite TEST_F_before_TEST_in_same_test_case,
+test DefinedUsingTEST_F is defined using TEST_F but
+test DefinedUsingTESTAndShouldFail is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+Stack trace: (omitted)
+
+[  FAILED  ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+[----------] 2 tests from TEST_before_TEST_F_in_same_test_case
+[ RUN      ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
+[       OK ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
+[ RUN      ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class, so mixing TEST_F and TEST in the same test suite is
+illegal.  In test suite TEST_before_TEST_F_in_same_test_case,
+test DefinedUsingTEST_FAndShouldFail is defined using TEST_F but
+test DefinedUsingTEST is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+Stack trace: (omitted)
+
+[  FAILED  ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+[----------] 8 tests from ExpectNonfatalFailureTest
+[ RUN      ] ExpectNonfatalFailureTest.CanReferenceGlobalVariables
+[       OK ] ExpectNonfatalFailureTest.CanReferenceGlobalVariables
+[ RUN      ] ExpectNonfatalFailureTest.CanReferenceLocalVariables
+[       OK ] ExpectNonfatalFailureTest.CanReferenceLocalVariables
+[ RUN      ] ExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
+[       OK ] ExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 2 failures
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure 1.
+Stack trace: (omitted)
+
+
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure 2.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenStatementReturns
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementReturns
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenStatementThrows
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementThrows
+[----------] 8 tests from ExpectFatalFailureTest
+[ RUN      ] ExpectFatalFailureTest.CanReferenceGlobalVariables
+[       OK ] ExpectFatalFailureTest.CanReferenceGlobalVariables
+[ RUN      ] ExpectFatalFailureTest.CanReferenceLocalStaticVariables
+[       OK ] ExpectFatalFailureTest.CanReferenceLocalStaticVariables
+[ RUN      ] ExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
+[       OK ] ExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
+[ RUN      ] ExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+[ RUN      ] ExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 2 failures
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+[ RUN      ] ExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+[ RUN      ] ExpectFatalFailureTest.FailsWhenStatementReturns
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementReturns
+[ RUN      ] ExpectFatalFailureTest.FailsWhenStatementThrows
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementThrows
+[----------] 2 tests from TypedTest/0, where TypeParam = int
+[ RUN      ] TypedTest/0.Success
+[       OK ] TypedTest/0.Success
+[ RUN      ] TypedTest/0.Failure
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  TypeParam()
+    Which is: 0
+Expected failure
+Stack trace: (omitted)
+
+[  FAILED  ] TypedTest/0.Failure, where TypeParam = int
+[----------] 2 tests from TypedTestWithNames/char0, where TypeParam = char
+[ RUN      ] TypedTestWithNames/char0.Success
+[       OK ] TypedTestWithNames/char0.Success
+[ RUN      ] TypedTestWithNames/char0.Failure
+googletest-output-test_.cc:#: Failure
+Failed
+Stack trace: (omitted)
+
+[  FAILED  ] TypedTestWithNames/char0.Failure, where TypeParam = char
+[----------] 2 tests from TypedTestWithNames/int1, where TypeParam = int
+[ RUN      ] TypedTestWithNames/int1.Success
+[       OK ] TypedTestWithNames/int1.Success
+[ RUN      ] TypedTestWithNames/int1.Failure
+googletest-output-test_.cc:#: Failure
+Failed
+Stack trace: (omitted)
+
+[  FAILED  ] TypedTestWithNames/int1.Failure, where TypeParam = int
+[----------] 2 tests from Unsigned/TypedTestP/0, where TypeParam = unsigned char
+[ RUN      ] Unsigned/TypedTestP/0.Success
+[       OK ] Unsigned/TypedTestP/0.Success
+[ RUN      ] Unsigned/TypedTestP/0.Failure
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1U
+    Which is: 1
+  TypeParam()
+    Which is: '\0'
+Expected failure
+Stack trace: (omitted)
+
+[  FAILED  ] Unsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
+[----------] 2 tests from Unsigned/TypedTestP/1, where TypeParam = unsigned int
+[ RUN      ] Unsigned/TypedTestP/1.Success
+[       OK ] Unsigned/TypedTestP/1.Success
+[ RUN      ] Unsigned/TypedTestP/1.Failure
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1U
+    Which is: 1
+  TypeParam()
+    Which is: 0
+Expected failure
+Stack trace: (omitted)
+
+[  FAILED  ] Unsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
+[----------] 2 tests from UnsignedCustomName/TypedTestP/unsignedChar0, where TypeParam = unsigned char
+[ RUN      ] UnsignedCustomName/TypedTestP/unsignedChar0.Success
+[       OK ] UnsignedCustomName/TypedTestP/unsignedChar0.Success
+[ RUN      ] UnsignedCustomName/TypedTestP/unsignedChar0.Failure
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1U
+    Which is: 1
+  TypeParam()
+    Which is: '\0'
+Expected failure
+Stack trace: (omitted)
+
+[  FAILED  ] UnsignedCustomName/TypedTestP/unsignedChar0.Failure, where TypeParam = unsigned char
+[----------] 2 tests from UnsignedCustomName/TypedTestP/unsignedInt1, where TypeParam = unsigned int
+[ RUN      ] UnsignedCustomName/TypedTestP/unsignedInt1.Success
+[       OK ] UnsignedCustomName/TypedTestP/unsignedInt1.Success
+[ RUN      ] UnsignedCustomName/TypedTestP/unsignedInt1.Failure
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1U
+    Which is: 1
+  TypeParam()
+    Which is: 0
+Expected failure
+Stack trace: (omitted)
+
+[  FAILED  ] UnsignedCustomName/TypedTestP/unsignedInt1.Failure, where TypeParam = unsigned int
+[----------] 4 tests from ExpectFailureTest
+[ RUN      ] ExpectFailureTest.ExpectFatalFailure
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+googletest-output-test_.cc:#: Success:
+Succeeded
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure containing "Some other fatal failure expected."
+  Actual:
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailure
+[ RUN      ] ExpectFailureTest.ExpectNonFatalFailure
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+googletest-output-test_.cc:#: Success:
+Succeeded
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure containing "Some other non-fatal failure."
+  Actual:
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailure
+[ RUN      ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+googletest-output-test_.cc:#: Success:
+Succeeded
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure containing "Some other fatal failure expected."
+  Actual:
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
+[ RUN      ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+googletest-output-test_.cc:#: Success:
+Succeeded
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+googletest-output-test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure containing "Some other non-fatal failure."
+  Actual:
+googletest-output-test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+[----------] 2 tests from ExpectFailureWithThreadsTest
+[ RUN      ] ExpectFailureWithThreadsTest.ExpectFatalFailure
+(expecting 2 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectFatalFailure
+[ RUN      ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
+(expecting 2 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+Stack trace: (omitted)
+
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
+[----------] 1 test from ScopedFakeTestPartResultReporterTest
+[ RUN      ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+(expecting 2 failures)
+googletest-output-test_.cc:#: Failure
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+googletest-output-test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+[  FAILED  ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+[----------] 2 tests from DynamicFixture
+DynamicFixture::SetUpTestSuite
+[ RUN      ] DynamicFixture.DynamicTestPass
+DynamicFixture()
+DynamicFixture::SetUp
+DynamicFixture::TearDown
+~DynamicFixture()
+[       OK ] DynamicFixture.DynamicTestPass
+[ RUN      ] DynamicFixture.DynamicTestFail
+DynamicFixture()
+DynamicFixture::SetUp
+googletest-output-test_.cc:#: Failure
+Value of: Pass
+  Actual: false
+Expected: true
+Stack trace: (omitted)
+
+DynamicFixture::TearDown
+~DynamicFixture()
+[  FAILED  ] DynamicFixture.DynamicTestFail
+DynamicFixture::TearDownTestSuite
+[----------] 1 test from DynamicFixtureAnotherName
+DynamicFixture::SetUpTestSuite
+[ RUN      ] DynamicFixtureAnotherName.DynamicTestPass
+DynamicFixture()
+DynamicFixture::SetUp
+DynamicFixture::TearDown
+~DynamicFixture()
+[       OK ] DynamicFixtureAnotherName.DynamicTestPass
+DynamicFixture::TearDownTestSuite
+[----------] 2 tests from BadDynamicFixture1
+DynamicFixture::SetUpTestSuite
+[ RUN      ] BadDynamicFixture1.FixtureBase
+DynamicFixture()
+DynamicFixture::SetUp
+DynamicFixture::TearDown
+~DynamicFixture()
+[       OK ] BadDynamicFixture1.FixtureBase
+[ RUN      ] BadDynamicFixture1.TestBase
+DynamicFixture()
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class, so mixing TEST_F and TEST in the same test suite is
+illegal.  In test suite BadDynamicFixture1,
+test FixtureBase is defined using TEST_F but
+test TestBase is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+Stack trace: (omitted)
+
+~DynamicFixture()
+[  FAILED  ] BadDynamicFixture1.TestBase
+DynamicFixture::TearDownTestSuite
+[----------] 2 tests from BadDynamicFixture2
+DynamicFixture::SetUpTestSuite
+[ RUN      ] BadDynamicFixture2.FixtureBase
+DynamicFixture()
+DynamicFixture::SetUp
+DynamicFixture::TearDown
+~DynamicFixture()
+[       OK ] BadDynamicFixture2.FixtureBase
+[ RUN      ] BadDynamicFixture2.Derived
+DynamicFixture()
+gtest.cc:#: Failure
+Failed
+All tests in the same test suite must use the same test fixture
+class.  However, in test suite BadDynamicFixture2,
+you defined test FixtureBase and test Derived
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test suites.
+Stack trace: (omitted)
+
+~DynamicFixture()
+[  FAILED  ] BadDynamicFixture2.Derived
+DynamicFixture::TearDownTestSuite
+[----------] 1 test from TestSuiteThatFailsToSetUp
+googletest-output-test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+Stack trace: (omitted)
+
+[ RUN      ] TestSuiteThatFailsToSetUp.ShouldNotRun
+googletest-output-test_.cc:#: Skipped
+
+[  SKIPPED ] TestSuiteThatFailsToSetUp.ShouldNotRun
+[----------] 1 test from TestSuiteThatSkipsInSetUp
+googletest-output-test_.cc:#: Skipped
+Skip entire test suite
+
+[ RUN      ] TestSuiteThatSkipsInSetUp.ShouldNotRun
+googletest-output-test_.cc:#: Skipped
+
+[  SKIPPED ] TestSuiteThatSkipsInSetUp.ShouldNotRun
+[----------] 1 test from PrintingFailingParams/FailingParamTest
+[ RUN      ] PrintingFailingParams/FailingParamTest.Fails/0
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  GetParam()
+    Which is: 2
+Stack trace: (omitted)
+
+[  FAILED  ] PrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
+[----------] 1 test from EmptyBasenameParamInst
+[ RUN      ] EmptyBasenameParamInst.Passes/0
+[       OK ] EmptyBasenameParamInst.Passes/0
+[----------] 2 tests from PrintingStrings/ParamTest
+[ RUN      ] PrintingStrings/ParamTest.Success/a
+[       OK ] PrintingStrings/ParamTest.Success/a
+[ RUN      ] PrintingStrings/ParamTest.Failure/a
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  "b"
+  GetParam()
+    Which is: "a"
+Expected failure
+Stack trace: (omitted)
+
+[  FAILED  ] PrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
+[----------] 3 tests from GoogleTestVerification
+[ RUN      ] GoogleTestVerification.UninstantiatedParameterizedTestSuite<NoTests>
+googletest-output-test_.cc:#: Failure
+Parameterized test suite NoTests is instantiated via INSTANTIATE_TEST_SUITE_P, but no tests are defined via TEST_P . No test cases will run.
+
+Ideally, INSTANTIATE_TEST_SUITE_P should only ever be invoked from code that always depend on code that provides TEST_P. Failing to do so is often an indication of dead code, e.g. the last TEST_P was removed but the rest got left behind.
+
+To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NoTests);
+Stack trace: (omitted)
+
+[  FAILED  ] GoogleTestVerification.UninstantiatedParameterizedTestSuite<NoTests>
+[ RUN      ] GoogleTestVerification.UninstantiatedParameterizedTestSuite<DetectNotInstantiatedTest>
+googletest-output-test_.cc:#: Failure
+Parameterized test suite DetectNotInstantiatedTest is defined via TEST_P, but never instantiated. None of the test cases will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only ones provided expand to nothing.
+
+Ideally, TEST_P definitions should only ever be included as part of binaries that intend to use them. (As opposed to, for example, being placed in a library that may be linked in to get other utilities.)
+
+To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DetectNotInstantiatedTest);
+Stack trace: (omitted)
+
+[  FAILED  ] GoogleTestVerification.UninstantiatedParameterizedTestSuite<DetectNotInstantiatedTest>
+[ RUN      ] GoogleTestVerification.UninstantiatedTypeParameterizedTestSuite<DetectNotInstantiatedTypesTest>
+googletest-output-test_.cc:#: Failure
+Type parameterized test suite DetectNotInstantiatedTypesTest is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run.
+
+Ideally, TYPED_TEST_P definitions should only ever be included as part of binaries that intend to use them. (As opposed to, for example, being placed in a library that may be linked in to get other utilities.)
+
+To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DetectNotInstantiatedTypesTest);
+Stack trace: (omitted)
+
+[  FAILED  ] GoogleTestVerification.UninstantiatedTypeParameterizedTestSuite<DetectNotInstantiatedTypesTest>
+[----------] Global test environment tear-down
+BarEnvironment::TearDown() called.
+googletest-output-test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+Stack trace: (omitted)
+
+FooEnvironment::TearDown() called.
+googletest-output-test_.cc:#: Failure
+Failed
+Expected fatal failure.
+Stack trace: (omitted)
+
+[==========] 90 tests from 43 test suites ran.
+[  PASSED  ] 31 tests.
+[  SKIPPED ] 2 tests, listed below:
+[  SKIPPED ] TestSuiteThatFailsToSetUp.ShouldNotRun
+[  SKIPPED ] TestSuiteThatSkipsInSetUp.ShouldNotRun
+[  FAILED  ] 57 tests, listed below:
+[  FAILED  ] NonfatalFailureTest.EscapesStringOperands
+[  FAILED  ] NonfatalFailureTest.DiffForLongStrings
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+[  FAILED  ] SCOPED_TRACETest.AcceptedValues
+[  FAILED  ] SCOPED_TRACETest.ObeysScopes
+[  FAILED  ] SCOPED_TRACETest.WorksInLoop
+[  FAILED  ] SCOPED_TRACETest.WorksInSubroutine
+[  FAILED  ] SCOPED_TRACETest.CanBeNested
+[  FAILED  ] SCOPED_TRACETest.CanBeRepeated
+[  FAILED  ] SCOPED_TRACETest.WorksConcurrently
+[  FAILED  ] ScopedTraceTest.WithExplicitFileAndLine
+[  FAILED  ] NonFatalFailureInFixtureConstructorTest.FailureInConstructor
+[  FAILED  ] FatalFailureInFixtureConstructorTest.FailureInConstructor
+[  FAILED  ] NonFatalFailureInSetUpTest.FailureInSetUp
+[  FAILED  ] FatalFailureInSetUpTest.FailureInSetUp
+[  FAILED  ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+[  FAILED  ] GtestFailAtTest.MessageContainsSpecifiedFileAndLineNumber
+[  FAILED  ] MixedUpTestSuiteTest.ThisShouldFail
+[  FAILED  ] MixedUpTestSuiteTest.ThisShouldFailToo
+[  FAILED  ] MixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[  FAILED  ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+[  FAILED  ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementReturns
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementThrows
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementReturns
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementThrows
+[  FAILED  ] TypedTest/0.Failure, where TypeParam = int
+[  FAILED  ] TypedTestWithNames/char0.Failure, where TypeParam = char
+[  FAILED  ] TypedTestWithNames/int1.Failure, where TypeParam = int
+[  FAILED  ] Unsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
+[  FAILED  ] Unsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
+[  FAILED  ] UnsignedCustomName/TypedTestP/unsignedChar0.Failure, where TypeParam = unsigned char
+[  FAILED  ] UnsignedCustomName/TypedTestP/unsignedInt1.Failure, where TypeParam = unsigned int
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailure
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailure
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectFatalFailure
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
+[  FAILED  ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+[  FAILED  ] DynamicFixture.DynamicTestFail
+[  FAILED  ] BadDynamicFixture1.TestBase
+[  FAILED  ] BadDynamicFixture2.Derived
+[  FAILED  ] PrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
+[  FAILED  ] PrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
+[  FAILED  ] GoogleTestVerification.UninstantiatedParameterizedTestSuite<NoTests>
+[  FAILED  ] GoogleTestVerification.UninstantiatedParameterizedTestSuite<DetectNotInstantiatedTest>
+[  FAILED  ] GoogleTestVerification.UninstantiatedTypeParameterizedTestSuite<DetectNotInstantiatedTypesTest>
+
+57 FAILED TESTS
+[  FAILED  ] TestSuiteThatFailsToSetUp: SetUpTestSuite or TearDownTestSuite
+
+ 1 FAILED TEST SUITE
+  YOU HAVE 1 DISABLED TEST
+
+Note: Google Test filter = FatalFailureTest.*:LoggingTest.*
+[==========] Running 4 tests from 2 test suites.
+[----------] Global test environment set-up.
+[----------] 3 tests from FatalFailureTest
+[ RUN      ] FatalFailureTest.FatalFailureInSubroutine
+(expecting a failure that x should be 1)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  x
+    Which is: 2
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine (? ms)
+[ RUN      ] FatalFailureTest.FatalFailureInNestedSubroutine
+(expecting a failure that x should be 1)
+googletest-output-test_.cc:#: Failure
+Expected equality of these values:
+  1
+  x
+    Which is: 2
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine (? ms)
+[ RUN      ] FatalFailureTest.NonfatalFailureInSubroutine
+(expecting a failure on false)
+googletest-output-test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+Stack trace: (omitted)
+
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine (? ms)
+[----------] 3 tests from FatalFailureTest (? ms total)
+
+[----------] 1 test from LoggingTest
+[ RUN      ] LoggingTest.InterleavingLoggingAndAssertions
+(expecting 2 failures on (3) >= (a[i]))
+i == 0
+i == 1
+googletest-output-test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 9
+Stack trace: (omitted)
+
+i == 2
+i == 3
+googletest-output-test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 6
+Stack trace: (omitted)
+
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions (? ms)
+[----------] 1 test from LoggingTest (? ms total)
+
+[----------] Global test environment tear-down
+[==========] 4 tests from 2 test suites ran. (? ms total)
+[  PASSED  ] 0 tests.
+[  FAILED  ] 4 tests, listed below:
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+
+ 4 FAILED TESTS
+Note: Google Test filter = *DISABLED_*
+[==========] Running 1 test from 1 test suite.
+[----------] Global test environment set-up.
+[----------] 1 test from DisabledTestsWarningTest
+[ RUN      ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
+[       OK ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test suite ran.
+[  PASSED  ] 1 test.
+Note: Google Test filter = PassingTest.*
+Note: This is test shard 2 of 2.
+[==========] Running 1 test from 1 test suite.
+[----------] Global test environment set-up.
+[----------] 1 test from PassingTest
+[ RUN      ] PassingTest.PassingTest2
+[       OK ] PassingTest.PassingTest2
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test suite ran.
+[  PASSED  ] 1 test.
diff --git a/3rd-party/googletest/googletest/test/googletest-output-test.py b/3rd-party/googletest/googletest/test/googletest-output-test.py
new file mode 100755
index 0000000..6d80d53
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-output-test.py
@@ -0,0 +1,385 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+r"""Tests the text output of Google C++ Testing and Mocking Framework.
+
+To update the golden file:
+googletest_output_test.py --build_dir=BUILD/DIR --gengolden
+where BUILD/DIR contains the built googletest-output-test_ file.
+googletest_output_test.py --gengolden
+googletest_output_test.py
+"""
+
+import difflib
+import os
+import re
+import sys
+from googletest.test import gtest_test_utils
+
+
+# The flag for generating the golden file
+GENGOLDEN_FLAG = '--gengolden'
+CATCH_EXCEPTIONS_ENV_VAR_NAME = 'GTEST_CATCH_EXCEPTIONS'
+
+# The flag indicating stacktraces are not supported
+NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support'
+
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+IS_WINDOWS = os.name == 'nt'
+
+GOLDEN_NAME = 'googletest-output-test-golden-lin.txt'
+
+PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('googletest-output-test_')
+
+# At least one command we exercise must not have the
+# 'internal_skip_environment_and_ad_hoc_tests' argument.
+COMMAND_LIST_TESTS = ({}, [PROGRAM_PATH, '--gtest_list_tests'])
+COMMAND_WITH_COLOR = ({}, [PROGRAM_PATH, '--gtest_color=yes'])
+COMMAND_WITH_TIME = (
+    {},
+    [
+        PROGRAM_PATH,
+        '--gtest_print_time',
+        'internal_skip_environment_and_ad_hoc_tests',
+        '--gtest_filter=FatalFailureTest.*:LoggingTest.*',
+    ],
+)
+COMMAND_WITH_DISABLED = (
+    {},
+    [
+        PROGRAM_PATH,
+        '--gtest_also_run_disabled_tests',
+        'internal_skip_environment_and_ad_hoc_tests',
+        '--gtest_filter=*DISABLED_*',
+    ],
+)
+COMMAND_WITH_SHARDING = (
+    {'GTEST_SHARD_INDEX': '1', 'GTEST_TOTAL_SHARDS': '2'},
+    [
+        PROGRAM_PATH,
+        'internal_skip_environment_and_ad_hoc_tests',
+        '--gtest_filter=PassingTest.*',
+    ],
+)
+
+GOLDEN_PATH = os.path.join(gtest_test_utils.GetSourceDir(), GOLDEN_NAME)
+
+
+def ToUnixLineEnding(s):
+  """Changes all Windows/Mac line endings in s to UNIX line endings."""
+
+  return s.replace('\r\n', '\n').replace('\r', '\n')
+
+
+def RemoveLocations(test_output):
+  """Removes all file location info from a Google Test program's output.
+
+  Args:
+       test_output:  the output of a Google Test program.
+
+  Returns:
+       output with all file location info (in the form of
+       'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
+       'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
+       'FILE_NAME:#: '.
+  """
+
+  return re.sub(
+      r'.*[/\\]((googletest-output-test_|gtest).cc)(\:\d+|\(\d+\))\: ',
+      r'\1:#: ',
+      test_output,
+  )
+
+
+def RemoveStackTraceDetails(output):
+  """Removes all stack traces from a Google Test program's output."""
+
+  # *? means "find the shortest string that matches".
+  return re.sub(
+      r'Stack trace:(.|\n)*?\n\n', 'Stack trace: (omitted)\n\n', output
+  )
+
+
+def RemoveStackTraces(output):
+  """Removes all traces of stack traces from a Google Test program's output."""
+
+  # *? means "find the shortest string that matches".
+  return re.sub(r'Stack trace:(.|\n)*?\n', '', output)
+
+
+def RemoveTime(output):
+  """Removes all time information from a Google Test program's output."""
+
+  return re.sub(r'\(\d+ ms', '(? ms', output)
+
+
+def RemoveTypeInfoDetails(test_output):
+  """Removes compiler-specific type info from Google Test program's output.
+
+  Args:
+       test_output:  the output of a Google Test program.
+
+  Returns:
+       output with type information normalized to canonical form.
+  """
+
+  # some compilers output the name of type 'unsigned int' as 'unsigned'
+  return re.sub(r'unsigned int', 'unsigned', test_output)
+
+
+def NormalizeToCurrentPlatform(test_output):
+  """Normalizes platform specific output details for easier comparison."""
+
+  if IS_WINDOWS:
+    # Removes the color information that is not present on Windows.
+    test_output = re.sub('\x1b\\[(0;3\d)?m', '', test_output)
+    # Changes failure message headers into the Windows format.
+    test_output = re.sub(r': Failure\n', r': error: ', test_output)
+    # Changes file(line_number) to file:line_number.
+    test_output = re.sub(r'((\w|\.)+)\((\d+)\):', r'\1:\3:', test_output)
+
+  return test_output
+
+
+def RemoveTestCounts(output):
+  """Removes test counts from a Google Test program's output."""
+
+  output = re.sub(r'\d+ tests?, listed below', '? tests, listed below', output)
+  output = re.sub(r'\d+ FAILED TESTS', '? FAILED TESTS', output)
+  output = re.sub(
+      r'\d+ tests? from \d+ test cases?', '? tests from ? test cases', output
+  )
+  output = re.sub(r'\d+ tests? from ([a-zA-Z_])', r'? tests from \1', output)
+  return re.sub(r'\d+ tests?\.', '? tests.', output)
+
+
+def RemoveMatchingTests(test_output, pattern):
+  """Removes output of specified tests from a Google Test program's output.
+
+  This function strips not only the beginning and the end of a test but also
+  all output in between.
+
+  Args:
+    test_output:       A string containing the test output.
+    pattern:           A regex string that matches names of test cases or tests
+      to remove.
+
+  Returns:
+    Contents of test_output with tests whose names match pattern removed.
+  """
+
+  test_output = re.sub(
+      r'.*\[ RUN      \] .*%s(.|\n)*?\[(  FAILED  |       OK )\] .*%s.*\n'
+      % (pattern, pattern),
+      '',
+      test_output,
+  )
+  return re.sub(r'.*%s.*\n' % pattern, '', test_output)
+
+
+def NormalizeOutput(output):
+  """Normalizes output (the output of googletest-output-test_.exe)."""
+
+  output = ToUnixLineEnding(output)
+  output = RemoveLocations(output)
+  output = RemoveStackTraceDetails(output)
+  output = RemoveTime(output)
+  return output
+
+
+def GetShellCommandOutput(env_cmd):
+  """Runs a command in a sub-process, and returns its output in a string.
+
+  Args:
+    env_cmd: The shell command. A 2-tuple where element 0 is a dict of extra
+      environment variables to set, and element 1 is a string with the command
+      and any flags.
+
+  Returns:
+    A string with the command's combined standard and diagnostic output.
+  """
+
+  # Spawns cmd in a sub-process, and gets its standard I/O file objects.
+  # Set and save the environment properly.
+  environ = os.environ.copy()
+  environ.update(env_cmd[0])
+  p = gtest_test_utils.Subprocess(env_cmd[1], env=environ)
+
+  return p.output
+
+
+def GetCommandOutput(env_cmd):
+  """Runs a command and returns output with all file location info stripped off.
+
+  Args:
+    env_cmd:  The shell command. A 2-tuple where element 0 is a dict of extra
+      environment variables to set, and element 1 is a string with the command
+      and any flags.
+
+  Returns:
+    A string with the command's combined standard and diagnostic output. File
+    location info is stripped.
+  """
+
+  # Disables exception pop-ups on Windows.
+  environ, cmdline = env_cmd
+  environ = dict(environ)  # Ensures we are modifying a copy.
+  environ[CATCH_EXCEPTIONS_ENV_VAR_NAME] = '1'
+  return NormalizeOutput(GetShellCommandOutput((environ, cmdline)))
+
+
+def GetOutputOfAllCommands():
+  """Returns concatenated output from several representative commands."""
+
+  return (
+      GetCommandOutput(COMMAND_WITH_COLOR)
+      + GetCommandOutput(COMMAND_WITH_TIME)
+      + GetCommandOutput(COMMAND_WITH_DISABLED)
+      + GetCommandOutput(COMMAND_WITH_SHARDING)
+  )
+
+
+test_list = GetShellCommandOutput(COMMAND_LIST_TESTS)
+SUPPORTS_DEATH_TESTS = 'DeathTest' in test_list
+SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
+SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
+SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv
+
+CAN_GENERATE_GOLDEN_FILE = (
+    SUPPORTS_DEATH_TESTS
+    and SUPPORTS_TYPED_TESTS
+    and SUPPORTS_THREADS
+    and SUPPORTS_STACK_TRACES
+)
+
+
+class GTestOutputTest(gtest_test_utils.TestCase):
+
+  def RemoveUnsupportedTests(self, test_output):
+    if not SUPPORTS_DEATH_TESTS:
+      test_output = RemoveMatchingTests(test_output, 'DeathTest')
+    if not SUPPORTS_TYPED_TESTS:
+      test_output = RemoveMatchingTests(test_output, 'TypedTest')
+      test_output = RemoveMatchingTests(test_output, 'TypedDeathTest')
+      test_output = RemoveMatchingTests(test_output, 'TypeParamDeathTest')
+    if not SUPPORTS_THREADS:
+      test_output = RemoveMatchingTests(
+          test_output, 'ExpectFailureWithThreadsTest'
+      )
+      test_output = RemoveMatchingTests(
+          test_output, 'ScopedFakeTestPartResultReporterTest'
+      )
+      test_output = RemoveMatchingTests(test_output, 'WorksConcurrently')
+    if not SUPPORTS_STACK_TRACES:
+      test_output = RemoveStackTraces(test_output)
+
+    return test_output
+
+  def testOutput(self):
+    output = GetOutputOfAllCommands()
+
+    golden_file = open(GOLDEN_PATH, 'rb')
+    # A mis-configured source control system can cause \r appear in EOL
+    # sequences when we read the golden file irrespective of an operating
+    # system used. Therefore, we need to strip those \r's from newlines
+    # unconditionally.
+    golden = ToUnixLineEnding(golden_file.read().decode())
+    golden_file.close()
+
+    # We want the test to pass regardless of certain features being
+    # supported or not.
+
+    # We still have to remove type name specifics in all cases.
+    normalized_actual = RemoveTypeInfoDetails(output)
+    normalized_golden = RemoveTypeInfoDetails(golden)
+
+    if CAN_GENERATE_GOLDEN_FILE:
+      self.assertEqual(
+          normalized_golden,
+          normalized_actual,
+          '\n'.join(
+              difflib.unified_diff(
+                  normalized_golden.split('\n'),
+                  normalized_actual.split('\n'),
+                  'golden',
+                  'actual',
+              )
+          ),
+      )
+    else:
+      normalized_actual = NormalizeToCurrentPlatform(
+          RemoveTestCounts(normalized_actual)
+      )
+      normalized_golden = NormalizeToCurrentPlatform(
+          RemoveTestCounts(self.RemoveUnsupportedTests(normalized_golden))
+      )
+
+      # This code is very handy when debugging golden file differences:
+      if os.getenv('DEBUG_GTEST_OUTPUT_TEST'):
+        open(
+            os.path.join(
+                gtest_test_utils.GetSourceDir(),
+                '_googletest-output-test_normalized_actual.txt',
+            ),
+            'wb',
+        ).write(normalized_actual)
+        open(
+            os.path.join(
+                gtest_test_utils.GetSourceDir(),
+                '_googletest-output-test_normalized_golden.txt',
+            ),
+            'wb',
+        ).write(normalized_golden)
+
+      self.assertEqual(normalized_golden, normalized_actual)
+
+
+if __name__ == '__main__':
+  if NO_STACKTRACE_SUPPORT_FLAG in sys.argv:
+    # unittest.main() can't handle unknown flags
+    sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
+
+  if GENGOLDEN_FLAG in sys.argv:
+    if CAN_GENERATE_GOLDEN_FILE:
+      output = GetOutputOfAllCommands()
+      golden_file = open(GOLDEN_PATH, 'wb')
+      golden_file.write(output.encode())
+      golden_file.close()
+    else:
+      message = """Unable to write a golden file when compiled in an environment
+that does not support all the required features (death tests,
+typed tests, stack traces, and multiple threads).
+Please build this test and generate the golden file using Blaze on Linux."""
+
+      sys.stderr.write(message)
+      sys.exit(1)
+  else:
+    gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-output-test_.cc b/3rd-party/googletest/googletest/test/googletest-output-test_.cc
new file mode 100644
index 0000000..e3560c0
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-output-test_.cc
@@ -0,0 +1,1058 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The purpose of this file is to generate Google Test output under
+// various conditions.  The output will then be verified by
+// googletest-output-test.py to ensure that Google Test generates the
+// desired messages.  Therefore, most tests in this file are MEANT TO
+// FAIL.
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <string>
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127 /* conditional expression is constant */)
+
+#ifdef GTEST_IS_THREADSAFE
+using testing::ScopedFakeTestPartResultReporter;
+using testing::TestPartResultArray;
+
+using testing::internal::Notification;
+using testing::internal::ThreadWithParam;
+#endif
+
+namespace posix = ::testing::internal::posix;
+
+// Tests catching fatal failures.
+
+// A subroutine used by the following test.
+void TestEq1(int x) { ASSERT_EQ(1, x); }
+
+// This function calls a test subroutine, catches the fatal failure it
+// generates, and then returns early.
+void TryTestSubroutine() {
+  // Calls a subrountine that yields a fatal failure.
+  TestEq1(2);
+
+  // Catches the fatal failure and aborts the test.
+  //
+  // The testing::Test:: prefix is necessary when calling
+  // HasFatalFailure() outside of a TEST, TEST_F, or test fixture.
+  if (testing::Test::HasFatalFailure()) return;
+
+  // If we get here, something is wrong.
+  FAIL() << "This should never be reached.";
+}
+
+TEST(PassingTest, PassingTest1) {}
+
+TEST(PassingTest, PassingTest2) {}
+
+// Tests that parameters of failing parameterized tests are printed in the
+// failing test summary.
+class FailingParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(FailingParamTest, Fails) { EXPECT_EQ(1, GetParam()); }
+
+// This generates a test which will fail. Google Test is expected to print
+// its parameter when it outputs the list of all failed tests.
+INSTANTIATE_TEST_SUITE_P(PrintingFailingParams, FailingParamTest,
+                         testing::Values(2));
+
+// Tests that an empty value for the test suite basename yields just
+// the test name without any prior /
+class EmptyBasenameParamInst : public testing::TestWithParam<int> {};
+
+TEST_P(EmptyBasenameParamInst, Passes) { EXPECT_EQ(1, GetParam()); }
+
+INSTANTIATE_TEST_SUITE_P(, EmptyBasenameParamInst, testing::Values(1));
+
+static const char kGoldenString[] = "\"Line\0 1\"\nLine 2";
+
+TEST(NonfatalFailureTest, EscapesStringOperands) {
+  std::string actual = "actual \"string\"";
+  EXPECT_EQ(kGoldenString, actual);
+
+  const char* golden = kGoldenString;
+  EXPECT_EQ(golden, actual);
+}
+
+TEST(NonfatalFailureTest, DiffForLongStrings) {
+  std::string golden_str(kGoldenString, sizeof(kGoldenString) - 1);
+  EXPECT_EQ(golden_str, "Line 2");
+}
+
+// Tests catching a fatal failure in a subroutine.
+TEST(FatalFailureTest, FatalFailureInSubroutine) {
+  printf("(expecting a failure that x should be 1)\n");
+
+  TryTestSubroutine();
+}
+
+// Tests catching a fatal failure in a nested subroutine.
+TEST(FatalFailureTest, FatalFailureInNestedSubroutine) {
+  printf("(expecting a failure that x should be 1)\n");
+
+  // Calls a subrountine that yields a fatal failure.
+  TryTestSubroutine();
+
+  // Catches the fatal failure and aborts the test.
+  //
+  // When calling HasFatalFailure() inside a TEST, TEST_F, or test
+  // fixture, the testing::Test:: prefix is not needed.
+  if (HasFatalFailure()) return;
+
+  // If we get here, something is wrong.
+  FAIL() << "This should never be reached.";
+}
+
+// Tests HasFatalFailure() after a failed EXPECT check.
+TEST(FatalFailureTest, NonfatalFailureInSubroutine) {
+  printf("(expecting a failure on false)\n");
+  EXPECT_TRUE(false);               // Generates a nonfatal failure
+  ASSERT_FALSE(HasFatalFailure());  // This should succeed.
+}
+
+// Tests interleaving user logging and Google Test assertions.
+TEST(LoggingTest, InterleavingLoggingAndAssertions) {
+  static const int a[4] = {3, 9, 2, 6};
+
+  printf("(expecting 2 failures on (3) >= (a[i]))\n");
+  for (int i = 0; i < static_cast<int>(sizeof(a) / sizeof(*a)); i++) {
+    printf("i == %d\n", i);
+    EXPECT_GE(3, a[i]);
+  }
+}
+
+// Tests the SCOPED_TRACE macro.
+
+// A helper function for testing SCOPED_TRACE.
+void SubWithoutTrace(int n) {
+  EXPECT_EQ(1, n);
+  ASSERT_EQ(2, n);
+}
+
+// Another helper function for testing SCOPED_TRACE.
+void SubWithTrace(int n) {
+  SCOPED_TRACE(testing::Message() << "n = " << n);
+
+  SubWithoutTrace(n);
+}
+
+TEST(SCOPED_TRACETest, AcceptedValues) {
+  SCOPED_TRACE("literal string");
+  SCOPED_TRACE(std::string("std::string"));
+  SCOPED_TRACE(1337);  // streamable type
+  const char* null_value = nullptr;
+  SCOPED_TRACE(null_value);
+
+  ADD_FAILURE() << "Just checking that all these values work fine.";
+}
+
+// Tests that SCOPED_TRACE() obeys lexical scopes.
+TEST(SCOPED_TRACETest, ObeysScopes) {
+  printf("(expected to fail)\n");
+
+  // There should be no trace before SCOPED_TRACE() is invoked.
+  ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
+
+  {
+    SCOPED_TRACE("Expected trace");
+    // After SCOPED_TRACE(), a failure in the current scope should contain
+    // the trace.
+    ADD_FAILURE() << "This failure is expected, and should have a trace.";
+  }
+
+  // Once the control leaves the scope of the SCOPED_TRACE(), there
+  // should be no trace again.
+  ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
+}
+
+// Tests that SCOPED_TRACE works inside a loop.
+TEST(SCOPED_TRACETest, WorksInLoop) {
+  printf("(expected to fail)\n");
+
+  for (int i = 1; i <= 2; i++) {
+    SCOPED_TRACE(testing::Message() << "i = " << i);
+
+    SubWithoutTrace(i);
+  }
+}
+
+// Tests that SCOPED_TRACE works in a subroutine.
+TEST(SCOPED_TRACETest, WorksInSubroutine) {
+  printf("(expected to fail)\n");
+
+  SubWithTrace(1);
+  SubWithTrace(2);
+}
+
+// Tests that SCOPED_TRACE can be nested.
+TEST(SCOPED_TRACETest, CanBeNested) {
+  printf("(expected to fail)\n");
+
+  SCOPED_TRACE("");  // A trace without a message.
+
+  SubWithTrace(2);
+}
+
+// Tests that multiple SCOPED_TRACEs can be used in the same scope.
+TEST(SCOPED_TRACETest, CanBeRepeated) {
+  printf("(expected to fail)\n");
+
+  SCOPED_TRACE("A");
+  ADD_FAILURE()
+      << "This failure is expected, and should contain trace point A.";
+
+  SCOPED_TRACE("B");
+  ADD_FAILURE()
+      << "This failure is expected, and should contain trace point A and B.";
+
+  {
+    SCOPED_TRACE("C");
+    ADD_FAILURE() << "This failure is expected, and should "
+                  << "contain trace point A, B, and C.";
+  }
+
+  SCOPED_TRACE("D");
+  ADD_FAILURE() << "This failure is expected, and should "
+                << "contain trace point A, B, and D.";
+}
+
+#ifdef GTEST_IS_THREADSAFE
+// Tests that SCOPED_TRACE()s can be used concurrently from multiple
+// threads.  Namely, an assertion should be affected by
+// SCOPED_TRACE()s in its own thread only.
+
+// Here's the sequence of actions that happen in the test:
+//
+//   Thread A (main)                | Thread B (spawned)
+//   ===============================|================================
+//   spawns thread B                |
+//   -------------------------------+--------------------------------
+//   waits for n1                   | SCOPED_TRACE("Trace B");
+//                                  | generates failure #1
+//                                  | notifies n1
+//   -------------------------------+--------------------------------
+//   SCOPED_TRACE("Trace A");       | waits for n2
+//   generates failure #2           |
+//   notifies n2                    |
+//   -------------------------------|--------------------------------
+//   waits for n3                   | generates failure #3
+//                                  | trace B dies
+//                                  | generates failure #4
+//                                  | notifies n3
+//   -------------------------------|--------------------------------
+//   generates failure #5           | finishes
+//   trace A dies                   |
+//   generates failure #6           |
+//   -------------------------------|--------------------------------
+//   waits for thread B to finish   |
+
+struct CheckPoints {
+  Notification n1;
+  Notification n2;
+  Notification n3;
+};
+
+static void ThreadWithScopedTrace(CheckPoints* check_points) {
+  {
+    SCOPED_TRACE("Trace B");
+    ADD_FAILURE() << "Expected failure #1 (in thread B, only trace B alive).";
+    check_points->n1.Notify();
+    check_points->n2.WaitForNotification();
+
+    ADD_FAILURE()
+        << "Expected failure #3 (in thread B, trace A & B both alive).";
+  }  // Trace B dies here.
+  ADD_FAILURE() << "Expected failure #4 (in thread B, only trace A alive).";
+  check_points->n3.Notify();
+}
+
+TEST(SCOPED_TRACETest, WorksConcurrently) {
+  printf("(expecting 6 failures)\n");
+
+  CheckPoints check_points;
+  ThreadWithParam<CheckPoints*> thread(&ThreadWithScopedTrace, &check_points,
+                                       nullptr);
+  check_points.n1.WaitForNotification();
+
+  {
+    SCOPED_TRACE("Trace A");
+    ADD_FAILURE()
+        << "Expected failure #2 (in thread A, trace A & B both alive).";
+    check_points.n2.Notify();
+    check_points.n3.WaitForNotification();
+
+    ADD_FAILURE() << "Expected failure #5 (in thread A, only trace A alive).";
+  }  // Trace A dies here.
+  ADD_FAILURE() << "Expected failure #6 (in thread A, no trace alive).";
+  thread.Join();
+}
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests basic functionality of the ScopedTrace utility (most of its features
+// are already tested in SCOPED_TRACETest).
+TEST(ScopedTraceTest, WithExplicitFileAndLine) {
+  testing::ScopedTrace trace("explicit_file.cc", 123, "expected trace message");
+  ADD_FAILURE() << "Check that the trace is attached to a particular location.";
+}
+
+TEST(DisabledTestsWarningTest,
+     DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning) {
+  // This test body is intentionally empty.  Its sole purpose is for
+  // verifying that the --gtest_also_run_disabled_tests flag
+  // suppresses the "YOU HAVE 12 DISABLED TESTS" warning at the end of
+  // the test output.
+}
+
+// Tests using assertions outside of TEST and TEST_F.
+//
+// This function creates two failures intentionally.
+void AdHocTest() {
+  printf("The non-test part of the code is expected to have 2 failures.\n\n");
+  EXPECT_TRUE(false);
+  EXPECT_EQ(2, 3);
+}
+
+// Runs all TESTs, all TEST_Fs, and the ad hoc test.
+int RunAllTests() {
+  AdHocTest();
+  return RUN_ALL_TESTS();
+}
+
+// Tests non-fatal failures in the fixture constructor.
+class NonFatalFailureInFixtureConstructorTest : public testing::Test {
+ protected:
+  NonFatalFailureInFixtureConstructorTest() {
+    printf("(expecting 5 failures)\n");
+    ADD_FAILURE() << "Expected failure #1, in the test fixture c'tor.";
+  }
+
+  ~NonFatalFailureInFixtureConstructorTest() override {
+    ADD_FAILURE() << "Expected failure #5, in the test fixture d'tor.";
+  }
+
+  void SetUp() override { ADD_FAILURE() << "Expected failure #2, in SetUp()."; }
+
+  void TearDown() override {
+    ADD_FAILURE() << "Expected failure #4, in TearDown.";
+  }
+};
+
+TEST_F(NonFatalFailureInFixtureConstructorTest, FailureInConstructor) {
+  ADD_FAILURE() << "Expected failure #3, in the test body.";
+}
+
+// Tests fatal failures in the fixture constructor.
+class FatalFailureInFixtureConstructorTest : public testing::Test {
+ protected:
+  FatalFailureInFixtureConstructorTest() {
+    printf("(expecting 2 failures)\n");
+    Init();
+  }
+
+  ~FatalFailureInFixtureConstructorTest() override {
+    ADD_FAILURE() << "Expected failure #2, in the test fixture d'tor.";
+  }
+
+  void SetUp() override {
+    ADD_FAILURE() << "UNEXPECTED failure in SetUp().  "
+                  << "We should never get here, as the test fixture c'tor "
+                  << "had a fatal failure.";
+  }
+
+  void TearDown() override {
+    ADD_FAILURE() << "UNEXPECTED failure in TearDown().  "
+                  << "We should never get here, as the test fixture c'tor "
+                  << "had a fatal failure.";
+  }
+
+ private:
+  void Init() { FAIL() << "Expected failure #1, in the test fixture c'tor."; }
+};
+
+TEST_F(FatalFailureInFixtureConstructorTest, FailureInConstructor) {
+  ADD_FAILURE() << "UNEXPECTED failure in the test body.  "
+                << "We should never get here, as the test fixture c'tor "
+                << "had a fatal failure.";
+}
+
+// Tests non-fatal failures in SetUp().
+class NonFatalFailureInSetUpTest : public testing::Test {
+ protected:
+  ~NonFatalFailureInSetUpTest() override { Deinit(); }
+
+  void SetUp() override {
+    printf("(expecting 4 failures)\n");
+    ADD_FAILURE() << "Expected failure #1, in SetUp().";
+  }
+
+  void TearDown() override { FAIL() << "Expected failure #3, in TearDown()."; }
+
+ private:
+  void Deinit() { FAIL() << "Expected failure #4, in the test fixture d'tor."; }
+};
+
+TEST_F(NonFatalFailureInSetUpTest, FailureInSetUp) {
+  FAIL() << "Expected failure #2, in the test function.";
+}
+
+// Tests fatal failures in SetUp().
+class FatalFailureInSetUpTest : public testing::Test {
+ protected:
+  ~FatalFailureInSetUpTest() override { Deinit(); }
+
+  void SetUp() override {
+    printf("(expecting 3 failures)\n");
+    FAIL() << "Expected failure #1, in SetUp().";
+  }
+
+  void TearDown() override { FAIL() << "Expected failure #2, in TearDown()."; }
+
+ private:
+  void Deinit() { FAIL() << "Expected failure #3, in the test fixture d'tor."; }
+};
+
+TEST_F(FatalFailureInSetUpTest, FailureInSetUp) {
+  FAIL() << "UNEXPECTED failure in the test function.  "
+         << "We should never get here, as SetUp() failed.";
+}
+
+TEST(AddFailureAtTest, MessageContainsSpecifiedFileAndLineNumber) {
+  ADD_FAILURE_AT("foo.cc", 42) << "Expected nonfatal failure in foo.cc";
+}
+
+TEST(GtestFailAtTest, MessageContainsSpecifiedFileAndLineNumber) {
+  GTEST_FAIL_AT("foo.cc", 42) << "Expected fatal failure in foo.cc";
+}
+
+// The MixedUpTestSuiteTest test case verifies that Google Test will fail a
+// test if it uses a different fixture class than what other tests in
+// the same test case use.  It deliberately contains two fixture
+// classes with the same name but defined in different namespaces.
+
+// The MixedUpTestSuiteWithSameTestNameTest test case verifies that
+// when the user defines two tests with the same test case name AND
+// same test name (but in different namespaces), the second test will
+// fail.
+
+namespace foo {
+
+class MixedUpTestSuiteTest : public testing::Test {};
+
+TEST_F(MixedUpTestSuiteTest, FirstTestFromNamespaceFoo) {}
+TEST_F(MixedUpTestSuiteTest, SecondTestFromNamespaceFoo) {}
+
+class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {};
+
+TEST_F(MixedUpTestSuiteWithSameTestNameTest,
+       TheSecondTestWithThisNameShouldFail) {}
+
+}  // namespace foo
+
+namespace bar {
+
+class MixedUpTestSuiteTest : public testing::Test {};
+
+// The following two tests are expected to fail.  We rely on the
+// golden file to check that Google Test generates the right error message.
+TEST_F(MixedUpTestSuiteTest, ThisShouldFail) {}
+TEST_F(MixedUpTestSuiteTest, ThisShouldFailToo) {}
+
+class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {};
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST_F(MixedUpTestSuiteWithSameTestNameTest,
+       TheSecondTestWithThisNameShouldFail) {}
+
+}  // namespace bar
+
+// The following two test cases verify that Google Test catches the user
+// error of mixing TEST and TEST_F in the same test case.  The first
+// test case checks the scenario where TEST_F appears before TEST, and
+// the second one checks where TEST appears before TEST_F.
+
+class TEST_F_before_TEST_in_same_test_case : public testing::Test {};
+
+TEST_F(TEST_F_before_TEST_in_same_test_case, DefinedUsingTEST_F) {}
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST(TEST_F_before_TEST_in_same_test_case, DefinedUsingTESTAndShouldFail) {}
+
+class TEST_before_TEST_F_in_same_test_case : public testing::Test {};
+
+TEST(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST) {}
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST_F(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST_FAndShouldFail) {}
+
+// Used for testing EXPECT_NONFATAL_FAILURE() and EXPECT_FATAL_FAILURE().
+int global_integer = 0;
+
+// Tests that EXPECT_NONFATAL_FAILURE() can reference global variables.
+TEST(ExpectNonfatalFailureTest, CanReferenceGlobalVariables) {
+  global_integer = 0;
+  EXPECT_NONFATAL_FAILURE(
+      { EXPECT_EQ(1, global_integer) << "Expected non-fatal failure."; },
+      "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() can reference local variables
+// (static or not).
+TEST(ExpectNonfatalFailureTest, CanReferenceLocalVariables) {
+  int m = 0;
+  static int n;
+  n = 1;
+  EXPECT_NONFATAL_FAILURE({ EXPECT_EQ(m, n) << "Expected non-fatal failure."; },
+                          "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() succeeds when there is exactly
+// one non-fatal failure and no fatal failure.
+TEST(ExpectNonfatalFailureTest, SucceedsWhenThereIsOneNonfatalFailure) {
+  EXPECT_NONFATAL_FAILURE({ ADD_FAILURE() << "Expected non-fatal failure."; },
+                          "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there is no
+// non-fatal failure.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereIsNoNonfatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({}, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there are two
+// non-fatal failures.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereAreTwoNonfatalFailures) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE(
+      {
+        ADD_FAILURE() << "Expected non-fatal failure 1.";
+        ADD_FAILURE() << "Expected non-fatal failure 2.";
+      },
+      "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there is one fatal
+// failure.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereIsOneFatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({ FAIL() << "Expected fatal failure."; }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
+// tested returns.
+TEST(ExpectNonfatalFailureTest, FailsWhenStatementReturns) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({ return; }, "");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
+// tested throws.
+TEST(ExpectNonfatalFailureTest, FailsWhenStatementThrows) {
+  printf("(expecting a failure)\n");
+  try {
+    EXPECT_NONFATAL_FAILURE({ throw 0; }, "");
+  } catch (int) {  // NOLINT
+  }
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_FATAL_FAILURE() can reference global variables.
+TEST(ExpectFatalFailureTest, CanReferenceGlobalVariables) {
+  global_integer = 0;
+  EXPECT_FATAL_FAILURE(
+      { ASSERT_EQ(1, global_integer) << "Expected fatal failure."; },
+      "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() can reference local static
+// variables.
+TEST(ExpectFatalFailureTest, CanReferenceLocalStaticVariables) {
+  static int n;
+  n = 1;
+  EXPECT_FATAL_FAILURE({ ASSERT_EQ(0, n) << "Expected fatal failure."; },
+                       "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() succeeds when there is exactly
+// one fatal failure and no non-fatal failure.
+TEST(ExpectFatalFailureTest, SucceedsWhenThereIsOneFatalFailure) {
+  EXPECT_FATAL_FAILURE({ FAIL() << "Expected fatal failure."; },
+                       "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there is no fatal
+// failure.
+TEST(ExpectFatalFailureTest, FailsWhenThereIsNoFatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({}, "");
+}
+
+// A helper for generating a fatal failure.
+void FatalFailure() { FAIL() << "Expected fatal failure."; }
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there are two
+// fatal failures.
+TEST(ExpectFatalFailureTest, FailsWhenThereAreTwoFatalFailures) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE(
+      {
+        FatalFailure();
+        FatalFailure();
+      },
+      "");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there is one non-fatal
+// failure.
+TEST(ExpectFatalFailureTest, FailsWhenThereIsOneNonfatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({ ADD_FAILURE() << "Expected non-fatal failure."; }, "");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
+// tested returns.
+TEST(ExpectFatalFailureTest, FailsWhenStatementReturns) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({ return; }, "");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
+// tested throws.
+TEST(ExpectFatalFailureTest, FailsWhenStatementThrows) {
+  printf("(expecting a failure)\n");
+  try {
+    EXPECT_FATAL_FAILURE({ throw 0; }, "");
+  } catch (int) {  // NOLINT
+  }
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// This #ifdef block tests the output of value-parameterized tests.
+
+std::string ParamNameFunc(const testing::TestParamInfo<std::string>& info) {
+  return info.param;
+}
+
+class ParamTest : public testing::TestWithParam<std::string> {};
+
+TEST_P(ParamTest, Success) { EXPECT_EQ("a", GetParam()); }
+
+TEST_P(ParamTest, Failure) { EXPECT_EQ("b", GetParam()) << "Expected failure"; }
+
+INSTANTIATE_TEST_SUITE_P(PrintingStrings, ParamTest,
+                         testing::Values(std::string("a")), ParamNameFunc);
+
+// The case where a suite has INSTANTIATE_TEST_SUITE_P but not TEST_P.
+using NoTests = ParamTest;
+INSTANTIATE_TEST_SUITE_P(ThisIsOdd, NoTests, ::testing::Values("Hello"));
+
+// fails under kErrorOnUninstantiatedParameterizedTest=true
+class DetectNotInstantiatedTest : public testing::TestWithParam<int> {};
+TEST_P(DetectNotInstantiatedTest, Used) {}
+
+// This would make the test failure from the above go away.
+// INSTANTIATE_TEST_SUITE_P(Fix, DetectNotInstantiatedTest, testing::Values(1));
+
+template <typename T>
+class TypedTest : public testing::Test {};
+
+TYPED_TEST_SUITE(TypedTest, testing::Types<int>);
+
+TYPED_TEST(TypedTest, Success) { EXPECT_EQ(0, TypeParam()); }
+
+TYPED_TEST(TypedTest, Failure) {
+  EXPECT_EQ(1, TypeParam()) << "Expected failure";
+}
+
+typedef testing::Types<char, int> TypesForTestWithNames;
+
+template <typename T>
+class TypedTestWithNames : public testing::Test {};
+
+class TypedTestNames {
+ public:
+  template <typename T>
+  static std::string GetName(int i) {
+    if (std::is_same<T, char>::value)
+      return std::string("char") + ::testing::PrintToString(i);
+    if (std::is_same<T, int>::value)
+      return std::string("int") + ::testing::PrintToString(i);
+  }
+};
+
+TYPED_TEST_SUITE(TypedTestWithNames, TypesForTestWithNames, TypedTestNames);
+
+TYPED_TEST(TypedTestWithNames, Success) {}
+
+TYPED_TEST(TypedTestWithNames, Failure) { FAIL(); }
+
+template <typename T>
+class TypedTestP : public testing::Test {};
+
+TYPED_TEST_SUITE_P(TypedTestP);
+
+TYPED_TEST_P(TypedTestP, Success) { EXPECT_EQ(0U, TypeParam()); }
+
+TYPED_TEST_P(TypedTestP, Failure) {
+  EXPECT_EQ(1U, TypeParam()) << "Expected failure";
+}
+
+REGISTER_TYPED_TEST_SUITE_P(TypedTestP, Success, Failure);
+
+typedef testing::Types<unsigned char, unsigned int> UnsignedTypes;
+INSTANTIATE_TYPED_TEST_SUITE_P(Unsigned, TypedTestP, UnsignedTypes);
+
+class TypedTestPNames {
+ public:
+  template <typename T>
+  static std::string GetName(int i) {
+    if (std::is_same<T, unsigned char>::value) {
+      return std::string("unsignedChar") + ::testing::PrintToString(i);
+    }
+    if (std::is_same<T, unsigned int>::value) {
+      return std::string("unsignedInt") + ::testing::PrintToString(i);
+    }
+  }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(UnsignedCustomName, TypedTestP, UnsignedTypes,
+                               TypedTestPNames);
+
+template <typename T>
+class DetectNotInstantiatedTypesTest : public testing::Test {};
+TYPED_TEST_SUITE_P(DetectNotInstantiatedTypesTest);
+TYPED_TEST_P(DetectNotInstantiatedTypesTest, Used) {
+  TypeParam instantiate;
+  (void)instantiate;
+}
+REGISTER_TYPED_TEST_SUITE_P(DetectNotInstantiatedTypesTest, Used);
+
+// kErrorOnUninstantiatedTypeParameterizedTest=true would make the above fail.
+// Adding the following would make that test failure go away.
+//
+// typedef ::testing::Types<char, int, unsigned int> MyTypes;
+// INSTANTIATE_TYPED_TEST_SUITE_P(All, DetectNotInstantiatedTypesTest, MyTypes);
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+// We rely on the golden file to verify that tests whose test case
+// name ends with DeathTest are run first.
+
+TEST(ADeathTest, ShouldRunFirst) {}
+
+// We rely on the golden file to verify that typed tests whose test
+// case name ends with DeathTest are run first.
+
+template <typename T>
+class ATypedDeathTest : public testing::Test {};
+
+typedef testing::Types<int, double> NumericTypes;
+TYPED_TEST_SUITE(ATypedDeathTest, NumericTypes);
+
+TYPED_TEST(ATypedDeathTest, ShouldRunFirst) {}
+
+// We rely on the golden file to verify that type-parameterized tests
+// whose test case name ends with DeathTest are run first.
+
+template <typename T>
+class ATypeParamDeathTest : public testing::Test {};
+
+TYPED_TEST_SUITE_P(ATypeParamDeathTest);
+
+TYPED_TEST_P(ATypeParamDeathTest, ShouldRunFirst) {}
+
+REGISTER_TYPED_TEST_SUITE_P(ATypeParamDeathTest, ShouldRunFirst);
+
+INSTANTIATE_TYPED_TEST_SUITE_P(My, ATypeParamDeathTest, NumericTypes);
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Tests various failure conditions of
+// EXPECT_{,NON}FATAL_FAILURE{,_ON_ALL_THREADS}.
+class ExpectFailureTest : public testing::Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  enum FailureMode { FATAL_FAILURE, NONFATAL_FAILURE };
+  static void AddFailure(FailureMode failure) {
+    if (failure == FATAL_FAILURE) {
+      FAIL() << "Expected fatal failure.";
+    } else {
+      ADD_FAILURE() << "Expected non-fatal failure.";
+    }
+  }
+};
+
+TEST_F(ExpectFailureTest, ExpectFatalFailure) {
+  // Expected fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(SUCCEED(), "Expected fatal failure.");
+  // Expected fatal failure, but got a non-fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(AddFailure(NONFATAL_FAILURE),
+                       "Expected non-fatal "
+                       "failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(AddFailure(FATAL_FAILURE),
+                       "Some other fatal failure "
+                       "expected.");
+}
+
+TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
+  // Expected non-fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(SUCCEED(), "Expected non-fatal failure.");
+  // Expected non-fatal failure, but got a fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailure(FATAL_FAILURE), "Expected fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailure(NONFATAL_FAILURE),
+                          "Some other non-fatal "
+                          "failure.");
+}
+
+#ifdef GTEST_IS_THREADSAFE
+
+class ExpectFailureWithThreadsTest : public ExpectFailureTest {
+ protected:
+  static void AddFailureInOtherThread(FailureMode failure) {
+    ThreadWithParam<FailureMode> thread(&AddFailure, failure, nullptr);
+    thread.Join();
+  }
+};
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailure) {
+  // We only intercept the current thread.
+  printf("(expecting 2 failures)\n");
+  EXPECT_FATAL_FAILURE(AddFailureInOtherThread(FATAL_FAILURE),
+                       "Expected fatal failure.");
+}
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailure) {
+  // We only intercept the current thread.
+  printf("(expecting 2 failures)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailureInOtherThread(NONFATAL_FAILURE),
+                          "Expected non-fatal failure.");
+}
+
+typedef ExpectFailureWithThreadsTest ScopedFakeTestPartResultReporterTest;
+
+// Tests that the ScopedFakeTestPartResultReporter only catches failures from
+// the current thread if it is instantiated with INTERCEPT_ONLY_CURRENT_THREAD.
+TEST_F(ScopedFakeTestPartResultReporterTest, InterceptOnlyCurrentThread) {
+  printf("(expecting 2 failures)\n");
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
+        &results);
+    AddFailureInOtherThread(FATAL_FAILURE);
+    AddFailureInOtherThread(NONFATAL_FAILURE);
+  }
+  // The two failures should not have been intercepted.
+  EXPECT_EQ(0, results.size()) << "This shouldn't fail.";
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
+  // Expected fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected fatal failure.");
+  // Expected fatal failure, but got a non-fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
+                                      "Expected non-fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
+                                      "Some other fatal failure expected.");
+}
+
+TEST_F(ExpectFailureTest, ExpectNonFatalFailureOnAllThreads) {
+  // Expected non-fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(SUCCEED(),
+                                         "Expected non-fatal "
+                                         "failure.");
+  // Expected non-fatal failure, but got a fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
+                                         "Expected fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
+                                         "Some other non-fatal failure.");
+}
+
+class DynamicFixture : public testing::Test {
+ protected:
+  DynamicFixture() { printf("DynamicFixture()\n"); }
+  ~DynamicFixture() override { printf("~DynamicFixture()\n"); }
+  void SetUp() override { printf("DynamicFixture::SetUp\n"); }
+  void TearDown() override { printf("DynamicFixture::TearDown\n"); }
+
+  static void SetUpTestSuite() { printf("DynamicFixture::SetUpTestSuite\n"); }
+  static void TearDownTestSuite() {
+    printf("DynamicFixture::TearDownTestSuite\n");
+  }
+};
+
+template <bool Pass>
+class DynamicTest : public DynamicFixture {
+ public:
+  void TestBody() override { EXPECT_TRUE(Pass); }
+};
+
+auto dynamic_test = (
+    // Register two tests with the same fixture correctly.
+    testing::RegisterTest(
+        "DynamicFixture", "DynamicTestPass", nullptr, nullptr, __FILE__,
+        __LINE__, []() -> DynamicFixture* { return new DynamicTest<true>; }),
+    testing::RegisterTest(
+        "DynamicFixture", "DynamicTestFail", nullptr, nullptr, __FILE__,
+        __LINE__, []() -> DynamicFixture* { return new DynamicTest<false>; }),
+
+    // Register the same fixture with another name. That's fine.
+    testing::RegisterTest(
+        "DynamicFixtureAnotherName", "DynamicTestPass", nullptr, nullptr,
+        __FILE__, __LINE__,
+        []() -> DynamicFixture* { return new DynamicTest<true>; }),
+
+    // Register two tests with the same fixture incorrectly.
+    testing::RegisterTest(
+        "BadDynamicFixture1", "FixtureBase", nullptr, nullptr, __FILE__,
+        __LINE__, []() -> DynamicFixture* { return new DynamicTest<true>; }),
+    testing::RegisterTest(
+        "BadDynamicFixture1", "TestBase", nullptr, nullptr, __FILE__, __LINE__,
+        []() -> testing::Test* { return new DynamicTest<true>; }),
+
+    // Register two tests with the same fixture incorrectly by omitting the
+    // return type.
+    testing::RegisterTest(
+        "BadDynamicFixture2", "FixtureBase", nullptr, nullptr, __FILE__,
+        __LINE__, []() -> DynamicFixture* { return new DynamicTest<true>; }),
+    testing::RegisterTest("BadDynamicFixture2", "Derived", nullptr, nullptr,
+                          __FILE__, __LINE__,
+                          []() { return new DynamicTest<true>; }));
+
+// Two test environments for testing testing::AddGlobalTestEnvironment().
+
+class FooEnvironment : public testing::Environment {
+ public:
+  void SetUp() override { printf("%s", "FooEnvironment::SetUp() called.\n"); }
+
+  void TearDown() override {
+    printf("%s", "FooEnvironment::TearDown() called.\n");
+    FAIL() << "Expected fatal failure.";
+  }
+};
+
+class BarEnvironment : public testing::Environment {
+ public:
+  void SetUp() override { printf("%s", "BarEnvironment::SetUp() called.\n"); }
+
+  void TearDown() override {
+    printf("%s", "BarEnvironment::TearDown() called.\n");
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }
+};
+
+class TestSuiteThatFailsToSetUp : public testing::Test {
+ public:
+  static void SetUpTestSuite() { EXPECT_TRUE(false); }
+};
+TEST_F(TestSuiteThatFailsToSetUp, ShouldNotRun) { std::abort(); }
+
+class TestSuiteThatSkipsInSetUp : public testing::Test {
+ public:
+  static void SetUpTestSuite() { GTEST_SKIP() << "Skip entire test suite"; }
+};
+TEST_F(TestSuiteThatSkipsInSetUp, ShouldNotRun) { std::abort(); }
+
+// The main function.
+//
+// The idea is to use Google Test to run all the tests we have defined (some
+// of them are intended to fail), and then compare the test results
+// with the "golden" file.
+int main(int argc, char** argv) {
+  GTEST_FLAG_SET(print_time, false);
+
+  // We just run the tests, knowing some of them are intended to fail.
+  // We will use a separate Python script to compare the output of
+  // this program with the golden file.
+
+  // It's hard to test InitGoogleTest() directly, as it has many
+  // global side effects.  The following line serves as a test
+  // for it.
+  testing::InitGoogleTest(&argc, argv);
+  bool internal_skip_environment_and_ad_hoc_tests =
+      std::count(argv, argv + argc,
+                 std::string("internal_skip_environment_and_ad_hoc_tests")) > 0;
+
+#ifdef GTEST_HAS_DEATH_TEST
+  if (!GTEST_FLAG_GET(internal_run_death_test).empty()) {
+    // Skip the usual output capturing if we're running as the child
+    // process of an threadsafe-style death test.
+#if defined(GTEST_OS_WINDOWS)
+    posix::FReopen("nul:", "w", stdout);
+#else
+    posix::FReopen("/dev/null", "w", stdout);
+#endif  // GTEST_OS_WINDOWS
+    return RUN_ALL_TESTS();
+  }
+#endif  // GTEST_HAS_DEATH_TEST
+
+  if (internal_skip_environment_and_ad_hoc_tests) return RUN_ALL_TESTS();
+
+  // Registers two global test environments.
+  // The golden file verifies that they are set up in the order they
+  // are registered, and torn down in the reverse order.
+  testing::AddGlobalTestEnvironment(new FooEnvironment);
+  testing::AddGlobalTestEnvironment(new BarEnvironment);
+  GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4127
+  return RunAllTests();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name1-test.py b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name1-test.py
new file mode 100644
index 0000000..4886e49
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name1-test.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test warns the user when not initialized properly."""
+
+from googletest.test import gtest_test_utils
+
+binary_name = 'googletest-param-test-invalid-name1-test_'
+COMMAND = gtest_test_utils.GetTestExecutablePath(binary_name)
+
+
+def Assert(condition):
+  if not condition:
+    raise AssertionError
+
+
+def TestExitCodeAndOutput(command):
+  """Runs the given command and verifies its exit code and output."""
+
+  err = 'Parameterized test name \'"InvalidWithQuotes"\' is invalid'
+
+  p = gtest_test_utils.Subprocess(command)
+  Assert(p.terminated_by_signal)
+
+  # Verify the output message contains appropriate output
+  Assert(err in p.output)
+
+
+class GTestParamTestInvalidName1Test(gtest_test_utils.TestCase):
+
+  def testExitCodeAndOutput(self):
+    TestExitCodeAndOutput(COMMAND)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name1-test_.cc b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name1-test_.cc
new file mode 100644
index 0000000..004733a
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name1-test_.cc
@@ -0,0 +1,46 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest.h"
+
+namespace {
+class DummyTest : public ::testing::TestWithParam<const char *> {};
+
+TEST_P(DummyTest, Dummy) {}
+
+INSTANTIATE_TEST_SUITE_P(InvalidTestName, DummyTest,
+                         ::testing::Values("InvalidWithQuotes"),
+                         ::testing::PrintToStringParamName());
+
+}  // namespace
+
+int main(int argc, char *argv[]) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name2-test.py b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name2-test.py
new file mode 100644
index 0000000..bcd8ddf
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name2-test.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test warns the user when not initialized properly."""
+
+from googletest.test import gtest_test_utils
+
+binary_name = 'googletest-param-test-invalid-name2-test_'
+COMMAND = gtest_test_utils.GetTestExecutablePath(binary_name)
+
+
+def Assert(condition):
+  if not condition:
+    raise AssertionError
+
+
+def TestExitCodeAndOutput(command):
+  """Runs the given command and verifies its exit code and output."""
+
+  err = "Duplicate parameterized test name 'a'"
+
+  p = gtest_test_utils.Subprocess(command)
+  Assert(p.terminated_by_signal)
+
+  # Check for appropriate output
+  Assert(err in p.output)
+
+
+class GTestParamTestInvalidName2Test(gtest_test_utils.TestCase):
+
+  def testExitCodeAndOutput(self):
+    TestExitCodeAndOutput(COMMAND)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name2-test_.cc b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name2-test_.cc
new file mode 100644
index 0000000..6d88a9c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test-invalid-name2-test_.cc
@@ -0,0 +1,52 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+namespace {
+class DummyTest : public ::testing::TestWithParam<const char *> {};
+
+std::string StringParamTestSuffix(
+    const testing::TestParamInfo<const char *> &info) {
+  return std::string(info.param);
+}
+
+TEST_P(DummyTest, Dummy) {}
+
+INSTANTIATE_TEST_SUITE_P(DuplicateTestNames, DummyTest,
+                         ::testing::Values("a", "b", "a", "c"),
+                         StringParamTestSuffix);
+}  // namespace
+
+int main(int argc, char *argv[]) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test-test.cc b/3rd-party/googletest/googletest/test/googletest-param-test-test.cc
new file mode 100644
index 0000000..c9c5e78
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test-test.cc
@@ -0,0 +1,1173 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for Google Test itself. This file verifies that the parameter
+// generators objects produce correct parameter sequences and that
+// Google Test runtime instantiates correct tests from those sequences.
+
+#include "test/googletest-param-test-test.h"
+
+#include <algorithm>
+#include <iostream>
+#include <list>
+#include <set>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"  // for UnitTestOptions
+
+using ::std::sort;
+using ::std::vector;
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Bool;
+using ::testing::Combine;
+using ::testing::ConvertGenerator;
+using ::testing::Message;
+using ::testing::Range;
+using ::testing::TestWithParam;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+using ::testing::internal::ParamGenerator;
+using ::testing::internal::UnitTestOptions;
+
+// Prints a value to a string.
+//
+// FIXME: remove PrintValue() when we move matchers and
+// EXPECT_THAT() from Google Mock to Google Test.  At that time, we
+// can write EXPECT_THAT(x, Eq(y)) to compare two tuples x and y, as
+// EXPECT_THAT() and the matchers know how to print tuples.
+template <typename T>
+::std::string PrintValue(const T& value) {
+  return testing::PrintToString(value);
+}
+
+// Verifies that a sequence generated by the generator and accessed
+// via the iterator object matches the expected one using Google Test
+// assertions.
+template <typename T, size_t N>
+void VerifyGenerator(const ParamGenerator<T>& generator,
+                     const T (&expected_values)[N]) {
+  typename ParamGenerator<T>::iterator it = generator.begin();
+  for (size_t i = 0; i < N; ++i) {
+    ASSERT_FALSE(it == generator.end())
+        << "At element " << i << " when accessing via an iterator "
+        << "created with the copy constructor.\n";
+    // We cannot use EXPECT_EQ() here as the values may be tuples,
+    // which don't support <<.
+    EXPECT_TRUE(expected_values[i] == *it)
+        << "where i is " << i << ", expected_values[i] is "
+        << PrintValue(expected_values[i]) << ", *it is " << PrintValue(*it)
+        << ", and 'it' is an iterator created with the copy constructor.\n";
+    ++it;
+  }
+  EXPECT_TRUE(it == generator.end())
+      << "At the presumed end of sequence when accessing via an iterator "
+      << "created with the copy constructor.\n";
+
+  // Test the iterator assignment. The following lines verify that
+  // the sequence accessed via an iterator initialized via the
+  // assignment operator (as opposed to a copy constructor) matches
+  // just the same.
+  it = generator.begin();
+  for (size_t i = 0; i < N; ++i) {
+    ASSERT_FALSE(it == generator.end())
+        << "At element " << i << " when accessing via an iterator "
+        << "created with the assignment operator.\n";
+    EXPECT_TRUE(expected_values[i] == *it)
+        << "where i is " << i << ", expected_values[i] is "
+        << PrintValue(expected_values[i]) << ", *it is " << PrintValue(*it)
+        << ", and 'it' is an iterator created with the copy constructor.\n";
+    ++it;
+  }
+  EXPECT_TRUE(it == generator.end())
+      << "At the presumed end of sequence when accessing via an iterator "
+      << "created with the assignment operator.\n";
+}
+
+template <typename T>
+void VerifyGeneratorIsEmpty(const ParamGenerator<T>& generator) {
+  typename ParamGenerator<T>::iterator it = generator.begin();
+  EXPECT_TRUE(it == generator.end());
+
+  it = generator.begin();
+  EXPECT_TRUE(it == generator.end());
+}
+
+// Generator tests. They test that each of the provided generator functions
+// generates an expected sequence of values. The general test pattern
+// instantiates a generator using one of the generator functions,
+// checks the sequence produced by the generator using its iterator API,
+// and then resets the iterator back to the beginning of the sequence
+// and checks the sequence again.
+
+// Tests that iterators produced by generator functions conform to the
+// ForwardIterator concept.
+TEST(IteratorTest, ParamIteratorConformsToForwardIteratorConcept) {
+  const ParamGenerator<int> gen = Range(0, 10);
+  ParamGenerator<int>::iterator it = gen.begin();
+
+  // Verifies that iterator initialization works as expected.
+  ParamGenerator<int>::iterator it2 = it;
+  EXPECT_TRUE(*it == *it2) << "Initialized iterators must point to the "
+                           << "element same as its source points to";
+
+  // Verifies that iterator assignment works as expected.
+  ++it;
+  EXPECT_FALSE(*it == *it2);
+  it2 = it;
+  EXPECT_TRUE(*it == *it2) << "Assigned iterators must point to the "
+                           << "element same as its source points to";
+
+  // Verifies that prefix operator++() returns *this.
+  EXPECT_EQ(&it, &(++it)) << "Result of the prefix operator++ must be "
+                          << "refer to the original object";
+
+  // Verifies that the result of the postfix operator++ points to the value
+  // pointed to by the original iterator.
+  int original_value = *it;  // Have to compute it outside of macro call to be
+                             // unaffected by the parameter evaluation order.
+  EXPECT_EQ(original_value, *(it++));
+
+  // Verifies that prefix and postfix operator++() advance an iterator
+  // all the same.
+  it2 = it;
+  ++it;
+  ++it2;
+  EXPECT_TRUE(*it == *it2);
+}
+
+// Tests that Range() generates the expected sequence.
+TEST(RangeTest, IntRangeWithDefaultStep) {
+  const ParamGenerator<int> gen = Range(0, 3);
+  const int expected_values[] = {0, 1, 2};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that Range() generates the single element sequence
+// as expected when provided with range limits that are equal.
+TEST(RangeTest, IntRangeSingleValue) {
+  const ParamGenerator<int> gen = Range(0, 1);
+  const int expected_values[] = {0};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that Range() with generates empty sequence when
+// supplied with an empty range.
+TEST(RangeTest, IntRangeEmpty) {
+  const ParamGenerator<int> gen = Range(0, 0);
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that Range() with custom step (greater then one) generates
+// the expected sequence.
+TEST(RangeTest, IntRangeWithCustomStep) {
+  const ParamGenerator<int> gen = Range(0, 9, 3);
+  const int expected_values[] = {0, 3, 6};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Range() with custom step (greater then one) generates
+// the expected sequence when the last element does not fall on the
+// upper range limit. Sequences generated by Range() must not have
+// elements beyond the range limits.
+TEST(RangeTest, IntRangeWithCustomStepOverUpperBound) {
+  const ParamGenerator<int> gen = Range(0, 4, 3);
+  const int expected_values[] = {0, 3};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Verifies that Range works with user-defined types that define
+// copy constructor, operator=(), operator+(), and operator<().
+class DogAdder {
+ public:
+  explicit DogAdder(const char* a_value) : value_(a_value) {}
+  DogAdder(const DogAdder& other) : value_(other.value_.c_str()) {}
+
+  DogAdder operator=(const DogAdder& other) {
+    if (this != &other) value_ = other.value_;
+    return *this;
+  }
+  DogAdder operator+(const DogAdder& other) const {
+    Message msg;
+    msg << value_ << other.value_;
+    return DogAdder(msg.GetString().c_str());
+  }
+  bool operator<(const DogAdder& other) const { return value_ < other.value_; }
+  const std::string& value() const { return value_; }
+
+ private:
+  std::string value_;
+};
+
+TEST(RangeTest, WorksWithACustomType) {
+  const ParamGenerator<DogAdder> gen =
+      Range(DogAdder("cat"), DogAdder("catdogdog"), DogAdder("dog"));
+  ParamGenerator<DogAdder>::iterator it = gen.begin();
+
+  ASSERT_FALSE(it == gen.end());
+  EXPECT_STREQ("cat", it->value().c_str());
+
+  ASSERT_FALSE(++it == gen.end());
+  EXPECT_STREQ("catdog", it->value().c_str());
+
+  EXPECT_TRUE(++it == gen.end());
+}
+
+class IntWrapper {
+ public:
+  explicit IntWrapper(int a_value) : value_(a_value) {}
+  IntWrapper(const IntWrapper& other) : value_(other.value_) {}
+
+  IntWrapper operator=(const IntWrapper& other) {
+    value_ = other.value_;
+    return *this;
+  }
+  // operator+() adds a different type.
+  IntWrapper operator+(int other) const { return IntWrapper(value_ + other); }
+  bool operator<(const IntWrapper& other) const {
+    return value_ < other.value_;
+  }
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+TEST(RangeTest, WorksWithACustomTypeWithDifferentIncrementType) {
+  const ParamGenerator<IntWrapper> gen = Range(IntWrapper(0), IntWrapper(2));
+  ParamGenerator<IntWrapper>::iterator it = gen.begin();
+
+  ASSERT_FALSE(it == gen.end());
+  EXPECT_EQ(0, it->value());
+
+  ASSERT_FALSE(++it == gen.end());
+  EXPECT_EQ(1, it->value());
+
+  EXPECT_TRUE(++it == gen.end());
+}
+
+// Tests that ValuesIn() with an array parameter generates
+// the expected sequence.
+TEST(ValuesInTest, ValuesInArray) {
+  int array[] = {3, 5, 8};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Tests that ValuesIn() with a const array parameter generates
+// the expected sequence.
+TEST(ValuesInTest, ValuesInConstArray) {
+  const int array[] = {3, 5, 8};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Edge case. Tests that ValuesIn() with an array parameter containing a
+// single element generates the single element sequence.
+TEST(ValuesInTest, ValuesInSingleElementArray) {
+  int array[] = {42};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Tests that ValuesIn() generates the expected sequence for an STL
+// container (vector).
+TEST(ValuesInTest, ValuesInVector) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(3);
+  values.push_back(5);
+  values.push_back(8);
+  const ParamGenerator<int> gen = ValuesIn(values);
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that ValuesIn() generates the expected sequence.
+TEST(ValuesInTest, ValuesInIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(3);
+  values.push_back(5);
+  values.push_back(8);
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that ValuesIn() provided with an iterator range specifying a
+// single value generates a single-element sequence.
+TEST(ValuesInTest, ValuesInSingleElementIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(42);
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  const int expected_values[] = {42};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that ValuesIn() provided with an empty iterator range
+// generates an empty sequence.
+TEST(ValuesInTest, ValuesInEmptyIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that the Values() generates the expected sequence.
+TEST(ValuesTest, ValuesWorks) {
+  const ParamGenerator<int> gen = Values(3, 5, 8);
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Values() generates the expected sequences from elements of
+// different types convertible to ParamGenerator's parameter type.
+TEST(ValuesTest, ValuesWorksForValuesOfCompatibleTypes) {
+  const ParamGenerator<double> gen = Values(3, 5.0f, 8.0);
+
+  const double expected_values[] = {3.0, 5.0, 8.0};
+  VerifyGenerator(gen, expected_values);
+}
+
+TEST(ValuesTest, ValuesWorksForMaxLengthList) {
+  const ParamGenerator<int> gen =
+      Values(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150,
+             160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280,
+             290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410,
+             420, 430, 440, 450, 460, 470, 480, 490, 500);
+
+  const int expected_values[] = {
+      10,  20,  30,  40,  50,  60,  70,  80,  90,  100, 110, 120, 130,
+      140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260,
+      270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390,
+      400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case test. Tests that single-parameter Values() generates the sequence
+// with the single value.
+TEST(ValuesTest, ValuesWithSingleParameter) {
+  const ParamGenerator<int> gen = Values(42);
+
+  const int expected_values[] = {42};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Bool() generates sequence (false, true).
+TEST(BoolTest, BoolWorks) {
+  const ParamGenerator<bool> gen = Bool();
+
+  const bool expected_values[] = {false, true};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Combine() with two parameters generates the expected sequence.
+TEST(CombineTest, CombineWithTwoParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<std::tuple<const char*, int>> gen =
+      Combine(Values(foo, bar), Values(3, 4));
+
+  std::tuple<const char*, int> expected_values[] = {
+      std::make_tuple(foo, 3), std::make_tuple(foo, 4), std::make_tuple(bar, 3),
+      std::make_tuple(bar, 4)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Combine() with three parameters generates the expected sequence.
+TEST(CombineTest, CombineWithThreeParameters) {
+  const ParamGenerator<std::tuple<int, int, int>> gen =
+      Combine(Values(0, 1), Values(3, 4), Values(5, 6));
+  std::tuple<int, int, int> expected_values[] = {
+      std::make_tuple(0, 3, 5), std::make_tuple(0, 3, 6),
+      std::make_tuple(0, 4, 5), std::make_tuple(0, 4, 6),
+      std::make_tuple(1, 3, 5), std::make_tuple(1, 3, 6),
+      std::make_tuple(1, 4, 5), std::make_tuple(1, 4, 6)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that the Combine() with the first parameter generating a single value
+// sequence generates a sequence with the number of elements equal to the
+// number of elements in the sequence generated by the second parameter.
+TEST(CombineTest, CombineWithFirstParameterSingleValue) {
+  const ParamGenerator<std::tuple<int, int>> gen =
+      Combine(Values(42), Values(0, 1));
+
+  std::tuple<int, int> expected_values[] = {std::make_tuple(42, 0),
+                                            std::make_tuple(42, 1)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that the Combine() with the second parameter generating a single value
+// sequence generates a sequence with the number of elements equal to the
+// number of elements in the sequence generated by the first parameter.
+TEST(CombineTest, CombineWithSecondParameterSingleValue) {
+  const ParamGenerator<std::tuple<int, int>> gen =
+      Combine(Values(0, 1), Values(42));
+
+  std::tuple<int, int> expected_values[] = {std::make_tuple(0, 42),
+                                            std::make_tuple(1, 42)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that when the first parameter produces an empty sequence,
+// Combine() produces an empty sequence, too.
+TEST(CombineTest, CombineWithFirstParameterEmptyRange) {
+  const ParamGenerator<std::tuple<int, int>> gen =
+      Combine(Range(0, 0), Values(0, 1));
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that when the second parameter produces an empty sequence,
+// Combine() produces an empty sequence, too.
+TEST(CombineTest, CombineWithSecondParameterEmptyRange) {
+  const ParamGenerator<std::tuple<int, int>> gen =
+      Combine(Values(0, 1), Range(1, 1));
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Edge case. Tests that combine works with the maximum number
+// of parameters supported by Google Test (currently 10).
+TEST(CombineTest, CombineWithMaxNumberOfParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<
+      std::tuple<const char*, int, int, int, int, int, int, int, int, int>>
+      gen =
+          Combine(Values(foo, bar), Values(1), Values(2), Values(3), Values(4),
+                  Values(5), Values(6), Values(7), Values(8), Values(9));
+
+  std::tuple<const char*, int, int, int, int, int, int, int, int, int>
+      expected_values[] = {std::make_tuple(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+                           std::make_tuple(bar, 1, 2, 3, 4, 5, 6, 7, 8, 9)};
+  VerifyGenerator(gen, expected_values);
+}
+
+class NonDefaultConstructAssignString {
+ public:
+  NonDefaultConstructAssignString(const std::string& s) : str_(s) {}
+  NonDefaultConstructAssignString() = delete;
+  NonDefaultConstructAssignString(const NonDefaultConstructAssignString&) =
+      default;
+  NonDefaultConstructAssignString& operator=(
+      const NonDefaultConstructAssignString&) = delete;
+  ~NonDefaultConstructAssignString() = default;
+
+  const std::string& str() const { return str_; }
+
+ private:
+  std::string str_;
+};
+
+TEST(CombineTest, NonDefaultConstructAssign) {
+  const ParamGenerator<std::tuple<int, NonDefaultConstructAssignString>> gen =
+      Combine(Values(0, 1), Values(NonDefaultConstructAssignString("A"),
+                                   NonDefaultConstructAssignString("B")));
+
+  ParamGenerator<std::tuple<int, NonDefaultConstructAssignString>>::iterator
+      it = gen.begin();
+
+  EXPECT_EQ(0, std::get<0>(*it));
+  EXPECT_EQ("A", std::get<1>(*it).str());
+  ++it;
+
+  EXPECT_EQ(0, std::get<0>(*it));
+  EXPECT_EQ("B", std::get<1>(*it).str());
+  ++it;
+
+  EXPECT_EQ(1, std::get<0>(*it));
+  EXPECT_EQ("A", std::get<1>(*it).str());
+  ++it;
+
+  EXPECT_EQ(1, std::get<0>(*it));
+  EXPECT_EQ("B", std::get<1>(*it).str());
+  ++it;
+
+  EXPECT_TRUE(it == gen.end());
+}
+
+template <typename T>
+class ConstructFromT {
+ public:
+  explicit ConstructFromT(const T& t) : t_(t) {}
+  template <typename... Args,
+            typename std::enable_if<sizeof...(Args) != 1, int>::type = 0>
+  ConstructFromT(Args&&... args) : t_(std::forward<Args>(args)...) {}
+
+  bool operator==(const ConstructFromT& other) const { return other.t_ == t_; }
+
+  const T& get() const { return t_; }
+
+ private:
+  T t_;
+};
+
+TEST(ConvertTest, CombineWithTwoParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<ConstructFromT<std::tuple<const char*, int>>> gen =
+      ConvertGenerator<std::tuple<const char*, int>>(
+          Combine(Values(foo, bar), Values(3, 4)));
+
+  ConstructFromT<std::tuple<const char*, int>> expected_values[] = {
+      {foo, 3}, {foo, 4}, {bar, 3}, {bar, 4}};
+  VerifyGenerator(gen, expected_values);
+}
+
+TEST(ConvertTest, NonDefaultConstructAssign) {
+  const ParamGenerator<
+      ConstructFromT<std::tuple<int, NonDefaultConstructAssignString>>>
+      gen = ConvertGenerator<std::tuple<int, NonDefaultConstructAssignString>>(
+          Combine(Values(0, 1), Values(NonDefaultConstructAssignString("A"),
+                                       NonDefaultConstructAssignString("B"))));
+
+  ParamGenerator<ConstructFromT<
+      std::tuple<int, NonDefaultConstructAssignString>>>::iterator it =
+      gen.begin();
+
+  EXPECT_EQ(0, std::get<0>(it->get()));
+  EXPECT_EQ("A", std::get<1>(it->get()).str());
+  ++it;
+
+  EXPECT_EQ(0, std::get<0>(it->get()));
+  EXPECT_EQ("B", std::get<1>(it->get()).str());
+  ++it;
+
+  EXPECT_EQ(1, std::get<0>(it->get()));
+  EXPECT_EQ("A", std::get<1>(it->get()).str());
+  ++it;
+
+  EXPECT_EQ(1, std::get<0>(it->get()));
+  EXPECT_EQ("B", std::get<1>(it->get()).str());
+  ++it;
+
+  EXPECT_TRUE(it == gen.end());
+}
+
+// Tests that an generator produces correct sequence after being
+// assigned from another generator.
+TEST(ParamGeneratorTest, AssignmentWorks) {
+  ParamGenerator<int> gen = Values(1, 2);
+  const ParamGenerator<int> gen2 = Values(3, 4);
+  gen = gen2;
+
+  const int expected_values[] = {3, 4};
+  VerifyGenerator(gen, expected_values);
+}
+
+// This test verifies that the tests are expanded and run as specified:
+// one test per element from the sequence produced by the generator
+// specified in INSTANTIATE_TEST_SUITE_P. It also verifies that the test's
+// fixture constructor, SetUp(), and TearDown() have run and have been
+// supplied with the correct parameters.
+
+// The use of environment object allows detection of the case where no test
+// case functionality is run at all. In this case TearDownTestSuite will not
+// be able to detect missing tests, naturally.
+template <int kExpectedCalls>
+class TestGenerationEnvironment : public ::testing::Environment {
+ public:
+  static TestGenerationEnvironment* Instance() {
+    static TestGenerationEnvironment* instance = new TestGenerationEnvironment;
+    return instance;
+  }
+
+  void FixtureConstructorExecuted() { fixture_constructor_count_++; }
+  void SetUpExecuted() { set_up_count_++; }
+  void TearDownExecuted() { tear_down_count_++; }
+  void TestBodyExecuted() { test_body_count_++; }
+
+  void TearDown() override {
+    // If all MultipleTestGenerationTest tests have been de-selected
+    // by the filter flag, the following checks make no sense.
+    bool perform_check = false;
+
+    for (int i = 0; i < kExpectedCalls; ++i) {
+      Message msg;
+      msg << "TestsExpandedAndRun/" << i;
+      if (UnitTestOptions::FilterMatchesTest(
+              "TestExpansionModule/MultipleTestGenerationTest",
+              msg.GetString().c_str())) {
+        perform_check = true;
+      }
+    }
+    if (perform_check) {
+      EXPECT_EQ(kExpectedCalls, fixture_constructor_count_)
+          << "Fixture constructor of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, set_up_count_)
+          << "Fixture SetUp method of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, tear_down_count_)
+          << "Fixture TearDown method of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, test_body_count_)
+          << "Test in ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+    }
+  }
+
+ private:
+  TestGenerationEnvironment()
+      : fixture_constructor_count_(0),
+        set_up_count_(0),
+        tear_down_count_(0),
+        test_body_count_(0) {}
+
+  int fixture_constructor_count_;
+  int set_up_count_;
+  int tear_down_count_;
+  int test_body_count_;
+
+  TestGenerationEnvironment(const TestGenerationEnvironment&) = delete;
+  TestGenerationEnvironment& operator=(const TestGenerationEnvironment&) =
+      delete;
+};
+
+const int test_generation_params[] = {36, 42, 72};
+
+class TestGenerationTest : public TestWithParam<int> {
+ public:
+  enum {
+    PARAMETER_COUNT =
+        sizeof(test_generation_params) / sizeof(test_generation_params[0])
+  };
+
+  typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;
+
+  TestGenerationTest() {
+    Environment::Instance()->FixtureConstructorExecuted();
+    current_parameter_ = GetParam();
+  }
+  void SetUp() override {
+    Environment::Instance()->SetUpExecuted();
+    EXPECT_EQ(current_parameter_, GetParam());
+  }
+  void TearDown() override {
+    Environment::Instance()->TearDownExecuted();
+    EXPECT_EQ(current_parameter_, GetParam());
+  }
+
+  static void SetUpTestSuite() {
+    bool all_tests_in_test_case_selected = true;
+
+    for (int i = 0; i < PARAMETER_COUNT; ++i) {
+      Message test_name;
+      test_name << "TestsExpandedAndRun/" << i;
+      if (!UnitTestOptions::FilterMatchesTest(
+              "TestExpansionModule/MultipleTestGenerationTest",
+              test_name.GetString())) {
+        all_tests_in_test_case_selected = false;
+      }
+    }
+    EXPECT_TRUE(all_tests_in_test_case_selected)
+        << "When running the TestGenerationTest test case all of its tests\n"
+        << "must be selected by the filter flag for the test case to pass.\n"
+        << "If not all of them are enabled, we can't reliably conclude\n"
+        << "that the correct number of tests have been generated.";
+
+    collected_parameters_.clear();
+  }
+
+  static void TearDownTestSuite() {
+    vector<int> expected_values(test_generation_params,
+                                test_generation_params + PARAMETER_COUNT);
+    // Test execution order is not guaranteed by Google Test,
+    // so the order of values in collected_parameters_ can be
+    // different and we have to sort to compare.
+    sort(expected_values.begin(), expected_values.end());
+    sort(collected_parameters_.begin(), collected_parameters_.end());
+
+    EXPECT_TRUE(collected_parameters_ == expected_values);
+  }
+
+ protected:
+  int current_parameter_;
+  static vector<int> collected_parameters_;
+
+ private:
+  TestGenerationTest(const TestGenerationTest&) = delete;
+  TestGenerationTest& operator=(const TestGenerationTest&) = delete;
+};
+vector<int> TestGenerationTest::collected_parameters_;
+
+TEST_P(TestGenerationTest, TestsExpandedAndRun) {
+  Environment::Instance()->TestBodyExecuted();
+  EXPECT_EQ(current_parameter_, GetParam());
+  collected_parameters_.push_back(GetParam());
+}
+INSTANTIATE_TEST_SUITE_P(TestExpansionModule, TestGenerationTest,
+                         ValuesIn(test_generation_params));
+
+// This test verifies that the element sequence (third parameter of
+// INSTANTIATE_TEST_SUITE_P) is evaluated in InitGoogleTest() and neither at
+// the call site of INSTANTIATE_TEST_SUITE_P nor in RUN_ALL_TESTS().  For
+// that, we declare param_value_ to be a static member of
+// GeneratorEvaluationTest and initialize it to 0.  We set it to 1 in
+// main(), just before invocation of InitGoogleTest().  After calling
+// InitGoogleTest(), we set the value to 2.  If the sequence is evaluated
+// before or after InitGoogleTest, INSTANTIATE_TEST_SUITE_P will create a
+// test with parameter other than 1, and the test body will fail the
+// assertion.
+class GeneratorEvaluationTest : public TestWithParam<int> {
+ public:
+  static int param_value() { return param_value_; }
+  static void set_param_value(int param_value) { param_value_ = param_value; }
+
+ private:
+  static int param_value_;
+};
+int GeneratorEvaluationTest::param_value_ = 0;
+
+TEST_P(GeneratorEvaluationTest, GeneratorsEvaluatedInMain) {
+  EXPECT_EQ(1, GetParam());
+}
+INSTANTIATE_TEST_SUITE_P(GenEvalModule, GeneratorEvaluationTest,
+                         Values(GeneratorEvaluationTest::param_value()));
+
+// Tests that generators defined in a different translation unit are
+// functional. Generator extern_gen is defined in gtest-param-test_test2.cc.
+extern ParamGenerator<int> extern_gen;
+class ExternalGeneratorTest : public TestWithParam<int> {};
+TEST_P(ExternalGeneratorTest, ExternalGenerator) {
+  // Sequence produced by extern_gen contains only a single value
+  // which we verify here.
+  EXPECT_EQ(GetParam(), 33);
+}
+INSTANTIATE_TEST_SUITE_P(ExternalGeneratorModule, ExternalGeneratorTest,
+                         extern_gen);
+
+// Tests that a parameterized test case can be defined in one translation
+// unit and instantiated in another. This test will be instantiated in
+// gtest-param-test_test2.cc. ExternalInstantiationTest fixture class is
+// defined in gtest-param-test_test.h.
+TEST_P(ExternalInstantiationTest, IsMultipleOf33) {
+  EXPECT_EQ(0, GetParam() % 33);
+}
+
+// Tests that a parameterized test case can be instantiated with multiple
+// generators.
+class MultipleInstantiationTest : public TestWithParam<int> {};
+TEST_P(MultipleInstantiationTest, AllowsMultipleInstances) {}
+INSTANTIATE_TEST_SUITE_P(Sequence1, MultipleInstantiationTest, Values(1, 2));
+INSTANTIATE_TEST_SUITE_P(Sequence2, MultipleInstantiationTest, Range(3, 5));
+
+// Tests that a parameterized test case can be instantiated
+// in multiple translation units. This test will be instantiated
+// here and in gtest-param-test_test2.cc.
+// InstantiationInMultipleTranslationUnitsTest fixture class
+// is defined in gtest-param-test_test.h.
+TEST_P(InstantiationInMultipleTranslationUnitsTest, IsMultipleOf42) {
+  EXPECT_EQ(0, GetParam() % 42);
+}
+INSTANTIATE_TEST_SUITE_P(Sequence1, InstantiationInMultipleTranslationUnitsTest,
+                         Values(42, 42 * 2));
+
+// Tests that each iteration of parameterized test runs in a separate test
+// object.
+class SeparateInstanceTest : public TestWithParam<int> {
+ public:
+  SeparateInstanceTest() : count_(0) {}
+
+  static void TearDownTestSuite() {
+    EXPECT_GE(global_count_, 2)
+        << "If some (but not all) SeparateInstanceTest tests have been "
+        << "filtered out this test will fail. Make sure that all "
+        << "GeneratorEvaluationTest are selected or de-selected together "
+        << "by the test filter.";
+  }
+
+ protected:
+  int count_;
+  static int global_count_;
+};
+int SeparateInstanceTest::global_count_ = 0;
+
+TEST_P(SeparateInstanceTest, TestsRunInSeparateInstances) {
+  EXPECT_EQ(0, count_++);
+  global_count_++;
+}
+INSTANTIATE_TEST_SUITE_P(FourElemSequence, SeparateInstanceTest, Range(1, 4));
+
+// Tests that all instantiations of a test have named appropriately. Test
+// defined with TEST_P(TestSuiteName, TestName) and instantiated with
+// INSTANTIATE_TEST_SUITE_P(SequenceName, TestSuiteName, generator) must be
+// named SequenceName/TestSuiteName.TestName/i, where i is the 0-based index of
+// the sequence element used to instantiate the test.
+class NamingTest : public TestWithParam<int> {};
+
+TEST_P(NamingTest, TestsReportCorrectNamesAndParameters) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_STREQ("ZeroToFiveSequence/NamingTest", test_info->test_suite_name());
+
+  Message index_stream;
+  index_stream << "TestsReportCorrectNamesAndParameters/" << GetParam();
+  EXPECT_STREQ(index_stream.GetString().c_str(), test_info->name());
+
+  EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
+}
+
+INSTANTIATE_TEST_SUITE_P(ZeroToFiveSequence, NamingTest, Range(0, 5));
+
+// Tests that macros in test names are expanded correctly.
+class MacroNamingTest : public TestWithParam<int> {};
+
+#define PREFIX_WITH_FOO(test_name) Foo##test_name
+#define PREFIX_WITH_MACRO(test_name) Macro##test_name
+
+TEST_P(PREFIX_WITH_MACRO(NamingTest), PREFIX_WITH_FOO(SomeTestName)) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_STREQ("FortyTwo/MacroNamingTest", test_info->test_suite_name());
+  EXPECT_STREQ("FooSomeTestName/0", test_info->name());
+}
+
+INSTANTIATE_TEST_SUITE_P(FortyTwo, MacroNamingTest, Values(42));
+
+// Tests the same thing for non-parametrized tests.
+class MacroNamingTestNonParametrized : public ::testing::Test {};
+
+TEST_F(PREFIX_WITH_MACRO(NamingTestNonParametrized),
+       PREFIX_WITH_FOO(SomeTestName)) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_STREQ("MacroNamingTestNonParametrized", test_info->test_suite_name());
+  EXPECT_STREQ("FooSomeTestName", test_info->name());
+}
+
+TEST(MacroNameing, LookupNames) {
+  std::set<std::string> know_suite_names, know_test_names;
+
+  const auto& ins = testing::UnitTest::GetInstance();
+  int ts = 0;
+  while (const testing::TestSuite* suite = ins->GetTestSuite(ts++)) {
+    know_suite_names.insert(suite->name());
+
+    int ti = 0;
+    while (const testing::TestInfo* info = suite->GetTestInfo(ti++)) {
+      know_test_names.insert(std::string(suite->name()) + "." + info->name());
+    }
+  }
+
+  // Check that the expected form of the test suit name actually exists.
+  EXPECT_NE(  //
+      know_suite_names.find("FortyTwo/MacroNamingTest"),
+      know_suite_names.end());
+  EXPECT_NE(know_suite_names.find("MacroNamingTestNonParametrized"),
+            know_suite_names.end());
+  // Check that the expected form of the test name actually exists.
+  EXPECT_NE(  //
+      know_test_names.find("FortyTwo/MacroNamingTest.FooSomeTestName/0"),
+      know_test_names.end());
+  EXPECT_NE(
+      know_test_names.find("MacroNamingTestNonParametrized.FooSomeTestName"),
+      know_test_names.end());
+}
+
+// Tests that user supplied custom parameter names are working correctly.
+// Runs the test with a builtin helper method which uses PrintToString,
+// as well as a custom function and custom functor to ensure all possible
+// uses work correctly.
+class CustomFunctorNamingTest : public TestWithParam<std::string> {};
+TEST_P(CustomFunctorNamingTest, CustomTestNames) {}
+
+struct CustomParamNameFunctor {
+  std::string operator()(const ::testing::TestParamInfo<std::string>& inf) {
+    return inf.param;
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(CustomParamNameFunctor, CustomFunctorNamingTest,
+                         Values(std::string("FunctorName")),
+                         CustomParamNameFunctor());
+
+INSTANTIATE_TEST_SUITE_P(AllAllowedCharacters, CustomFunctorNamingTest,
+                         Values("abcdefghijklmnopqrstuvwxyz",
+                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "01234567890_"),
+                         CustomParamNameFunctor());
+
+inline std::string CustomParamNameFunction(
+    const ::testing::TestParamInfo<std::string>& inf) {
+  return inf.param;
+}
+
+class CustomFunctionNamingTest : public TestWithParam<std::string> {};
+TEST_P(CustomFunctionNamingTest, CustomTestNames) {}
+
+INSTANTIATE_TEST_SUITE_P(CustomParamNameFunction, CustomFunctionNamingTest,
+                         Values(std::string("FunctionName")),
+                         CustomParamNameFunction);
+
+INSTANTIATE_TEST_SUITE_P(CustomParamNameFunctionP, CustomFunctionNamingTest,
+                         Values(std::string("FunctionNameP")),
+                         &CustomParamNameFunction);
+
+// Test custom naming with a lambda
+
+class CustomLambdaNamingTest : public TestWithParam<std::string> {};
+TEST_P(CustomLambdaNamingTest, CustomTestNames) {}
+
+INSTANTIATE_TEST_SUITE_P(CustomParamNameLambda, CustomLambdaNamingTest,
+                         Values(std::string("LambdaName")),
+                         [](const ::testing::TestParamInfo<std::string>& inf) {
+                           return inf.param;
+                         });
+
+TEST(CustomNamingTest, CheckNameRegistry) {
+  const auto& unit_test = ::testing::UnitTest::GetInstance();
+  std::set<std::string> test_names;
+  for (int suite_num = 0; suite_num < unit_test->total_test_suite_count();
+       ++suite_num) {
+    const ::testing::TestSuite* test_suite = unit_test->GetTestSuite(suite_num);
+    for (int test_num = 0; test_num < test_suite->total_test_count();
+         ++test_num) {
+      const ::testing::TestInfo* test_info = test_suite->GetTestInfo(test_num);
+      test_names.insert(std::string(test_info->name()));
+    }
+  }
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctorName"));
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctionName"));
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctionNameP"));
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/LambdaName"));
+}
+
+// Test a numeric name to ensure PrintToStringParamName works correctly.
+
+class CustomIntegerNamingTest : public TestWithParam<int> {};
+
+TEST_P(CustomIntegerNamingTest, TestsReportCorrectNames) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+  Message test_name_stream;
+  test_name_stream << "TestsReportCorrectNames/" << GetParam();
+  EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
+}
+
+INSTANTIATE_TEST_SUITE_P(PrintToString, CustomIntegerNamingTest, Range(0, 5),
+                         ::testing::PrintToStringParamName());
+
+// Test a custom struct with PrintToString.
+
+struct CustomStruct {
+  explicit CustomStruct(int value) : x(value) {}
+  int x;
+};
+
+std::ostream& operator<<(std::ostream& stream, const CustomStruct& val) {
+  stream << val.x;
+  return stream;
+}
+
+class CustomStructNamingTest : public TestWithParam<CustomStruct> {};
+
+TEST_P(CustomStructNamingTest, TestsReportCorrectNames) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+  Message test_name_stream;
+  test_name_stream << "TestsReportCorrectNames/" << GetParam();
+  EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
+}
+
+INSTANTIATE_TEST_SUITE_P(PrintToString, CustomStructNamingTest,
+                         Values(CustomStruct(0), CustomStruct(1)),
+                         ::testing::PrintToStringParamName());
+
+// Test that using a stateful parameter naming function works as expected.
+
+struct StatefulNamingFunctor {
+  StatefulNamingFunctor() : sum(0) {}
+  std::string operator()(const ::testing::TestParamInfo<int>& info) {
+    int value = info.param + sum;
+    sum += info.param;
+    return ::testing::PrintToString(value);
+  }
+  int sum;
+};
+
+class StatefulNamingTest : public ::testing::TestWithParam<int> {
+ protected:
+  StatefulNamingTest() : sum_(0) {}
+  int sum_;
+};
+
+TEST_P(StatefulNamingTest, TestsReportCorrectNames) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+  sum_ += GetParam();
+  Message test_name_stream;
+  test_name_stream << "TestsReportCorrectNames/" << sum_;
+  EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
+}
+
+INSTANTIATE_TEST_SUITE_P(StatefulNamingFunctor, StatefulNamingTest, Range(0, 5),
+                         StatefulNamingFunctor());
+
+// Class that cannot be streamed into an ostream.  It needs to be copyable
+// (and, in case of MSVC, also assignable) in order to be a test parameter
+// type.  Its default copy constructor and assignment operator do exactly
+// what we need.
+class Unstreamable {
+ public:
+  explicit Unstreamable(int value) : value_(value) {}
+  // -Wunused-private-field: dummy accessor for `value_`.
+  const int& dummy_value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+class CommentTest : public TestWithParam<Unstreamable> {};
+
+TEST_P(CommentTest, TestsCorrectlyReportUnstreamableParams) {
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
+}
+
+INSTANTIATE_TEST_SUITE_P(InstantiationWithComments, CommentTest,
+                         Values(Unstreamable(1)));
+
+// Verify that we can create a hierarchy of test fixtures, where the base
+// class fixture is not parameterized and the derived class is. In this case
+// ParameterizedDerivedTest inherits from NonParameterizedBaseTest.  We
+// perform simple tests on both.
+class NonParameterizedBaseTest : public ::testing::Test {
+ public:
+  NonParameterizedBaseTest() : n_(17) {}
+
+ protected:
+  int n_;
+};
+
+class ParameterizedDerivedTest : public NonParameterizedBaseTest,
+                                 public ::testing::WithParamInterface<int> {
+ protected:
+  ParameterizedDerivedTest() : count_(0) {}
+  int count_;
+  static int global_count_;
+};
+
+int ParameterizedDerivedTest::global_count_ = 0;
+
+TEST_F(NonParameterizedBaseTest, FixtureIsInitialized) { EXPECT_EQ(17, n_); }
+
+TEST_P(ParameterizedDerivedTest, SeesSequence) {
+  EXPECT_EQ(17, n_);
+  EXPECT_EQ(0, count_++);
+  EXPECT_EQ(GetParam(), global_count_++);
+}
+
+class ParameterizedDeathTest : public ::testing::TestWithParam<int> {};
+
+TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
+  EXPECT_DEATH_IF_SUPPORTED(GetParam(), ".* value-parameterized test .*");
+}
+
+INSTANTIATE_TEST_SUITE_P(RangeZeroToFive, ParameterizedDerivedTest,
+                         Range(0, 5));
+
+// Tests param generator working with Enums
+enum MyEnums {
+  ENUM1 = 1,
+  ENUM2 = 3,
+  ENUM3 = 8,
+};
+
+class MyEnumTest : public testing::TestWithParam<MyEnums> {};
+
+TEST_P(MyEnumTest, ChecksParamMoreThanZero) { EXPECT_GE(10, GetParam()); }
+INSTANTIATE_TEST_SUITE_P(MyEnumTests, MyEnumTest,
+                         ::testing::Values(ENUM1, ENUM2, 0));
+
+namespace works_here {
+// Never used not instantiated, this should work.
+class NotUsedTest : public testing::TestWithParam<int> {};
+
+///////
+// Never used not instantiated, this should work.
+template <typename T>
+class NotUsedTypeTest : public testing::Test {};
+TYPED_TEST_SUITE_P(NotUsedTypeTest);
+
+// Used but not instantiated, this would fail. but...
+class NotInstantiatedTest : public testing::TestWithParam<int> {};
+// ... we mark is as allowed.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NotInstantiatedTest);
+
+TEST_P(NotInstantiatedTest, Used) {}
+
+using OtherName = NotInstantiatedTest;
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OtherName);
+TEST_P(OtherName, Used) {}
+
+// Used but not instantiated, this would fail. but...
+template <typename T>
+class NotInstantiatedTypeTest : public testing::Test {};
+TYPED_TEST_SUITE_P(NotInstantiatedTypeTest);
+// ... we mark is as allowed.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NotInstantiatedTypeTest);
+
+TYPED_TEST_P(NotInstantiatedTypeTest, Used) {}
+REGISTER_TYPED_TEST_SUITE_P(NotInstantiatedTypeTest, Used);
+}  // namespace works_here
+
+int main(int argc, char** argv) {
+  // Used in TestGenerationTest test suite.
+  AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());
+  // Used in GeneratorEvaluationTest test suite. Tests that the updated value
+  // will be picked up for instantiating tests in GeneratorEvaluationTest.
+  GeneratorEvaluationTest::set_param_value(1);
+
+  ::testing::InitGoogleTest(&argc, argv);
+
+  // Used in GeneratorEvaluationTest test suite. Tests that value updated
+  // here will NOT be used for instantiating tests in
+  // GeneratorEvaluationTest.
+  GeneratorEvaluationTest::set_param_value(2);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test-test.h b/3rd-party/googletest/googletest/test/googletest-param-test-test.h
new file mode 100644
index 0000000..6d77e10
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test-test.h
@@ -0,0 +1,49 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file provides classes and functions used internally
+// for testing Google Test itself.
+
+#ifndef GOOGLETEST_TEST_GOOGLETEST_PARAM_TEST_TEST_H_
+#define GOOGLETEST_TEST_GOOGLETEST_PARAM_TEST_TEST_H_
+
+#include "gtest/gtest.h"
+
+// Test fixture for testing definition and instantiation of a test
+// in separate translation units.
+class ExternalInstantiationTest : public ::testing::TestWithParam<int> {};
+
+// Test fixture for testing instantiation of a test in multiple
+// translation units.
+class InstantiationInMultipleTranslationUnitsTest
+    : public ::testing::TestWithParam<int> {};
+
+#endif  // GOOGLETEST_TEST_GOOGLETEST_PARAM_TEST_TEST_H_
diff --git a/3rd-party/googletest/googletest/test/googletest-param-test2-test.cc b/3rd-party/googletest/googletest/test/googletest-param-test2-test.cc
new file mode 100644
index 0000000..71727a6
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-param-test2-test.cc
@@ -0,0 +1,58 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for Google Test itself.  This verifies that the basic constructs of
+// Google Test work.
+
+#include "gtest/gtest.h"
+#include "test/googletest-param-test-test.h"
+
+using ::testing::Values;
+using ::testing::internal::ParamGenerator;
+
+// Tests that generators defined in a different translation unit
+// are functional. The test using extern_gen is defined
+// in googletest-param-test-test.cc.
+ParamGenerator<int> extern_gen = Values(33);
+
+// Tests that a parameterized test case can be defined in one translation unit
+// and instantiated in another. The test is defined in
+// googletest-param-test-test.cc and ExternalInstantiationTest fixture class is
+// defined in gtest-param-test_test.h.
+INSTANTIATE_TEST_SUITE_P(MultiplesOf33, ExternalInstantiationTest,
+                         Values(33, 66));
+
+// Tests that a parameterized test case can be instantiated
+// in multiple translation units. Another instantiation is defined
+// in googletest-param-test-test.cc and
+// InstantiationInMultipleTranslationUnitsTest fixture is defined in
+// gtest-param-test_test.h
+INSTANTIATE_TEST_SUITE_P(Sequence2, InstantiationInMultipleTranslationUnitsTest,
+                         Values(42 * 3, 42 * 4, 42 * 5));
diff --git a/3rd-party/googletest/googletest/test/googletest-port-test.cc b/3rd-party/googletest/googletest/test/googletest-port-test.cc
new file mode 100644
index 0000000..9f05a01
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-port-test.cc
@@ -0,0 +1,1301 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file tests the internal cross-platform support utilities.
+#include <stdio.h>
+
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_OS_MAC
+#include <time.h>
+#endif  // GTEST_OS_MAC
+
+#include <chrono>  // NOLINT
+#include <list>
+#include <memory>
+#include <string>
+#include <thread>   // NOLINT
+#include <utility>  // For std::pair and std::make_pair.
+#include <vector>
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+using std::make_pair;
+using std::pair;
+
+namespace testing {
+namespace internal {
+
+TEST(IsXDigitTest, WorksForNarrowAscii) {
+  EXPECT_TRUE(IsXDigit('0'));
+  EXPECT_TRUE(IsXDigit('9'));
+  EXPECT_TRUE(IsXDigit('A'));
+  EXPECT_TRUE(IsXDigit('F'));
+  EXPECT_TRUE(IsXDigit('a'));
+  EXPECT_TRUE(IsXDigit('f'));
+
+  EXPECT_FALSE(IsXDigit('-'));
+  EXPECT_FALSE(IsXDigit('g'));
+  EXPECT_FALSE(IsXDigit('G'));
+}
+
+TEST(IsXDigitTest, ReturnsFalseForNarrowNonAscii) {
+  EXPECT_FALSE(IsXDigit(static_cast<char>('\x80')));
+  EXPECT_FALSE(IsXDigit(static_cast<char>('0' | '\x80')));
+}
+
+TEST(IsXDigitTest, WorksForWideAscii) {
+  EXPECT_TRUE(IsXDigit(L'0'));
+  EXPECT_TRUE(IsXDigit(L'9'));
+  EXPECT_TRUE(IsXDigit(L'A'));
+  EXPECT_TRUE(IsXDigit(L'F'));
+  EXPECT_TRUE(IsXDigit(L'a'));
+  EXPECT_TRUE(IsXDigit(L'f'));
+
+  EXPECT_FALSE(IsXDigit(L'-'));
+  EXPECT_FALSE(IsXDigit(L'g'));
+  EXPECT_FALSE(IsXDigit(L'G'));
+}
+
+TEST(IsXDigitTest, ReturnsFalseForWideNonAscii) {
+  EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(0x80)));
+  EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x80)));
+  EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x100)));
+}
+
+class Base {
+ public:
+  Base() : member_(0) {}
+  explicit Base(int n) : member_(n) {}
+  Base(const Base&) = default;
+  Base& operator=(const Base&) = default;
+  virtual ~Base() = default;
+  int member() { return member_; }
+
+ private:
+  int member_;
+};
+
+class Derived : public Base {
+ public:
+  explicit Derived(int n) : Base(n) {}
+};
+
+TEST(ImplicitCastTest, ConvertsPointers) {
+  Derived derived(0);
+  EXPECT_TRUE(&derived == ::testing::internal::ImplicitCast_<Base*>(&derived));
+}
+
+TEST(ImplicitCastTest, CanUseInheritance) {
+  Derived derived(1);
+  Base base = ::testing::internal::ImplicitCast_<Base>(derived);
+  EXPECT_EQ(derived.member(), base.member());
+}
+
+class Castable {
+ public:
+  explicit Castable(bool* converted) : converted_(converted) {}
+  operator Base() {
+    *converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+};
+
+TEST(ImplicitCastTest, CanUseNonConstCastOperator) {
+  bool converted = false;
+  Castable castable(&converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(castable);
+  EXPECT_TRUE(converted);
+}
+
+class ConstCastable {
+ public:
+  explicit ConstCastable(bool* converted) : converted_(converted) {}
+  operator Base() const {
+    *converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+};
+
+TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) {
+  bool converted = false;
+  const ConstCastable const_castable(&converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(const_castable);
+  EXPECT_TRUE(converted);
+}
+
+class ConstAndNonConstCastable {
+ public:
+  ConstAndNonConstCastable(bool* converted, bool* const_converted)
+      : converted_(converted), const_converted_(const_converted) {}
+  operator Base() {
+    *converted_ = true;
+    return Base();
+  }
+  operator Base() const {
+    *const_converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+  bool* const_converted_;
+};
+
+TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) {
+  bool converted = false;
+  bool const_converted = false;
+  ConstAndNonConstCastable castable(&converted, &const_converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(castable);
+  EXPECT_TRUE(converted);
+  EXPECT_FALSE(const_converted);
+
+  converted = false;
+  const_converted = false;
+  const ConstAndNonConstCastable const_castable(&converted, &const_converted);
+  base = ::testing::internal::ImplicitCast_<Base>(const_castable);
+  EXPECT_FALSE(converted);
+  EXPECT_TRUE(const_converted);
+}
+
+class To {
+ public:
+  To(bool* converted) { *converted = true; }  // NOLINT
+};
+
+TEST(ImplicitCastTest, CanUseImplicitConstructor) {
+  bool converted = false;
+  To to = ::testing::internal::ImplicitCast_<To>(&converted);
+  (void)to;
+  EXPECT_TRUE(converted);
+}
+
+// The following code intentionally tests a suboptimal syntax.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-else"
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
+  if (AlwaysFalse())
+    GTEST_CHECK_(false) << "This should never be executed; "
+                           "It's a compilation test only.";
+
+  if (AlwaysTrue())
+    GTEST_CHECK_(true);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    GTEST_CHECK_(true) << "";
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
+  switch (0) {
+    case 1:
+      break;
+    default:
+      GTEST_CHECK_(true);
+  }
+
+  switch (0)
+  case 0:
+    GTEST_CHECK_(true) << "Check failed in switch case";
+}
+
+// Verifies behavior of FormatFileLocation.
+TEST(FormatFileLocationTest, FormatsFileLocation) {
+  EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42));
+  EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42));
+}
+
+TEST(FormatFileLocationTest, FormatsUnknownFile) {
+  EXPECT_PRED_FORMAT2(IsSubstring, "unknown file",
+                      FormatFileLocation(nullptr, 42));
+  EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation(nullptr, 42));
+}
+
+TEST(FormatFileLocationTest, FormatsUknownLine) {
+  EXPECT_EQ("foo.cc:", FormatFileLocation("foo.cc", -1));
+}
+
+TEST(FormatFileLocationTest, FormatsUknownFileAndLine) {
+  EXPECT_EQ("unknown file:", FormatFileLocation(nullptr, -1));
+}
+
+// Verifies behavior of FormatCompilerIndependentFileLocation.
+TEST(FormatCompilerIndependentFileLocationTest, FormatsFileLocation) {
+  EXPECT_EQ("foo.cc:42", FormatCompilerIndependentFileLocation("foo.cc", 42));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFile) {
+  EXPECT_EQ("unknown file:42",
+            FormatCompilerIndependentFileLocation(nullptr, 42));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) {
+  EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
+  EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1));
+}
+
+#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_MAC) ||           \
+    defined(GTEST_OS_QNX) || defined(GTEST_OS_FUCHSIA) ||         \
+    defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) ||   \
+    defined(GTEST_OS_GNU_KFREEBSD) || defined(GTEST_OS_NETBSD) || \
+    defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_GNU_HURD)
+void* ThreadFunc(void* data) {
+  internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
+  mutex->Lock();
+  mutex->Unlock();
+  return nullptr;
+}
+
+TEST(GetThreadCountTest, ReturnsCorrectValue) {
+  size_t starting_count;
+  size_t thread_count_after_create;
+  size_t thread_count_after_join = 0;
+
+  // We can't guarantee that no other thread was created or destroyed between
+  // any two calls to GetThreadCount(). We make multiple attempts, hoping that
+  // background noise is not constant and we would see the "right" values at
+  // some point.
+  for (int attempt = 0; attempt < 20; ++attempt) {
+    starting_count = GetThreadCount();
+    pthread_t thread_id;
+
+    internal::Mutex mutex;
+    {
+      internal::MutexLock lock(&mutex);
+      pthread_attr_t attr;
+      ASSERT_EQ(0, pthread_attr_init(&attr));
+      ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
+
+      const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
+      ASSERT_EQ(0, pthread_attr_destroy(&attr));
+      ASSERT_EQ(0, status);
+
+      thread_count_after_create = GetThreadCount();
+    }
+
+    void* dummy;
+    ASSERT_EQ(0, pthread_join(thread_id, &dummy));
+
+    // Join before we decide whether we need to retry the test. Retry if an
+    // arbitrary other thread was created or destroyed in the meantime.
+    if (thread_count_after_create != starting_count + 1) continue;
+
+    // The OS may not immediately report the updated thread count after
+    // joining a thread, causing flakiness in this test. To counter that, we
+    // wait for up to .5 seconds for the OS to report the correct value.
+    bool thread_count_matches = false;
+    for (int i = 0; i < 5; ++i) {
+      thread_count_after_join = GetThreadCount();
+      if (thread_count_after_join == starting_count) {
+        thread_count_matches = true;
+        break;
+      }
+
+      std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    }
+
+    // Retry if an arbitrary other thread was created or destroyed.
+    if (!thread_count_matches) continue;
+
+    break;
+  }
+
+  EXPECT_EQ(thread_count_after_create, starting_count + 1);
+  EXPECT_EQ(thread_count_after_join, starting_count);
+}
+#else
+TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
+  EXPECT_EQ(0U, GetThreadCount());
+}
+#endif  // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA
+
+TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
+  const bool a_false_condition = false;
+  const char regex[] =
+#ifdef _MSC_VER
+      "googletest-port-test\\.cc\\(\\d+\\):"
+#elif defined(GTEST_USES_POSIX_RE)
+      "googletest-port-test\\.cc:[0-9]+"
+#else
+      "googletest-port-test\\.cc:\\d+"
+#endif  // _MSC_VER
+      ".*a_false_condition.*Extra info.*";
+
+  EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
+                            regex);
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
+  EXPECT_EXIT(
+      {
+        GTEST_CHECK_(true) << "Extra info";
+        ::std::cerr << "Success\n";
+        exit(0);
+      },
+      ::testing::ExitedWithCode(0), "Success");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Verifies that Google Test choose regular expression engine appropriate to
+// the platform. The test will produce compiler errors in case of failure.
+// For simplicity, we only cover the most important platforms here.
+TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) {
+#ifdef GTEST_HAS_ABSL
+  EXPECT_TRUE(GTEST_USES_RE2);
+#elif GTEST_HAS_POSIX_RE
+  EXPECT_TRUE(GTEST_USES_POSIX_RE);
+#else
+  EXPECT_TRUE(GTEST_USES_SIMPLE_RE);
+#endif
+}
+
+#ifdef GTEST_USES_POSIX_RE
+
+template <typename Str>
+class RETest : public ::testing::Test {};
+
+// Defines StringTypes as the list of all string types that class RE
+// supports.
+typedef testing::Types< ::std::string, const char*> StringTypes;
+
+TYPED_TEST_SUITE(RETest, StringTypes);
+
+// Tests RE's implicit constructors.
+TYPED_TEST(RETest, ImplicitConstructorWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_STREQ("", empty.pattern());
+
+  const RE simple(TypeParam("hello"));
+  EXPECT_STREQ("hello", simple.pattern());
+
+  const RE normal(TypeParam(".*(\\w+)"));
+  EXPECT_STREQ(".*(\\w+)", normal.pattern());
+}
+
+// Tests that RE's constructors reject invalid regular expressions.
+TYPED_TEST(RETest, RejectsInvalidRegex) {
+  EXPECT_NONFATAL_FAILURE(
+      { const RE invalid(TypeParam("?")); },
+      "\"?\" is not a valid POSIX Extended regular expression.");
+}
+
+// Tests RE::FullMatch().
+TYPED_TEST(RETest, FullMatchWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty));
+
+  const RE re(TypeParam("a.*z"));
+  EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re));
+  EXPECT_TRUE(RE::FullMatch(TypeParam("axyz"), re));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("baz"), re));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("azy"), re));
+}
+
+// Tests RE::PartialMatch().
+TYPED_TEST(RETest, PartialMatchWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam(""), empty));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("a"), empty));
+
+  const RE re(TypeParam("a.*z"));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("az"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("axyz"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("baz"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("azy"), re));
+  EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re));
+}
+
+#elif defined(GTEST_USES_SIMPLE_RE)
+
+TEST(IsInSetTest, NulCharIsNotInAnySet) {
+  EXPECT_FALSE(IsInSet('\0', ""));
+  EXPECT_FALSE(IsInSet('\0', "\0"));
+  EXPECT_FALSE(IsInSet('\0', "a"));
+}
+
+TEST(IsInSetTest, WorksForNonNulChars) {
+  EXPECT_FALSE(IsInSet('a', "Ab"));
+  EXPECT_FALSE(IsInSet('c', ""));
+
+  EXPECT_TRUE(IsInSet('b', "bcd"));
+  EXPECT_TRUE(IsInSet('b', "ab"));
+}
+
+TEST(IsAsciiDigitTest, IsFalseForNonDigit) {
+  EXPECT_FALSE(IsAsciiDigit('\0'));
+  EXPECT_FALSE(IsAsciiDigit(' '));
+  EXPECT_FALSE(IsAsciiDigit('+'));
+  EXPECT_FALSE(IsAsciiDigit('-'));
+  EXPECT_FALSE(IsAsciiDigit('.'));
+  EXPECT_FALSE(IsAsciiDigit('a'));
+}
+
+TEST(IsAsciiDigitTest, IsTrueForDigit) {
+  EXPECT_TRUE(IsAsciiDigit('0'));
+  EXPECT_TRUE(IsAsciiDigit('1'));
+  EXPECT_TRUE(IsAsciiDigit('5'));
+  EXPECT_TRUE(IsAsciiDigit('9'));
+}
+
+TEST(IsAsciiPunctTest, IsFalseForNonPunct) {
+  EXPECT_FALSE(IsAsciiPunct('\0'));
+  EXPECT_FALSE(IsAsciiPunct(' '));
+  EXPECT_FALSE(IsAsciiPunct('\n'));
+  EXPECT_FALSE(IsAsciiPunct('a'));
+  EXPECT_FALSE(IsAsciiPunct('0'));
+}
+
+TEST(IsAsciiPunctTest, IsTrueForPunct) {
+  for (const char* p = "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"; *p; p++) {
+    EXPECT_PRED1(IsAsciiPunct, *p);
+  }
+}
+
+TEST(IsRepeatTest, IsFalseForNonRepeatChar) {
+  EXPECT_FALSE(IsRepeat('\0'));
+  EXPECT_FALSE(IsRepeat(' '));
+  EXPECT_FALSE(IsRepeat('a'));
+  EXPECT_FALSE(IsRepeat('1'));
+  EXPECT_FALSE(IsRepeat('-'));
+}
+
+TEST(IsRepeatTest, IsTrueForRepeatChar) {
+  EXPECT_TRUE(IsRepeat('?'));
+  EXPECT_TRUE(IsRepeat('*'));
+  EXPECT_TRUE(IsRepeat('+'));
+}
+
+TEST(IsAsciiWhiteSpaceTest, IsFalseForNonWhiteSpace) {
+  EXPECT_FALSE(IsAsciiWhiteSpace('\0'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('a'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('1'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('+'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('_'));
+}
+
+TEST(IsAsciiWhiteSpaceTest, IsTrueForWhiteSpace) {
+  EXPECT_TRUE(IsAsciiWhiteSpace(' '));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\n'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\r'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\t'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\v'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\f'));
+}
+
+TEST(IsAsciiWordCharTest, IsFalseForNonWordChar) {
+  EXPECT_FALSE(IsAsciiWordChar('\0'));
+  EXPECT_FALSE(IsAsciiWordChar('+'));
+  EXPECT_FALSE(IsAsciiWordChar('.'));
+  EXPECT_FALSE(IsAsciiWordChar(' '));
+  EXPECT_FALSE(IsAsciiWordChar('\n'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForLetter) {
+  EXPECT_TRUE(IsAsciiWordChar('a'));
+  EXPECT_TRUE(IsAsciiWordChar('b'));
+  EXPECT_TRUE(IsAsciiWordChar('A'));
+  EXPECT_TRUE(IsAsciiWordChar('Z'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForDigit) {
+  EXPECT_TRUE(IsAsciiWordChar('0'));
+  EXPECT_TRUE(IsAsciiWordChar('1'));
+  EXPECT_TRUE(IsAsciiWordChar('7'));
+  EXPECT_TRUE(IsAsciiWordChar('9'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForUnderscore) {
+  EXPECT_TRUE(IsAsciiWordChar('_'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForNonPrintable) {
+  EXPECT_FALSE(IsValidEscape('\0'));
+  EXPECT_FALSE(IsValidEscape('\007'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForDigit) {
+  EXPECT_FALSE(IsValidEscape('0'));
+  EXPECT_FALSE(IsValidEscape('9'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForWhiteSpace) {
+  EXPECT_FALSE(IsValidEscape(' '));
+  EXPECT_FALSE(IsValidEscape('\n'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForSomeLetter) {
+  EXPECT_FALSE(IsValidEscape('a'));
+  EXPECT_FALSE(IsValidEscape('Z'));
+}
+
+TEST(IsValidEscapeTest, IsTrueForPunct) {
+  EXPECT_TRUE(IsValidEscape('.'));
+  EXPECT_TRUE(IsValidEscape('-'));
+  EXPECT_TRUE(IsValidEscape('^'));
+  EXPECT_TRUE(IsValidEscape('$'));
+  EXPECT_TRUE(IsValidEscape('('));
+  EXPECT_TRUE(IsValidEscape(']'));
+  EXPECT_TRUE(IsValidEscape('{'));
+  EXPECT_TRUE(IsValidEscape('|'));
+}
+
+TEST(IsValidEscapeTest, IsTrueForSomeLetter) {
+  EXPECT_TRUE(IsValidEscape('d'));
+  EXPECT_TRUE(IsValidEscape('D'));
+  EXPECT_TRUE(IsValidEscape('s'));
+  EXPECT_TRUE(IsValidEscape('S'));
+  EXPECT_TRUE(IsValidEscape('w'));
+  EXPECT_TRUE(IsValidEscape('W'));
+}
+
+TEST(AtomMatchesCharTest, EscapedPunct) {
+  EXPECT_FALSE(AtomMatchesChar(true, '\\', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, '\\', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, '_', '.'));
+  EXPECT_FALSE(AtomMatchesChar(true, '.', 'a'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, '\\', '\\'));
+  EXPECT_TRUE(AtomMatchesChar(true, '_', '_'));
+  EXPECT_TRUE(AtomMatchesChar(true, '+', '+'));
+  EXPECT_TRUE(AtomMatchesChar(true, '.', '.'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_d) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', '.'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'd', '0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'd', '9'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_D) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'D', '0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'D', '9'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', '-'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_s) {
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '.'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '9'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 's', ' '));
+  EXPECT_TRUE(AtomMatchesChar(true, 's', '\n'));
+  EXPECT_TRUE(AtomMatchesChar(true, 's', '\t'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_S) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'S', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, 'S', '\r'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', '9'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_w) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '+'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '\n'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', '0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', 'b'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', 'C'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', '_'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_W) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', 'A'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', 'b'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', '9'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', '_'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '*'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '\n'));
+}
+
+TEST(AtomMatchesCharTest, EscapedWhiteSpace) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'f', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'f', '\n'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'n', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'n', '\r'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'r', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'r', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 't', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 't', 't'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'v', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'v', '\f'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'f', '\f'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'n', '\n'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'r', '\r'));
+  EXPECT_TRUE(AtomMatchesChar(true, 't', '\t'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'v', '\v'));
+}
+
+TEST(AtomMatchesCharTest, UnescapedDot) {
+  EXPECT_FALSE(AtomMatchesChar(false, '.', '\n'));
+
+  EXPECT_TRUE(AtomMatchesChar(false, '.', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', '.'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', ' '));
+}
+
+TEST(AtomMatchesCharTest, UnescapedChar) {
+  EXPECT_FALSE(AtomMatchesChar(false, 'a', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(false, 'a', 'b'));
+  EXPECT_FALSE(AtomMatchesChar(false, '$', 'a'));
+
+  EXPECT_TRUE(AtomMatchesChar(false, '$', '$'));
+  EXPECT_TRUE(AtomMatchesChar(false, '5', '5'));
+  EXPECT_TRUE(AtomMatchesChar(false, 'Z', 'Z'));
+}
+
+TEST(ValidateRegexTest, GeneratesFailureAndReturnsFalseForInvalid) {
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(NULL)),
+                          "NULL is not a valid simple regular expression");
+  EXPECT_NONFATAL_FAILURE(
+      ASSERT_FALSE(ValidateRegex("a\\")),
+      "Syntax error at index 1 in simple regular expression \"a\\\": ");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a\\")),
+                          "'\\' cannot appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\n\\")),
+                          "'\\' cannot appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\s\\hb")),
+                          "invalid escape sequence \"\\h\"");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^^")),
+                          "'^' can only appear at the beginning");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(".*^b")),
+                          "'^' can only appear at the beginning");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("$$")),
+                          "'$' can only appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^$a")),
+                          "'$' can only appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a(b")),
+                          "'(' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("ab)")),
+                          "')' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("[ab")),
+                          "'[' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a{2")),
+                          "'{' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("?")),
+                          "'?' can only follow a repeatable token");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^*")),
+                          "'*' can only follow a repeatable token");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("5*+")),
+                          "'+' can only follow a repeatable token");
+}
+
+TEST(ValidateRegexTest, ReturnsTrueForValid) {
+  EXPECT_TRUE(ValidateRegex(""));
+  EXPECT_TRUE(ValidateRegex("a"));
+  EXPECT_TRUE(ValidateRegex(".*"));
+  EXPECT_TRUE(ValidateRegex("^a_+"));
+  EXPECT_TRUE(ValidateRegex("^a\\t\\&?"));
+  EXPECT_TRUE(ValidateRegex("09*$"));
+  EXPECT_TRUE(ValidateRegex("^Z$"));
+  EXPECT_TRUE(ValidateRegex("a\\^Z\\$\\(\\)\\|\\[\\]\\{\\}"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrOne) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "a", "ba"));
+  // Repeating more than once.
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "aab"));
+
+  // Repeating zero times.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ba"));
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ab"));
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '#', '?', ".", "##"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrMany) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '*', "a$", "baab"));
+
+  // Repeating zero times.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "bc"));
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "abc"));
+  // Repeating more than once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '*', "-", "ab_1-g"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForOneOrMany) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "a$", "baab"));
+  // Repeating zero times.
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "bc"));
+
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "abc"));
+  // Repeating more than once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '+', "-", "ab_1-g"));
+}
+
+TEST(MatchRegexAtHeadTest, ReturnsTrueForEmptyRegex) {
+  EXPECT_TRUE(MatchRegexAtHead("", ""));
+  EXPECT_TRUE(MatchRegexAtHead("", "ab"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenDollarIsInRegex) {
+  EXPECT_FALSE(MatchRegexAtHead("$", "a"));
+
+  EXPECT_TRUE(MatchRegexAtHead("$", ""));
+  EXPECT_TRUE(MatchRegexAtHead("a$", "a"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithEscapeSequence) {
+  EXPECT_FALSE(MatchRegexAtHead("\\w", "+"));
+  EXPECT_FALSE(MatchRegexAtHead("\\W", "ab"));
+
+  EXPECT_TRUE(MatchRegexAtHead("\\sa", "\nab"));
+  EXPECT_TRUE(MatchRegexAtHead("\\d", "1a"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) {
+  EXPECT_FALSE(MatchRegexAtHead(".+a", "abc"));
+  EXPECT_FALSE(MatchRegexAtHead("a?b", "aab"));
+
+  EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab"));
+  EXPECT_TRUE(MatchRegexAtHead("a?b", "b"));
+  EXPECT_TRUE(MatchRegexAtHead("a?b", "ab"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
+  EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc"));
+  EXPECT_FALSE(MatchRegexAtHead("\\s?b", "  b"));
+
+  EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab"));
+  EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b"));
+  EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b"));
+  EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b"));
+}
+
+TEST(MatchRegexAtHeadTest, MatchesSequentially) {
+  EXPECT_FALSE(MatchRegexAtHead("ab.*c", "acabc"));
+
+  EXPECT_TRUE(MatchRegexAtHead("ab.*c", "ab-fsc"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsFalseWhenStringIsNull) {
+  EXPECT_FALSE(MatchRegexAnywhere("", NULL));
+}
+
+TEST(MatchRegexAnywhereTest, WorksWhenRegexStartsWithCaret) {
+  EXPECT_FALSE(MatchRegexAnywhere("^a", "ba"));
+  EXPECT_FALSE(MatchRegexAnywhere("^$", "a"));
+
+  EXPECT_TRUE(MatchRegexAnywhere("^a", "ab"));
+  EXPECT_TRUE(MatchRegexAnywhere("^", "ab"));
+  EXPECT_TRUE(MatchRegexAnywhere("^$", ""));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsFalseWhenNoMatch) {
+  EXPECT_FALSE(MatchRegexAnywhere("a", "bcde123"));
+  EXPECT_FALSE(MatchRegexAnywhere("a.+a", "--aa88888888"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingPrefix) {
+  EXPECT_TRUE(MatchRegexAnywhere("\\w+", "ab1_ - 5"));
+  EXPECT_TRUE(MatchRegexAnywhere(".*=", "="));
+  EXPECT_TRUE(MatchRegexAnywhere("x.*ab?.*bc", "xaaabc"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) {
+  EXPECT_TRUE(MatchRegexAnywhere("\\w+", "$$$ ab1_ - 5"));
+  EXPECT_TRUE(MatchRegexAnywhere("\\.+=", "=  ...="));
+}
+
+// Tests RE's implicit constructors.
+TEST(RETest, ImplicitConstructorWorks) {
+  const RE empty("");
+  EXPECT_STREQ("", empty.pattern());
+
+  const RE simple("hello");
+  EXPECT_STREQ("hello", simple.pattern());
+}
+
+// Tests that RE's constructors reject invalid regular expressions.
+TEST(RETest, RejectsInvalidRegex) {
+  EXPECT_NONFATAL_FAILURE({ const RE normal(NULL); },
+                          "NULL is not a valid simple regular expression");
+
+  EXPECT_NONFATAL_FAILURE({ const RE normal(".*(\\w+"); },
+                          "'(' is unsupported");
+
+  EXPECT_NONFATAL_FAILURE({ const RE invalid("^?"); },
+                          "'?' can only follow a repeatable token");
+}
+
+// Tests RE::FullMatch().
+TEST(RETest, FullMatchWorks) {
+  const RE empty("");
+  EXPECT_TRUE(RE::FullMatch("", empty));
+  EXPECT_FALSE(RE::FullMatch("a", empty));
+
+  const RE re1("a");
+  EXPECT_TRUE(RE::FullMatch("a", re1));
+
+  const RE re("a.*z");
+  EXPECT_TRUE(RE::FullMatch("az", re));
+  EXPECT_TRUE(RE::FullMatch("axyz", re));
+  EXPECT_FALSE(RE::FullMatch("baz", re));
+  EXPECT_FALSE(RE::FullMatch("azy", re));
+}
+
+// Tests RE::PartialMatch().
+TEST(RETest, PartialMatchWorks) {
+  const RE empty("");
+  EXPECT_TRUE(RE::PartialMatch("", empty));
+  EXPECT_TRUE(RE::PartialMatch("a", empty));
+
+  const RE re("a.*z");
+  EXPECT_TRUE(RE::PartialMatch("az", re));
+  EXPECT_TRUE(RE::PartialMatch("axyz", re));
+  EXPECT_TRUE(RE::PartialMatch("baz", re));
+  EXPECT_TRUE(RE::PartialMatch("azy", re));
+  EXPECT_FALSE(RE::PartialMatch("zza", re));
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+
+TEST(CaptureTest, CapturesStdout) {
+  CaptureStdout();
+  fprintf(stdout, "abc");
+  EXPECT_STREQ("abc", GetCapturedStdout().c_str());
+
+  CaptureStdout();
+  fprintf(stdout, "def%cghi", '\0');
+  EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout()));
+}
+
+TEST(CaptureTest, CapturesStderr) {
+  CaptureStderr();
+  fprintf(stderr, "jkl");
+  EXPECT_STREQ("jkl", GetCapturedStderr().c_str());
+
+  CaptureStderr();
+  fprintf(stderr, "jkl%cmno", '\0');
+  EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr()));
+}
+
+// Tests that stdout and stderr capture don't interfere with each other.
+TEST(CaptureTest, CapturesStdoutAndStderr) {
+  CaptureStdout();
+  CaptureStderr();
+  fprintf(stdout, "pqr");
+  fprintf(stderr, "stu");
+  EXPECT_STREQ("pqr", GetCapturedStdout().c_str());
+  EXPECT_STREQ("stu", GetCapturedStderr().c_str());
+}
+
+TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
+  CaptureStdout();
+  EXPECT_DEATH_IF_SUPPORTED(CaptureStdout(),
+                            "Only one stdout capturer can exist at a time");
+  GetCapturedStdout();
+
+  // We cannot test stderr capturing using death tests as they use it
+  // themselves.
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) {
+  ThreadLocal<int> t1;
+  EXPECT_EQ(0, t1.get());
+
+  ThreadLocal<void*> t2;
+  EXPECT_TRUE(t2.get() == nullptr);
+}
+
+TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
+  ThreadLocal<int> t1(123);
+  EXPECT_EQ(123, t1.get());
+
+  int i = 0;
+  ThreadLocal<int*> t2(&i);
+  EXPECT_EQ(&i, t2.get());
+}
+
+class NoDefaultConstructor {
+ public:
+  explicit NoDefaultConstructor(const char*) {}
+  NoDefaultConstructor(const NoDefaultConstructor&) = default;
+};
+
+TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
+  ThreadLocal<NoDefaultConstructor> bar(NoDefaultConstructor("foo"));
+  bar.pointer();
+}
+
+TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
+  ThreadLocal<std::string> thread_local_string;
+
+  EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get()));
+
+  // Verifies the condition still holds after calling set.
+  thread_local_string.set("foo");
+  EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get()));
+}
+
+TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) {
+  ThreadLocal<std::string> thread_local_string;
+  const ThreadLocal<std::string>& const_thread_local_string =
+      thread_local_string;
+
+  EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer());
+
+  thread_local_string.set("foo");
+  EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer());
+}
+
+#ifdef GTEST_IS_THREADSAFE
+
+void AddTwo(int* param) { *param += 2; }
+
+TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
+  int i = 40;
+  ThreadWithParam<int*> thread(&AddTwo, &i, nullptr);
+  thread.Join();
+  EXPECT_EQ(42, i);
+}
+
+TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
+  // AssertHeld() is flaky only in the presence of multiple threads accessing
+  // the lock. In this case, the test is robust.
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        Mutex m;
+        { MutexLock lock(&m); }
+        m.AssertHeld();
+      },
+      "thread .*hold");
+}
+
+TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
+  Mutex m;
+  MutexLock lock(&m);
+  m.AssertHeld();
+}
+
+class AtomicCounterWithMutex {
+ public:
+  explicit AtomicCounterWithMutex(Mutex* mutex)
+      : value_(0), mutex_(mutex), random_(42) {}
+
+  void Increment() {
+    MutexLock lock(mutex_);
+    int temp = value_;
+    {
+      // We need to put up a memory barrier to prevent reads and writes to
+      // value_ rearranged with the call to sleep_for when observed
+      // from other threads.
+#if GTEST_HAS_PTHREAD
+      // On POSIX, locking a mutex puts up a memory barrier.  We cannot use
+      // Mutex and MutexLock here or rely on their memory barrier
+      // functionality as we are testing them here.
+      pthread_mutex_t memory_barrier_mutex;
+      GTEST_CHECK_POSIX_SUCCESS_(
+          pthread_mutex_init(&memory_barrier_mutex, nullptr));
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
+
+      std::this_thread::sleep_for(
+          std::chrono::milliseconds(random_.Generate(30)));
+
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex));
+#elif defined(GTEST_OS_WINDOWS)
+      // On Windows, performing an interlocked access puts up a memory barrier.
+      volatile LONG dummy = 0;
+      ::InterlockedIncrement(&dummy);
+      std::this_thread::sleep_for(
+          std::chrono::milliseconds(random_.Generate(30)));
+      ::InterlockedIncrement(&dummy);
+#else
+#error "Memory barrier not implemented on this platform."
+#endif  // GTEST_HAS_PTHREAD
+    }
+    value_ = temp + 1;
+  }
+  int value() const { return value_; }
+
+ private:
+  volatile int value_;
+  Mutex* const mutex_;  // Protects value_.
+  Random random_;
+};
+
+void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
+  for (int i = 0; i < param.second; ++i) param.first->Increment();
+}
+
+// Tests that the mutex only lets one thread at a time to lock it.
+TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
+  Mutex mutex;
+  AtomicCounterWithMutex locked_counter(&mutex);
+
+  typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
+  const int kCycleCount = 20;
+  const int kThreadCount = 7;
+  std::unique_ptr<ThreadType> counting_threads[kThreadCount];
+  Notification threads_can_start;
+  // Creates and runs kThreadCount threads that increment locked_counter
+  // kCycleCount times each.
+  for (int i = 0; i < kThreadCount; ++i) {
+    counting_threads[i] = std::make_unique<ThreadType>(
+        &CountingThreadFunc, make_pair(&locked_counter, kCycleCount),
+        &threads_can_start);
+  }
+  threads_can_start.Notify();
+  for (int i = 0; i < kThreadCount; ++i) counting_threads[i]->Join();
+
+  // If the mutex lets more than one thread to increment the counter at a
+  // time, they are likely to encounter a race condition and have some
+  // increments overwritten, resulting in the lower then expected counter
+  // value.
+  EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
+}
+
+template <typename T>
+void RunFromThread(void(func)(T), T param) {
+  ThreadWithParam<T> thread(func, param, nullptr);
+  thread.Join();
+}
+
+void RetrieveThreadLocalValue(
+    pair<ThreadLocal<std::string>*, std::string*> param) {
+  *param.second = param.first->get();
+}
+
+TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
+  ThreadLocal<std::string> thread_local_string("foo");
+  EXPECT_STREQ("foo", thread_local_string.get().c_str());
+
+  thread_local_string.set("bar");
+  EXPECT_STREQ("bar", thread_local_string.get().c_str());
+
+  std::string result;
+  RunFromThread(&RetrieveThreadLocalValue,
+                make_pair(&thread_local_string, &result));
+  EXPECT_STREQ("foo", result.c_str());
+}
+
+// Keeps track of whether of destructors being called on instances of
+// DestructorTracker.  On Windows, waits for the destructor call reports.
+class DestructorCall {
+ public:
+  DestructorCall() {
+    invoked_ = false;
+#ifdef GTEST_OS_WINDOWS
+    wait_event_.Reset(::CreateEvent(NULL, TRUE, FALSE, NULL));
+    GTEST_CHECK_(wait_event_.Get() != NULL);
+#endif
+  }
+
+  bool CheckDestroyed() const {
+#ifdef GTEST_OS_WINDOWS
+    if (::WaitForSingleObject(wait_event_.Get(), 1000) != WAIT_OBJECT_0)
+      return false;
+#endif
+    return invoked_;
+  }
+
+  void ReportDestroyed() {
+    invoked_ = true;
+#ifdef GTEST_OS_WINDOWS
+    ::SetEvent(wait_event_.Get());
+#endif
+  }
+
+  static std::vector<DestructorCall*>& List() { return *list_; }
+
+  static void ResetList() {
+    for (size_t i = 0; i < list_->size(); ++i) {
+      delete list_->at(i);
+    }
+    list_->clear();
+  }
+
+ private:
+  bool invoked_;
+#ifdef GTEST_OS_WINDOWS
+  AutoHandle wait_event_;
+#endif
+  static std::vector<DestructorCall*>* const list_;
+
+  DestructorCall(const DestructorCall&) = delete;
+  DestructorCall& operator=(const DestructorCall&) = delete;
+};
+
+std::vector<DestructorCall*>* const DestructorCall::list_ =
+    new std::vector<DestructorCall*>;
+
+// DestructorTracker keeps track of whether its instances have been
+// destroyed.
+class DestructorTracker {
+ public:
+  DestructorTracker() : index_(GetNewIndex()) {}
+  DestructorTracker(const DestructorTracker& /* rhs */)
+      : index_(GetNewIndex()) {}
+  ~DestructorTracker() {
+    // We never access DestructorCall::List() concurrently, so we don't need
+    // to protect this access with a mutex.
+    DestructorCall::List()[index_]->ReportDestroyed();
+  }
+
+ private:
+  static size_t GetNewIndex() {
+    DestructorCall::List().push_back(new DestructorCall);
+    return DestructorCall::List().size() - 1;
+  }
+  const size_t index_;
+};
+
+typedef ThreadLocal<DestructorTracker>* ThreadParam;
+
+void CallThreadLocalGet(ThreadParam thread_local_param) {
+  thread_local_param->get();
+}
+
+// Tests that when a ThreadLocal object dies in a thread, it destroys
+// the managed object for that thread.
+TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) {
+  DestructorCall::ResetList();
+
+  {
+    ThreadLocal<DestructorTracker> thread_local_tracker;
+    ASSERT_EQ(0U, DestructorCall::List().size());
+
+    // This creates another DestructorTracker object for the main thread.
+    thread_local_tracker.get();
+    ASSERT_EQ(1U, DestructorCall::List().size());
+    ASSERT_FALSE(DestructorCall::List()[0]->CheckDestroyed());
+  }
+
+  // Now thread_local_tracker has died.
+  ASSERT_EQ(1U, DestructorCall::List().size());
+  EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed());
+
+  DestructorCall::ResetList();
+}
+
+// Tests that when a thread exits, the thread-local object for that
+// thread is destroyed.
+TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) {
+  DestructorCall::ResetList();
+
+  {
+    ThreadLocal<DestructorTracker> thread_local_tracker;
+    ASSERT_EQ(0U, DestructorCall::List().size());
+
+    // This creates another DestructorTracker object in the new thread.
+    ThreadWithParam<ThreadParam> thread(&CallThreadLocalGet,
+                                        &thread_local_tracker, nullptr);
+    thread.Join();
+
+    // The thread has exited, and we should have a DestroyedTracker
+    // instance created for it. But it may not have been destroyed yet.
+    ASSERT_EQ(1U, DestructorCall::List().size());
+  }
+
+  // The thread has exited and thread_local_tracker has died.
+  ASSERT_EQ(1U, DestructorCall::List().size());
+  EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed());
+
+  DestructorCall::ResetList();
+}
+
+TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
+  ThreadLocal<std::string> thread_local_string;
+  thread_local_string.set("Foo");
+  EXPECT_STREQ("Foo", thread_local_string.get().c_str());
+
+  std::string result;
+  RunFromThread(&RetrieveThreadLocalValue,
+                make_pair(&thread_local_string, &result));
+  EXPECT_TRUE(result.empty());
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+#ifdef GTEST_OS_WINDOWS
+TEST(WindowsTypesTest, HANDLEIsVoidStar) {
+  StaticAssertTypeEq<HANDLE, void*>();
+}
+
+#if defined(GTEST_OS_WINDOWS_MINGW) && !defined(__MINGW64_VERSION_MAJOR)
+TEST(WindowsTypesTest, _CRITICAL_SECTIONIs_CRITICAL_SECTION) {
+  StaticAssertTypeEq<CRITICAL_SECTION, _CRITICAL_SECTION>();
+}
+#else
+TEST(WindowsTypesTest, CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION) {
+  StaticAssertTypeEq<CRITICAL_SECTION, _RTL_CRITICAL_SECTION>();
+}
+#endif
+
+#endif  // GTEST_OS_WINDOWS
+
+}  // namespace internal
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/test/googletest-printers-test.cc b/3rd-party/googletest/googletest/test/googletest-printers-test.cc
new file mode 100644
index 0000000..d5061be
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-printers-test.cc
@@ -0,0 +1,2034 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Test - The Google C++ Testing and Mocking Framework
+//
+// This file tests the universal value printer.
+
+#include <algorithm>
+#include <cctype>
+#include <cstdint>
+#include <cstring>
+#include <deque>
+#include <forward_list>
+#include <functional>
+#include <limits>
+#include <list>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+#ifdef GTEST_HAS_ABSL
+#include "absl/strings/str_format.h"
+#endif
+
+#if GTEST_INTERNAL_HAS_STD_SPAN
+#include <span>  // NOLINT
+#endif  // GTEST_INTERNAL_HAS_STD_SPAN
+
+// Some user-defined types for testing the universal value printer.
+
+// An anonymous enum type.
+enum AnonymousEnum { kAE1 = -1, kAE2 = 1 };
+
+// An enum without a user-defined printer.
+enum EnumWithoutPrinter { kEWP1 = -2, kEWP2 = 42 };
+
+// An enum with a << operator.
+enum EnumWithStreaming { kEWS1 = 10 };
+
+std::ostream& operator<<(std::ostream& os, EnumWithStreaming e) {
+  return os << (e == kEWS1 ? "kEWS1" : "invalid");
+}
+
+// An enum with a PrintTo() function.
+enum EnumWithPrintTo { kEWPT1 = 1 };
+
+void PrintTo(EnumWithPrintTo e, std::ostream* os) {
+  *os << (e == kEWPT1 ? "kEWPT1" : "invalid");
+}
+
+// A class implicitly convertible to BiggestInt.
+class BiggestIntConvertible {
+ public:
+  operator ::testing::internal::BiggestInt() const { return 42; }
+};
+
+// A parent class with two child classes. The parent and one of the kids have
+// stream operators.
+class ParentClass {};
+class ChildClassWithStreamOperator : public ParentClass {};
+class ChildClassWithoutStreamOperator : public ParentClass {};
+static void operator<<(std::ostream& os, const ParentClass&) {
+  os << "ParentClass";
+}
+static void operator<<(std::ostream& os, const ChildClassWithStreamOperator&) {
+  os << "ChildClassWithStreamOperator";
+}
+
+// A user-defined unprintable class template in the global namespace.
+template <typename T>
+class UnprintableTemplateInGlobal {
+ public:
+  UnprintableTemplateInGlobal() : value_() {}
+
+ private:
+  T value_;
+};
+
+// A user-defined streamable type in the global namespace.
+class StreamableInGlobal {
+ public:
+  virtual ~StreamableInGlobal() = default;
+};
+
+inline void operator<<(::std::ostream& os, const StreamableInGlobal& /* x */) {
+  os << "StreamableInGlobal";
+}
+
+void operator<<(::std::ostream& os, const StreamableInGlobal* /* x */) {
+  os << "StreamableInGlobal*";
+}
+
+#ifdef GTEST_HAS_ABSL
+// A user-defined type with AbslStringify
+struct Point {
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const Point& p) {
+    absl::Format(&sink, "(%d, %d)", p.x, p.y);
+  }
+
+  int x = 10;
+  int y = 20;
+};
+#endif
+
+namespace foo {
+
+// A user-defined unprintable type in a user namespace.
+class UnprintableInFoo {
+ public:
+  UnprintableInFoo() : z_(0) { memcpy(xy_, "\xEF\x12\x0\x0\x34\xAB\x0\x0", 8); }
+  double z() const { return z_; }
+
+ private:
+  char xy_[8];
+  double z_;
+};
+
+// A user-defined printable type in a user-chosen namespace.
+struct PrintableViaPrintTo {
+  PrintableViaPrintTo() : value() {}
+  int value;
+};
+
+void PrintTo(const PrintableViaPrintTo& x, ::std::ostream* os) {
+  *os << "PrintableViaPrintTo: " << x.value;
+}
+
+// A type with a user-defined << for printing its pointer.
+struct PointerPrintable {};
+
+::std::ostream& operator<<(::std::ostream& os,
+                           const PointerPrintable* /* x */) {
+  return os << "PointerPrintable*";
+}
+
+// A user-defined printable class template in a user-chosen namespace.
+template <typename T>
+class PrintableViaPrintToTemplate {
+ public:
+  explicit PrintableViaPrintToTemplate(const T& a_value) : value_(a_value) {}
+
+  const T& value() const { return value_; }
+
+ private:
+  T value_;
+};
+
+template <typename T>
+void PrintTo(const PrintableViaPrintToTemplate<T>& x, ::std::ostream* os) {
+  *os << "PrintableViaPrintToTemplate: " << x.value();
+}
+
+// A user-defined streamable class template in a user namespace.
+template <typename T>
+class StreamableTemplateInFoo {
+ public:
+  StreamableTemplateInFoo() : value_() {}
+
+  const T& value() const { return value_; }
+
+ private:
+  T value_;
+};
+
+template <typename T>
+inline ::std::ostream& operator<<(::std::ostream& os,
+                                  const StreamableTemplateInFoo<T>& x) {
+  return os << "StreamableTemplateInFoo: " << x.value();
+}
+
+// A user-defined streamable type in a user namespace whose operator<< is
+// templated on the type of the output stream.
+struct TemplatedStreamableInFoo {};
+
+template <typename OutputStream>
+OutputStream& operator<<(OutputStream& os,
+                         const TemplatedStreamableInFoo& /*ts*/) {
+  os << "TemplatedStreamableInFoo";
+  return os;
+}
+
+struct StreamableInLocal {};
+void operator<<(::std::ostream& os, const StreamableInLocal& /* x */) {
+  os << "StreamableInLocal";
+}
+
+// A user-defined streamable but recursively-defined container type in
+// a user namespace, it mimics therefore std::filesystem::path or
+// boost::filesystem::path.
+class PathLike {
+ public:
+  struct iterator {
+    typedef PathLike value_type;
+
+    iterator& operator++();
+    PathLike& operator*();
+  };
+
+  using value_type = char;
+  using const_iterator = iterator;
+
+  PathLike() = default;
+
+  iterator begin() const { return iterator(); }
+  iterator end() const { return iterator(); }
+
+  friend ::std::ostream& operator<<(::std::ostream& os, const PathLike&) {
+    return os << "Streamable-PathLike";
+  }
+};
+
+}  // namespace foo
+
+namespace testing {
+namespace {
+template <typename T>
+class Wrapper {
+ public:
+  explicit Wrapper(T&& value) : value_(std::forward<T>(value)) {}
+
+  const T& value() const { return value_; }
+
+ private:
+  T value_;
+};
+
+}  // namespace
+
+namespace internal {
+template <typename T>
+class UniversalPrinter<Wrapper<T>> {
+ public:
+  static void Print(const Wrapper<T>& w, ::std::ostream* os) {
+    *os << "Wrapper(";
+    UniversalPrint(w.value(), os);
+    *os << ')';
+  }
+};
+}  // namespace internal
+
+namespace gtest_printers_test {
+
+using ::std::deque;
+using ::std::list;
+using ::std::make_pair;
+using ::std::map;
+using ::std::multimap;
+using ::std::multiset;
+using ::std::pair;
+using ::std::set;
+using ::std::vector;
+using ::testing::PrintToString;
+using ::testing::internal::FormatForComparisonFailureMessage;
+using ::testing::internal::NativeArray;
+using ::testing::internal::RelationToSourceReference;
+using ::testing::internal::Strings;
+using ::testing::internal::UniversalPrint;
+using ::testing::internal::UniversalPrinter;
+using ::testing::internal::UniversalTersePrint;
+using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
+
+// Prints a value to a string using the universal value printer.  This
+// is a helper for testing UniversalPrinter<T>::Print() for various types.
+template <typename T>
+std::string Print(const T& value) {
+  ::std::stringstream ss;
+  UniversalPrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+// Prints a value passed by reference to a string, using the universal
+// value printer.  This is a helper for testing
+// UniversalPrinter<T&>::Print() for various types.
+template <typename T>
+std::string PrintByRef(const T& value) {
+  ::std::stringstream ss;
+  UniversalPrinter<T&>::Print(value, &ss);
+  return ss.str();
+}
+
+// Tests printing various enum types.
+
+TEST(PrintEnumTest, AnonymousEnum) {
+  EXPECT_EQ("-1", Print(kAE1));
+  EXPECT_EQ("1", Print(kAE2));
+}
+
+TEST(PrintEnumTest, EnumWithoutPrinter) {
+  EXPECT_EQ("-2", Print(kEWP1));
+  EXPECT_EQ("42", Print(kEWP2));
+}
+
+TEST(PrintEnumTest, EnumWithStreaming) {
+  EXPECT_EQ("kEWS1", Print(kEWS1));
+  EXPECT_EQ("invalid", Print(static_cast<EnumWithStreaming>(0)));
+}
+
+TEST(PrintEnumTest, EnumWithPrintTo) {
+  EXPECT_EQ("kEWPT1", Print(kEWPT1));
+  EXPECT_EQ("invalid", Print(static_cast<EnumWithPrintTo>(0)));
+}
+
+#ifdef GTEST_HAS_ABSL
+// Tests printing a class that defines AbslStringify
+TEST(PrintClassTest, AbslStringify) { EXPECT_EQ("(10, 20)", Print(Point())); }
+#endif
+
+// Tests printing a class implicitly convertible to BiggestInt.
+
+TEST(PrintClassTest, BiggestIntConvertible) {
+  EXPECT_EQ("42", Print(BiggestIntConvertible()));
+}
+
+// Tests printing various char types.
+
+// char.
+TEST(PrintCharTest, PlainChar) {
+  EXPECT_EQ("'\\0'", Print('\0'));
+  EXPECT_EQ("'\\'' (39, 0x27)", Print('\''));
+  EXPECT_EQ("'\"' (34, 0x22)", Print('"'));
+  EXPECT_EQ("'?' (63, 0x3F)", Print('?'));
+  EXPECT_EQ("'\\\\' (92, 0x5C)", Print('\\'));
+  EXPECT_EQ("'\\a' (7)", Print('\a'));
+  EXPECT_EQ("'\\b' (8)", Print('\b'));
+  EXPECT_EQ("'\\f' (12, 0xC)", Print('\f'));
+  EXPECT_EQ("'\\n' (10, 0xA)", Print('\n'));
+  EXPECT_EQ("'\\r' (13, 0xD)", Print('\r'));
+  EXPECT_EQ("'\\t' (9)", Print('\t'));
+  EXPECT_EQ("'\\v' (11, 0xB)", Print('\v'));
+  EXPECT_EQ("'\\x7F' (127)", Print('\x7F'));
+  EXPECT_EQ("'\\xFF' (255)", Print('\xFF'));
+  EXPECT_EQ("' ' (32, 0x20)", Print(' '));
+  EXPECT_EQ("'a' (97, 0x61)", Print('a'));
+}
+
+// signed char.
+TEST(PrintCharTest, SignedChar) {
+  EXPECT_EQ("'\\0'", Print(static_cast<signed char>('\0')));
+  EXPECT_EQ("'\\xCE' (-50)", Print(static_cast<signed char>(-50)));
+}
+
+// unsigned char.
+TEST(PrintCharTest, UnsignedChar) {
+  EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0')));
+  EXPECT_EQ("'b' (98, 0x62)", Print(static_cast<unsigned char>('b')));
+}
+
+TEST(PrintCharTest, Char16) { EXPECT_EQ("U+0041", Print(u'A')); }
+
+TEST(PrintCharTest, Char32) { EXPECT_EQ("U+0041", Print(U'A')); }
+
+#ifdef __cpp_lib_char8_t
+TEST(PrintCharTest, Char8) { EXPECT_EQ("U+0041", Print(u8'A')); }
+#endif
+
+// Tests printing other simple, built-in types.
+
+// bool.
+TEST(PrintBuiltInTypeTest, Bool) {
+  EXPECT_EQ("false", Print(false));
+  EXPECT_EQ("true", Print(true));
+}
+
+// wchar_t.
+TEST(PrintBuiltInTypeTest, Wchar_t) {
+  EXPECT_EQ("L'\\0'", Print(L'\0'));
+  EXPECT_EQ("L'\\'' (39, 0x27)", Print(L'\''));
+  EXPECT_EQ("L'\"' (34, 0x22)", Print(L'"'));
+  EXPECT_EQ("L'?' (63, 0x3F)", Print(L'?'));
+  EXPECT_EQ("L'\\\\' (92, 0x5C)", Print(L'\\'));
+  EXPECT_EQ("L'\\a' (7)", Print(L'\a'));
+  EXPECT_EQ("L'\\b' (8)", Print(L'\b'));
+  EXPECT_EQ("L'\\f' (12, 0xC)", Print(L'\f'));
+  EXPECT_EQ("L'\\n' (10, 0xA)", Print(L'\n'));
+  EXPECT_EQ("L'\\r' (13, 0xD)", Print(L'\r'));
+  EXPECT_EQ("L'\\t' (9)", Print(L'\t'));
+  EXPECT_EQ("L'\\v' (11, 0xB)", Print(L'\v'));
+  EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F'));
+  EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF'));
+  EXPECT_EQ("L' ' (32, 0x20)", Print(L' '));
+  EXPECT_EQ("L'a' (97, 0x61)", Print(L'a'));
+  EXPECT_EQ("L'\\x576' (1398)", Print(static_cast<wchar_t>(0x576)));
+  EXPECT_EQ("L'\\xC74D' (51021)", Print(static_cast<wchar_t>(0xC74D)));
+}
+
+// Test that int64_t provides more storage than wchar_t.
+TEST(PrintTypeSizeTest, Wchar_t) {
+  EXPECT_LT(sizeof(wchar_t), sizeof(int64_t));
+}
+
+// Various integer types.
+TEST(PrintBuiltInTypeTest, Integer) {
+  EXPECT_EQ("'\\xFF' (255)", Print(static_cast<unsigned char>(255)));  // uint8
+  EXPECT_EQ("'\\x80' (-128)", Print(static_cast<signed char>(-128)));  // int8
+  EXPECT_EQ("65535", Print(std::numeric_limits<uint16_t>::max()));     // uint16
+  EXPECT_EQ("-32768", Print(std::numeric_limits<int16_t>::min()));     // int16
+  EXPECT_EQ("4294967295",
+            Print(std::numeric_limits<uint32_t>::max()));  // uint32
+  EXPECT_EQ("-2147483648",
+            Print(std::numeric_limits<int32_t>::min()));  // int32
+  EXPECT_EQ("18446744073709551615",
+            Print(std::numeric_limits<uint64_t>::max()));  // uint64
+  EXPECT_EQ("-9223372036854775808",
+            Print(std::numeric_limits<int64_t>::min()));  // int64
+#ifdef __cpp_lib_char8_t
+  EXPECT_EQ("U+0000",
+            Print(std::numeric_limits<char8_t>::min()));  // char8_t
+  EXPECT_EQ("U+00FF",
+            Print(std::numeric_limits<char8_t>::max()));  // char8_t
+#endif
+  EXPECT_EQ("U+0000",
+            Print(std::numeric_limits<char16_t>::min()));  // char16_t
+  EXPECT_EQ("U+FFFF",
+            Print(std::numeric_limits<char16_t>::max()));  // char16_t
+  EXPECT_EQ("U+0000",
+            Print(std::numeric_limits<char32_t>::min()));  // char32_t
+  EXPECT_EQ("U+FFFFFFFF",
+            Print(std::numeric_limits<char32_t>::max()));  // char32_t
+}
+
+// Size types.
+TEST(PrintBuiltInTypeTest, Size_t) {
+  EXPECT_EQ("1", Print(sizeof('a')));  // size_t.
+#ifndef GTEST_OS_WINDOWS
+  // Windows has no ssize_t type.
+  EXPECT_EQ("-2", Print(static_cast<ssize_t>(-2)));  // ssize_t.
+#endif                                               // !GTEST_OS_WINDOWS
+}
+
+// gcc/clang __{u,}int128_t values.
+#if defined(__SIZEOF_INT128__)
+TEST(PrintBuiltInTypeTest, Int128) {
+  // Small ones
+  EXPECT_EQ("0", Print(__int128_t{0}));
+  EXPECT_EQ("0", Print(__uint128_t{0}));
+  EXPECT_EQ("12345", Print(__int128_t{12345}));
+  EXPECT_EQ("12345", Print(__uint128_t{12345}));
+  EXPECT_EQ("-12345", Print(__int128_t{-12345}));
+
+  // Large ones
+  EXPECT_EQ("340282366920938463463374607431768211455", Print(~__uint128_t{}));
+  __int128_t max_128 = static_cast<__int128_t>(~__uint128_t{} / 2);
+  EXPECT_EQ("-170141183460469231731687303715884105728", Print(~max_128));
+  EXPECT_EQ("170141183460469231731687303715884105727", Print(max_128));
+}
+#endif  // __SIZEOF_INT128__
+
+// Floating-points.
+TEST(PrintBuiltInTypeTest, FloatingPoints) {
+  // float (32-bit precision)
+  EXPECT_EQ("1.5", Print(1.5f));
+
+  EXPECT_EQ("1.0999999", Print(1.09999990f));
+  EXPECT_EQ("1.1", Print(1.10000002f));
+  EXPECT_EQ("1.10000014", Print(1.10000014f));
+  EXPECT_EQ("9e+09", Print(9e9f));
+
+  // double
+  EXPECT_EQ("-2.5", Print(-2.5));  // double
+}
+
+#if GTEST_HAS_RTTI
+TEST(PrintBuiltInTypeTest, TypeInfo) {
+  struct MyStruct {};
+  auto res = Print(typeid(MyStruct{}));
+  // We can't guarantee that we can demangle the name, but either name should
+  // contain the substring "MyStruct".
+  EXPECT_NE(res.find("MyStruct"), res.npos) << res;
+}
+#endif  // GTEST_HAS_RTTI
+
+// Since ::std::stringstream::operator<<(const void *) formats the pointer
+// output differently with different compilers, we have to create the expected
+// output first and use it as our expectation.
+static std::string PrintPointer(const void* p) {
+  ::std::stringstream expected_result_stream;
+  expected_result_stream << p;
+  return expected_result_stream.str();
+}
+
+// Tests printing C strings.
+
+// const char*.
+TEST(PrintCStringTest, Const) {
+  const char* p = "World";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"World\"", Print(p));
+}
+
+// char*.
+TEST(PrintCStringTest, NonConst) {
+  char p[] = "Hi";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"Hi\"",
+            Print(static_cast<char*>(p)));
+}
+
+// NULL C string.
+TEST(PrintCStringTest, Null) {
+  const char* p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that C strings are escaped properly.
+TEST(PrintCStringTest, EscapesProperly) {
+  const char* p = "'\"?\\\a\b\f\n\r\t\v\x7F\xFF a";
+  EXPECT_EQ(PrintPointer(p) +
+                " pointing to \"'\\\"?\\\\\\a\\b\\f"
+                "\\n\\r\\t\\v\\x7F\\xFF a\"",
+            Print(p));
+}
+
+#ifdef __cpp_lib_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,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+
+// const wchar_t*.
+TEST(PrintWideCStringTest, Const) {
+  const wchar_t* p = L"World";
+  EXPECT_EQ(PrintPointer(p) + " pointing to L\"World\"", Print(p));
+}
+
+// wchar_t*.
+TEST(PrintWideCStringTest, NonConst) {
+  wchar_t p[] = L"Hi";
+  EXPECT_EQ(PrintPointer(p) + " pointing to L\"Hi\"",
+            Print(static_cast<wchar_t*>(p)));
+}
+
+// NULL wide C string.
+TEST(PrintWideCStringTest, Null) {
+  const wchar_t* p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that wide C strings are escaped properly.
+TEST(PrintWideCStringTest, EscapesProperly) {
+  const wchar_t s[] = {'\'',  '"',   '?',    '\\', '\a', '\b',
+                       '\f',  '\n',  '\r',   '\t', '\v', 0xD3,
+                       0x576, 0x8D3, 0xC74D, ' ',  'a',  '\0'};
+  EXPECT_EQ(PrintPointer(s) +
+                " pointing to L\"'\\\"?\\\\\\a\\b\\f"
+                "\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
+            Print(static_cast<const wchar_t*>(s)));
+}
+#endif  // native wchar_t
+
+// Tests printing pointers to other char types.
+
+// signed char*.
+TEST(PrintCharPointerTest, SignedChar) {
+  signed char* p = reinterpret_cast<signed char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const signed char*.
+TEST(PrintCharPointerTest, ConstSignedChar) {
+  signed char* p = reinterpret_cast<signed char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// unsigned char*.
+TEST(PrintCharPointerTest, UnsignedChar) {
+  unsigned char* p = reinterpret_cast<unsigned char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const unsigned char*.
+TEST(PrintCharPointerTest, ConstUnsignedChar) {
+  const unsigned char* p = reinterpret_cast<const unsigned char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing pointers to simple, built-in types.
+
+// bool*.
+TEST(PrintPointerToBuiltInTypeTest, Bool) {
+  bool* p = reinterpret_cast<bool*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// void*.
+TEST(PrintPointerToBuiltInTypeTest, Void) {
+  void* p = reinterpret_cast<void*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const void*.
+TEST(PrintPointerToBuiltInTypeTest, ConstVoid) {
+  const void* p = reinterpret_cast<const void*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing pointers to pointers.
+TEST(PrintPointerToPointerTest, IntPointerPointer) {
+  int** p = reinterpret_cast<int**>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = nullptr;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing (non-member) function pointers.
+
+void MyFunction(int /* n */) {}
+
+TEST(PrintPointerTest, NonMemberFunctionPointer) {
+  // We cannot directly cast &MyFunction to const void* because the
+  // standard disallows casting between pointers to functions and
+  // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
+  // this limitation.
+  EXPECT_EQ(PrintPointer(reinterpret_cast<const void*>(
+                reinterpret_cast<internal::BiggestInt>(&MyFunction))),
+            Print(&MyFunction));
+  int (*p)(bool) = NULL;  // NOLINT
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// An assertion predicate determining whether a one string is a prefix for
+// another.
+template <typename StringType>
+AssertionResult HasPrefix(const StringType& str, const StringType& prefix) {
+  if (str.find(prefix, 0) == 0) return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(prefix[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+         << begin_string_quote << prefix << "\" is not a prefix of "
+         << begin_string_quote << str << "\"\n";
+}
+
+// Tests printing member variable pointers.  Although they are called
+// pointers, they don't point to a location in the address space.
+// Their representation is implementation-defined.  Thus they will be
+// printed as raw bytes.
+
+struct Foo {
+ public:
+  virtual ~Foo() = default;
+  int MyMethod(char x) { return x + 1; }
+  virtual char MyVirtualMethod(int /* n */) { return 'a'; }
+
+  int value;
+};
+
+TEST(PrintPointerTest, MemberVariablePointer) {
+  EXPECT_TRUE(HasPrefix(Print(&Foo::value),
+                        Print(sizeof(&Foo::value)) + "-byte object "));
+  int Foo::*p = NULL;  // NOLINT
+  EXPECT_TRUE(HasPrefix(Print(p), Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests printing member function pointers.  Although they are called
+// pointers, they don't point to a location in the address space.
+// Their representation is implementation-defined.  Thus they will be
+// printed as raw bytes.
+TEST(PrintPointerTest, MemberFunctionPointer) {
+  EXPECT_TRUE(HasPrefix(Print(&Foo::MyMethod),
+                        Print(sizeof(&Foo::MyMethod)) + "-byte object "));
+  EXPECT_TRUE(
+      HasPrefix(Print(&Foo::MyVirtualMethod),
+                Print(sizeof((&Foo::MyVirtualMethod))) + "-byte object "));
+  int (Foo::*p)(char) = NULL;  // NOLINT
+  EXPECT_TRUE(HasPrefix(Print(p), Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests printing C arrays.
+
+// The difference between this and Print() is that it ensures that the
+// argument is a reference to an array.
+template <typename T, size_t N>
+std::string PrintArrayHelper(T (&a)[N]) {
+  return Print(a);
+}
+
+// One-dimensional array.
+TEST(PrintArrayTest, OneDimensionalArray) {
+  int a[5] = {1, 2, 3, 4, 5};
+  EXPECT_EQ("{ 1, 2, 3, 4, 5 }", PrintArrayHelper(a));
+}
+
+// Two-dimensional array.
+TEST(PrintArrayTest, TwoDimensionalArray) {
+  int a[2][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}};
+  EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", PrintArrayHelper(a));
+}
+
+// Array of const elements.
+TEST(PrintArrayTest, ConstArray) {
+  const bool a[1] = {false};
+  EXPECT_EQ("{ false }", PrintArrayHelper(a));
+}
+
+// char array without terminating NUL.
+TEST(PrintArrayTest, CharArrayWithNoTerminatingNul) {
+  // Array a contains '\0' in the middle and doesn't end with '\0'.
+  char a[] = {'H', '\0', 'i'};
+  EXPECT_EQ("\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
+}
+
+// char array with terminating NUL.
+TEST(PrintArrayTest, CharArrayWithTerminatingNul) {
+  const char a[] = "\0Hi";
+  EXPECT_EQ("\"\\0Hi\"", PrintArrayHelper(a));
+}
+
+#ifdef __cpp_lib_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'};
+  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.
+TEST(PrintArrayTest, ObjectArray) {
+  std::string a[3] = {"Hi", "Hello", "Ni hao"};
+  EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", PrintArrayHelper(a));
+}
+
+// Array with many elements.
+TEST(PrintArrayTest, BigArray) {
+  int a[100] = {1, 2, 3};
+  EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }",
+            PrintArrayHelper(a));
+}
+
+// Tests printing ::string and ::std::string.
+
+// ::std::string.
+TEST(PrintStringTest, StringInStdNamespace) {
+  const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
+  const ::std::string str(s, sizeof(s));
+  EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
+            Print(str));
+}
+
+TEST(PrintStringTest, StringAmbiguousHex) {
+  // "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
+  // '\x6', '\x6B', or '\x6BA'.
+
+  // a hex escaping sequence following by a decimal digit
+  EXPECT_EQ("\"0\\x12\" \"3\"", Print(::std::string("0\x12"
+                                                    "3")));
+  // a hex escaping sequence following by a hex digit (lower-case)
+  EXPECT_EQ("\"mm\\x6\" \"bananas\"", Print(::std::string("mm\x6"
+                                                          "bananas")));
+  // a hex escaping sequence following by a hex digit (upper-case)
+  EXPECT_EQ("\"NOM\\x6\" \"BANANA\"", Print(::std::string("NOM\x6"
+                                                          "BANANA")));
+  // a hex escaping sequence following by a non-xdigit
+  EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
+}
+
+// Tests printing ::std::wstring.
+#if GTEST_HAS_STD_WSTRING
+// ::std::wstring.
+TEST(PrintWideStringTest, StringInStdNamespace) {
+  const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
+  const ::std::wstring str(s, sizeof(s) / sizeof(wchar_t));
+  EXPECT_EQ(
+      "L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
+      "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
+      Print(str));
+}
+
+TEST(PrintWideStringTest, StringAmbiguousHex) {
+  // same for wide strings.
+  EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12"
+                                                       L"3")));
+  EXPECT_EQ("L\"mm\\x6\" L\"bananas\"", Print(::std::wstring(L"mm\x6"
+                                                             L"bananas")));
+  EXPECT_EQ("L\"NOM\\x6\" L\"BANANA\"", Print(::std::wstring(L"NOM\x6"
+                                                             L"BANANA")));
+  EXPECT_EQ("L\"!\\x5-!\"", Print(::std::wstring(L"!\x5-!")));
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifdef __cpp_lib_char8_t
+TEST(PrintStringTest, U8String) {
+  std::u8string str = u8"Hello, 世界";
+  EXPECT_EQ(str, str);  // Verify EXPECT_EQ compiles with this type.
+  EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
+}
+#endif
+
+TEST(PrintStringTest, U16String) {
+  std::u16string str = u"Hello, 世界";
+  EXPECT_EQ(str, str);  // Verify EXPECT_EQ compiles with this type.
+  EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
+}
+
+TEST(PrintStringTest, U32String) {
+  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
+// to std::basic_ostream<Char, CharTraits> for any valid Char and
+// CharTraits types).
+
+// Tests printing a non-template type that supports generic streaming.
+
+class AllowsGenericStreaming {};
+
+template <typename Char, typename CharTraits>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreaming& /* a */) {
+  return os << "AllowsGenericStreaming";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, NonTemplateType) {
+  AllowsGenericStreaming a;
+  EXPECT_EQ("AllowsGenericStreaming", Print(a));
+}
+
+// Tests printing a template type that supports generic streaming.
+
+template <typename T>
+class AllowsGenericStreamingTemplate {};
+
+template <typename Char, typename CharTraits, typename T>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreamingTemplate<T>& /* a */) {
+  return os << "AllowsGenericStreamingTemplate";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, TemplateType) {
+  AllowsGenericStreamingTemplate<int> a;
+  EXPECT_EQ("AllowsGenericStreamingTemplate", Print(a));
+}
+
+// Tests printing a type that supports generic streaming and can be
+// implicitly converted to another printable type.
+
+template <typename T>
+class AllowsGenericStreamingAndImplicitConversionTemplate {
+ public:
+  operator bool() const { return false; }
+};
+
+template <typename Char, typename CharTraits, typename T>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreamingAndImplicitConversionTemplate<T>& /* a */) {
+  return os << "AllowsGenericStreamingAndImplicitConversionTemplate";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
+  AllowsGenericStreamingAndImplicitConversionTemplate<int> a;
+  EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
+}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+
+// Tests printing internal::StringView.
+
+TEST(PrintStringViewTest, SimpleStringView) {
+  const internal::StringView sp = "Hello";
+  EXPECT_EQ("\"Hello\"", Print(sp));
+}
+
+TEST(PrintStringViewTest, UnprintableCharacters) {
+  const char str[] = "NUL (\0) and \r\t";
+  const internal::StringView sp(str, sizeof(str) - 1);
+  EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
+}
+
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+// Tests printing STL containers.
+
+TEST(PrintStlContainerTest, EmptyDeque) {
+  deque<char> empty;
+  EXPECT_EQ("{}", Print(empty));
+}
+
+TEST(PrintStlContainerTest, NonEmptyDeque) {
+  deque<int> non_empty;
+  non_empty.push_back(1);
+  non_empty.push_back(3);
+  EXPECT_EQ("{ 1, 3 }", Print(non_empty));
+}
+
+TEST(PrintStlContainerTest, OneElementHashMap) {
+  ::std::unordered_map<int, char> map1;
+  map1[1] = 'a';
+  EXPECT_EQ("{ (1, 'a' (97, 0x61)) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, HashMultiMap) {
+  ::std::unordered_multimap<int, bool> map1;
+  map1.insert(make_pair(5, true));
+  map1.insert(make_pair(5, false));
+
+  // Elements of hash_multimap can be printed in any order.
+  const std::string result = Print(map1);
+  EXPECT_TRUE(result == "{ (5, true), (5, false) }" ||
+              result == "{ (5, false), (5, true) }")
+      << " where Print(map1) returns \"" << result << "\".";
+}
+
+TEST(PrintStlContainerTest, HashSet) {
+  ::std::unordered_set<int> set1;
+  set1.insert(1);
+  EXPECT_EQ("{ 1 }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, HashMultiSet) {
+  const int kSize = 5;
+  int a[kSize] = {1, 1, 2, 5, 1};
+  ::std::unordered_multiset<int> set1(a, a + kSize);
+
+  // Elements of hash_multiset can be printed in any order.
+  const std::string result = Print(set1);
+  const std::string expected_pattern = "{ d, d, d, d, d }";  // d means a digit.
+
+  // Verifies the result matches the expected pattern; also extracts
+  // the numbers in the result.
+  ASSERT_EQ(expected_pattern.length(), result.length());
+  std::vector<int> numbers;
+  for (size_t i = 0; i != result.length(); i++) {
+    if (expected_pattern[i] == 'd') {
+      ASSERT_NE(isdigit(static_cast<unsigned char>(result[i])), 0);
+      numbers.push_back(result[i] - '0');
+    } else {
+      EXPECT_EQ(expected_pattern[i], result[i])
+          << " where result is " << result;
+    }
+  }
+
+  // Makes sure the result contains the right numbers.
+  std::sort(numbers.begin(), numbers.end());
+  std::sort(a, a + kSize);
+  EXPECT_TRUE(std::equal(a, a + kSize, numbers.begin()));
+}
+
+TEST(PrintStlContainerTest, List) {
+  const std::string a[] = {"hello", "world"};
+  const list<std::string> strings(a, a + 2);
+  EXPECT_EQ("{ \"hello\", \"world\" }", Print(strings));
+}
+
+TEST(PrintStlContainerTest, Map) {
+  map<int, bool> map1;
+  map1[1] = true;
+  map1[5] = false;
+  map1[3] = true;
+  EXPECT_EQ("{ (1, true), (3, true), (5, false) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, MultiMap) {
+  multimap<bool, int> map1;
+  // The make_pair template function would deduce the type as
+  // pair<bool, int> here, and since the key part in a multimap has to
+  // be constant, without a templated ctor in the pair class (as in
+  // libCstd on Solaris), make_pair call would fail to compile as no
+  // implicit conversion is found.  Thus explicit typename is used
+  // here instead.
+  map1.insert(pair<const bool, int>(true, 0));
+  map1.insert(pair<const bool, int>(true, 1));
+  map1.insert(pair<const bool, int>(false, 2));
+  EXPECT_EQ("{ (false, 2), (true, 0), (true, 1) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, Set) {
+  const unsigned int a[] = {3, 0, 5};
+  set<unsigned int> set1(a, a + 3);
+  EXPECT_EQ("{ 0, 3, 5 }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, MultiSet) {
+  const int a[] = {1, 1, 2, 5, 1};
+  multiset<int> set1(a, a + 5);
+  EXPECT_EQ("{ 1, 1, 1, 2, 5 }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, SinglyLinkedList) {
+  int a[] = {9, 2, 8};
+  const std::forward_list<int> ints(a, a + 3);
+  EXPECT_EQ("{ 9, 2, 8 }", Print(ints));
+}
+
+TEST(PrintStlContainerTest, Pair) {
+  pair<const bool, int> p(true, 5);
+  EXPECT_EQ("(true, 5)", Print(p));
+}
+
+TEST(PrintStlContainerTest, Vector) {
+  vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  EXPECT_EQ("{ 1, 2 }", Print(v));
+}
+
+TEST(PrintStlContainerTest, StdSpan) {
+#if GTEST_INTERNAL_HAS_STD_SPAN
+  int a[] = {3, 6, 5};
+  std::span<int> s = a;
+
+  EXPECT_EQ("{ 3, 6, 5 }", Print(s));
+#else
+  GTEST_SKIP() << "Does not have std::span.";
+#endif  // GTEST_INTERNAL_HAS_STD_SPAN
+}
+
+TEST(PrintStlContainerTest, LongSequence) {
+  const int a[100] = {1, 2, 3};
+  const vector<int> v(a, a + 100);
+  EXPECT_EQ(
+      "{ 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "
+      "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... }",
+      Print(v));
+}
+
+TEST(PrintStlContainerTest, NestedContainer) {
+  const int a1[] = {1, 2};
+  const int a2[] = {3, 4, 5};
+  const list<int> l1(a1, a1 + 2);
+  const list<int> l2(a2, a2 + 3);
+
+  vector<list<int>> v;
+  v.push_back(l1);
+  v.push_back(l2);
+  EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
+}
+
+TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
+  const int a[3] = {1, 2, 3};
+  NativeArray<int> b(a, 3, RelationToSourceReference());
+  EXPECT_EQ("{ 1, 2, 3 }", Print(b));
+}
+
+TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
+  const int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
+  NativeArray<int[3]> b(a, 2, RelationToSourceReference());
+  EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
+}
+
+// Tests that a class named iterator isn't treated as a container.
+
+struct iterator {
+  char x;
+};
+
+TEST(PrintStlContainerTest, Iterator) {
+  iterator it = {};
+  EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+// Tests that a class named const_iterator isn't treated as a container.
+
+struct const_iterator {
+  char x;
+};
+
+TEST(PrintStlContainerTest, ConstIterator) {
+  const_iterator it = {};
+  EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+// Tests printing ::std::tuples.
+
+// Tuples of various arities.
+TEST(PrintStdTupleTest, VariousSizes) {
+  ::std::tuple<> t0;
+  EXPECT_EQ("()", Print(t0));
+
+  ::std::tuple<int> t1(5);
+  EXPECT_EQ("(5)", Print(t1));
+
+  ::std::tuple<char, bool> t2('a', true);
+  EXPECT_EQ("('a' (97, 0x61), true)", Print(t2));
+
+  ::std::tuple<bool, int, int> t3(false, 2, 3);
+  EXPECT_EQ("(false, 2, 3)", Print(t3));
+
+  ::std::tuple<bool, int, int, int> t4(false, 2, 3, 4);
+  EXPECT_EQ("(false, 2, 3, 4)", Print(t4));
+
+  const char* const str = "8";
+  ::std::tuple<bool, char, short, int32_t, int64_t, float, double,  // NOLINT
+               const char*, void*, std::string>
+      t10(false, 'a', static_cast<short>(3), 4, 5, 1.5F, -2.5, str,  // NOLINT
+          nullptr, "10");
+  EXPECT_EQ("(false, 'a' (97, 0x61), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) +
+                " pointing to \"8\", NULL, \"10\")",
+            Print(t10));
+}
+
+// Nested tuples.
+TEST(PrintStdTupleTest, NestedTuple) {
+  ::std::tuple<::std::tuple<int, bool>, char> nested(::std::make_tuple(5, true),
+                                                     'a');
+  EXPECT_EQ("((5, true), 'a' (97, 0x61))", Print(nested));
+}
+
+TEST(PrintNullptrT, Basic) { EXPECT_EQ("(nullptr)", Print(nullptr)); }
+
+TEST(PrintReferenceWrapper, Printable) {
+  int x = 5;
+  EXPECT_EQ("@" + PrintPointer(&x) + " 5", Print(std::ref(x)));
+  EXPECT_EQ("@" + PrintPointer(&x) + " 5", Print(std::cref(x)));
+}
+
+TEST(PrintReferenceWrapper, Unprintable) {
+  ::foo::UnprintableInFoo up;
+  EXPECT_EQ(
+      "@" + PrintPointer(&up) +
+          " 16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+      Print(std::ref(up)));
+  EXPECT_EQ(
+      "@" + PrintPointer(&up) +
+          " 16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+      Print(std::cref(up)));
+}
+
+// Tests printing user-defined unprintable types.
+
+// Unprintable types in the global namespace.
+TEST(PrintUnprintableTypeTest, InGlobalNamespace) {
+  EXPECT_EQ("1-byte object <00>", Print(UnprintableTemplateInGlobal<char>()));
+}
+
+// Unprintable types in a user namespace.
+TEST(PrintUnprintableTypeTest, InUserNamespace) {
+  EXPECT_EQ("16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+            Print(::foo::UnprintableInFoo()));
+}
+
+// Unprintable types are that too big to be printed completely.
+
+struct Big {
+  Big() { memset(array, 0, sizeof(array)); }
+  char array[257];
+};
+
+TEST(PrintUnpritableTypeTest, BigObject) {
+  EXPECT_EQ(
+      "257-byte object <00-00 00-00 00-00 00-00 00-00 00-00 "
+      "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+      "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+      "00-00 00-00 00-00 00-00 00-00 00-00 ... 00-00 00-00 00-00 "
+      "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+      "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+      "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00>",
+      Print(Big()));
+}
+
+// Tests printing user-defined streamable types.
+
+// Streamable types in the global namespace.
+TEST(PrintStreamableTypeTest, InGlobalNamespace) {
+  StreamableInGlobal x;
+  EXPECT_EQ("StreamableInGlobal", Print(x));
+  EXPECT_EQ("StreamableInGlobal*", Print(&x));
+}
+
+// Printable template types in a user namespace.
+TEST(PrintStreamableTypeTest, TemplateTypeInUserNamespace) {
+  EXPECT_EQ("StreamableTemplateInFoo: 0",
+            Print(::foo::StreamableTemplateInFoo<int>()));
+}
+
+TEST(PrintStreamableTypeTest, TypeInUserNamespaceWithTemplatedStreamOperator) {
+  EXPECT_EQ("TemplatedStreamableInFoo",
+            Print(::foo::TemplatedStreamableInFoo()));
+}
+
+TEST(PrintStreamableTypeTest, SubclassUsesSuperclassStreamOperator) {
+  ParentClass parent;
+  ChildClassWithStreamOperator child_stream;
+  ChildClassWithoutStreamOperator child_no_stream;
+  EXPECT_EQ("ParentClass", Print(parent));
+  EXPECT_EQ("ChildClassWithStreamOperator", Print(child_stream));
+  EXPECT_EQ("ParentClass", Print(child_no_stream));
+}
+
+// Tests printing a user-defined recursive container type that has a <<
+// operator.
+TEST(PrintStreamableTypeTest, PathLikeInUserNamespace) {
+  ::foo::PathLike x;
+  EXPECT_EQ("Streamable-PathLike", Print(x));
+  const ::foo::PathLike cx;
+  EXPECT_EQ("Streamable-PathLike", Print(cx));
+}
+
+// Tests printing user-defined types that have a PrintTo() function.
+TEST(PrintPrintableTypeTest, InUserNamespace) {
+  EXPECT_EQ("PrintableViaPrintTo: 0", Print(::foo::PrintableViaPrintTo()));
+}
+
+// Tests printing a pointer to a user-defined type that has a <<
+// operator for its pointer.
+TEST(PrintPrintableTypeTest, PointerInUserNamespace) {
+  ::foo::PointerPrintable x;
+  EXPECT_EQ("PointerPrintable*", Print(&x));
+}
+
+// Tests printing user-defined class template that have a PrintTo() function.
+TEST(PrintPrintableTypeTest, TemplateInUserNamespace) {
+  EXPECT_EQ("PrintableViaPrintToTemplate: 5",
+            Print(::foo::PrintableViaPrintToTemplate<int>(5)));
+}
+
+// Tests that the universal printer prints both the address and the
+// value of a reference.
+TEST(PrintReferenceTest, PrintsAddressAndValue) {
+  int n = 5;
+  EXPECT_EQ("@" + PrintPointer(&n) + " 5", PrintByRef(n));
+
+  int a[2][3] = {{0, 1, 2}, {3, 4, 5}};
+  EXPECT_EQ("@" + PrintPointer(a) + " { { 0, 1, 2 }, { 3, 4, 5 } }",
+            PrintByRef(a));
+
+  const ::foo::UnprintableInFoo x;
+  EXPECT_EQ("@" + PrintPointer(&x) +
+                " 16-byte object "
+                "<EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+            PrintByRef(x));
+}
+
+// Tests that the universal printer prints a function pointer passed by
+// reference.
+TEST(PrintReferenceTest, HandlesFunctionPointer) {
+  void (*fp)(int n) = &MyFunction;
+  const std::string fp_pointer_string =
+      PrintPointer(reinterpret_cast<const void*>(&fp));
+  // We cannot directly cast &MyFunction to const void* because the
+  // standard disallows casting between pointers to functions and
+  // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
+  // this limitation.
+  const std::string fp_string = PrintPointer(reinterpret_cast<const void*>(
+      reinterpret_cast<internal::BiggestInt>(fp)));
+  EXPECT_EQ("@" + fp_pointer_string + " " + fp_string, PrintByRef(fp));
+}
+
+// Tests that the universal printer prints a member function pointer
+// passed by reference.
+TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
+  int (Foo::*p)(char ch) = &Foo::MyMethod;
+  EXPECT_TRUE(HasPrefix(PrintByRef(p),
+                        "@" + PrintPointer(reinterpret_cast<const void*>(&p)) +
+                            " " + Print(sizeof(p)) + "-byte object "));
+
+  char (Foo::*p2)(int n) = &Foo::MyVirtualMethod;
+  EXPECT_TRUE(HasPrefix(PrintByRef(p2),
+                        "@" + PrintPointer(reinterpret_cast<const void*>(&p2)) +
+                            " " + Print(sizeof(p2)) + "-byte object "));
+}
+
+// Tests that the universal printer prints a member variable pointer
+// passed by reference.
+TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
+  int Foo::*p = &Foo::value;  // NOLINT
+  EXPECT_TRUE(HasPrefix(PrintByRef(p), "@" + PrintPointer(&p) + " " +
+                                           Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests that FormatForComparisonFailureMessage(), which is used to print
+// an operand in a comparison assertion (e.g. ASSERT_EQ) when the assertion
+// fails, formats the operand in the desired way.
+
+// scalar
+TEST(FormatForComparisonFailureMessageTest, WorksForScalar) {
+  EXPECT_STREQ("123", FormatForComparisonFailureMessage(123, 124).c_str());
+}
+
+// non-char pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForNonCharPointer) {
+  int n = 0;
+  EXPECT_EQ(PrintPointer(&n),
+            FormatForComparisonFailureMessage(&n, &n).c_str());
+}
+
+// non-char array
+TEST(FormatForComparisonFailureMessageTest, FormatsNonCharArrayAsPointer) {
+  // In expression 'array == x', 'array' is compared by pointer.
+  // Therefore we want to print an array operand as a pointer.
+  int n[] = {1, 2, 3};
+  EXPECT_EQ(PrintPointer(n), FormatForComparisonFailureMessage(n, n).c_str());
+}
+
+// Tests formatting a char pointer when it's compared with another pointer.
+// In this case we want to print it as a raw pointer, as the comparison is by
+// pointer.
+
+// char pointer vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsPointer) {
+  // In expression 'p == x', where 'p' and 'x' are (const or not) char
+  // pointers, the operands are compared by pointer.  Therefore we
+  // want to print 'p' as a pointer instead of a C string (we don't
+  // even know if it's supposed to point to a valid C string).
+
+  // const char*
+  const char* s = "hello";
+  EXPECT_EQ(PrintPointer(s), FormatForComparisonFailureMessage(s, s).c_str());
+
+  // char*
+  char ch = 'a';
+  EXPECT_EQ(PrintPointer(&ch),
+            FormatForComparisonFailureMessage(&ch, &ch).c_str());
+}
+
+// wchar_t pointer vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsPointer) {
+  // In expression 'p == x', where 'p' and 'x' are (const or not) char
+  // pointers, the operands are compared by pointer.  Therefore we
+  // want to print 'p' as a pointer instead of a wide C string (we don't
+  // even know if it's supposed to point to a valid wide C string).
+
+  // const wchar_t*
+  const wchar_t* s = L"hello";
+  EXPECT_EQ(PrintPointer(s), FormatForComparisonFailureMessage(s, s).c_str());
+
+  // wchar_t*
+  wchar_t ch = L'a';
+  EXPECT_EQ(PrintPointer(&ch),
+            FormatForComparisonFailureMessage(&ch, &ch).c_str());
+}
+
+// Tests formatting a char pointer when it's compared to a string object.
+// In this case we want to print the char pointer as a C string.
+
+// char pointer vs std::string
+TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsStdString) {
+  const char* s = "hello \"world";
+  EXPECT_STREQ("\"hello \\\"world\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(s, ::std::string()).c_str());
+
+  // char*
+  char str[] = "hi\1";
+  char* p = str;
+  EXPECT_STREQ("\"hi\\x1\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(p, ::std::string()).c_str());
+}
+
+#if GTEST_HAS_STD_WSTRING
+// wchar_t pointer vs std::wstring
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsStdWString) {
+  const wchar_t* s = L"hi \"world";
+  EXPECT_STREQ("L\"hi \\\"world\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(s, ::std::wstring()).c_str());
+
+  // wchar_t*
+  wchar_t str[] = L"hi\1";
+  wchar_t* p = str;
+  EXPECT_STREQ("L\"hi\\x1\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(p, ::std::wstring()).c_str());
+}
+#endif
+
+// Tests formatting a char array when it's compared with a pointer or array.
+// In this case we want to print the array as a row pointer, as the comparison
+// is by pointer.
+
+// char array vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsPointer) {
+  char str[] = "hi \"world\"";
+  char* p = nullptr;
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, p).c_str());
+}
+
+// char array vs char array
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsCharArray) {
+  const char str[] = "hi \"world\"";
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, str).c_str());
+}
+
+// wchar_t array vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsPointer) {
+  wchar_t str[] = L"hi \"world\"";
+  wchar_t* p = nullptr;
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, p).c_str());
+}
+
+// wchar_t array vs wchar_t array
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsWCharArray) {
+  const wchar_t str[] = L"hi \"world\"";
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, str).c_str());
+}
+
+// Tests formatting a char array when it's compared with a string object.
+// In this case we want to print the array as a C string.
+
+// char array vs std::string
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsStdString) {
+  const char str[] = "hi \"world\"";
+  EXPECT_STREQ("\"hi \\\"world\\\"\"",  // The content should be escaped.
+               FormatForComparisonFailureMessage(str, ::std::string()).c_str());
+}
+
+#if GTEST_HAS_STD_WSTRING
+// wchar_t array vs std::wstring
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsStdWString) {
+  const wchar_t str[] = L"hi \"w\0rld\"";
+  EXPECT_STREQ(
+      "L\"hi \\\"w\"",  // The content should be escaped.
+                        // Embedded NUL terminates the string.
+      FormatForComparisonFailureMessage(str, ::std::wstring()).c_str());
+}
+#endif
+
+// Useful for testing PrintToString().  We cannot use EXPECT_EQ()
+// there as its implementation uses PrintToString().  The caller must
+// ensure that 'value' has no side effect.
+#define EXPECT_PRINT_TO_STRING_(value, expected_string)  \
+  EXPECT_TRUE(PrintToString(value) == (expected_string)) \
+      << " where " #value " prints as " << (PrintToString(value))
+
+TEST(PrintToStringTest, WorksForScalar) { EXPECT_PRINT_TO_STRING_(123, "123"); }
+
+TEST(PrintToStringTest, WorksForPointerToConstChar) {
+  const char* p = "hello";
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
+}
+
+TEST(PrintToStringTest, WorksForPointerToNonConstChar) {
+  char s[] = "hello";
+  char* p = s;
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
+}
+
+TEST(PrintToStringTest, EscapesForPointerToConstChar) {
+  const char* p = "hello\n";
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\\n\"");
+}
+
+TEST(PrintToStringTest, EscapesForPointerToNonConstChar) {
+  char s[] = "hello\1";
+  char* p = s;
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\\x1\"");
+}
+
+TEST(PrintToStringTest, WorksForArray) {
+  int n[3] = {1, 2, 3};
+  EXPECT_PRINT_TO_STRING_(n, "{ 1, 2, 3 }");
+}
+
+TEST(PrintToStringTest, WorksForCharArray) {
+  char s[] = "hello";
+  EXPECT_PRINT_TO_STRING_(s, "\"hello\"");
+}
+
+TEST(PrintToStringTest, WorksForCharArrayWithEmbeddedNul) {
+  const char str_with_nul[] = "hello\0 world";
+  EXPECT_PRINT_TO_STRING_(str_with_nul, "\"hello\\0 world\"");
+
+  char mutable_str_with_nul[] = "hello\0 world";
+  EXPECT_PRINT_TO_STRING_(mutable_str_with_nul, "\"hello\\0 world\"");
+}
+
+TEST(PrintToStringTest, ContainsNonLatin) {
+  // Test with valid UTF-8. Prints both in hex and as text.
+  std::string non_ascii_str = ::std::string("오전 4:30");
+  EXPECT_PRINT_TO_STRING_(non_ascii_str,
+                          "\"\\xEC\\x98\\xA4\\xEC\\xA0\\x84 4:30\"\n"
+                          "    As Text: \"오전 4:30\"");
+  non_ascii_str = ::std::string("From ä — ẑ");
+  EXPECT_PRINT_TO_STRING_(non_ascii_str,
+                          "\"From \\xC3\\xA4 \\xE2\\x80\\x94 \\xE1\\xBA\\x91\""
+                          "\n    As Text: \"From ä — ẑ\"");
+}
+
+TEST(PrintToStringTest, PrintStreamableInLocal) {
+  EXPECT_STREQ("StreamableInLocal",
+               PrintToString(foo::StreamableInLocal()).c_str());
+}
+
+TEST(PrintToStringTest, PrintReferenceToStreamableInLocal) {
+  foo::StreamableInLocal s;
+  std::reference_wrapper<foo::StreamableInLocal> r(s);
+  EXPECT_STREQ("StreamableInLocal", PrintToString(r).c_str());
+}
+
+TEST(PrintToStringTest, PrintReferenceToStreamableInGlobal) {
+  StreamableInGlobal s;
+  std::reference_wrapper<StreamableInGlobal> r(s);
+  EXPECT_STREQ("StreamableInGlobal", PrintToString(r).c_str());
+}
+
+#ifdef GTEST_HAS_ABSL
+TEST(PrintToStringTest, AbslStringify) {
+  EXPECT_PRINT_TO_STRING_(Point(), "(10, 20)");
+}
+#endif
+
+TEST(IsValidUTF8Test, IllFormedUTF8) {
+  // The following test strings are ill-formed UTF-8 and are printed
+  // as hex only (or ASCII, in case of ASCII bytes) because IsValidUTF8() is
+  // expected to fail, thus output does not contain "As Text:".
+
+  static const char* const kTestdata[][2] = {
+      // 2-byte lead byte followed by a single-byte character.
+      {"\xC3\x74", "\"\\xC3t\""},
+      // Valid 2-byte character followed by an orphan trail byte.
+      {"\xC3\x84\xA4", "\"\\xC3\\x84\\xA4\""},
+      // Lead byte without trail byte.
+      {"abc\xC3", "\"abc\\xC3\""},
+      // 3-byte lead byte, single-byte character, orphan trail byte.
+      {"x\xE2\x70\x94", "\"x\\xE2p\\x94\""},
+      // Truncated 3-byte character.
+      {"\xE2\x80", "\"\\xE2\\x80\""},
+      // Truncated 3-byte character followed by valid 2-byte char.
+      {"\xE2\x80\xC3\x84", "\"\\xE2\\x80\\xC3\\x84\""},
+      // Truncated 3-byte character followed by a single-byte character.
+      {"\xE2\x80\x7A", "\"\\xE2\\x80z\""},
+      // 3-byte lead byte followed by valid 3-byte character.
+      {"\xE2\xE2\x80\x94", "\"\\xE2\\xE2\\x80\\x94\""},
+      // 4-byte lead byte followed by valid 3-byte character.
+      {"\xF0\xE2\x80\x94", "\"\\xF0\\xE2\\x80\\x94\""},
+      // Truncated 4-byte character.
+      {"\xF0\xE2\x80", "\"\\xF0\\xE2\\x80\""},
+      // Invalid UTF-8 byte sequences embedded in other chars.
+      {"abc\xE2\x80\x94\xC3\x74xyc", "\"abc\\xE2\\x80\\x94\\xC3txyc\""},
+      {"abc\xC3\x84\xE2\x80\xC3\x84xyz",
+       "\"abc\\xC3\\x84\\xE2\\x80\\xC3\\x84xyz\""},
+      // Non-shortest UTF-8 byte sequences are also ill-formed.
+      // The classics: xC0, xC1 lead byte.
+      {"\xC0\x80", "\"\\xC0\\x80\""},
+      {"\xC1\x81", "\"\\xC1\\x81\""},
+      // Non-shortest sequences.
+      {"\xE0\x80\x80", "\"\\xE0\\x80\\x80\""},
+      {"\xf0\x80\x80\x80", "\"\\xF0\\x80\\x80\\x80\""},
+      // Last valid code point before surrogate range, should be printed as
+      // text,
+      // too.
+      {"\xED\x9F\xBF", "\"\\xED\\x9F\\xBF\"\n    As Text: \"퟿\""},
+      // Start of surrogate lead. Surrogates are not printed as text.
+      {"\xED\xA0\x80", "\"\\xED\\xA0\\x80\""},
+      // Last non-private surrogate lead.
+      {"\xED\xAD\xBF", "\"\\xED\\xAD\\xBF\""},
+      // First private-use surrogate lead.
+      {"\xED\xAE\x80", "\"\\xED\\xAE\\x80\""},
+      // Last private-use surrogate lead.
+      {"\xED\xAF\xBF", "\"\\xED\\xAF\\xBF\""},
+      // Mid-point of surrogate trail.
+      {"\xED\xB3\xBF", "\"\\xED\\xB3\\xBF\""},
+      // First valid code point after surrogate range, should be printed as
+      // text,
+      // too.
+      {"\xEE\x80\x80", "\"\\xEE\\x80\\x80\"\n    As Text: \"\""}};
+
+  for (int i = 0; i < int(sizeof(kTestdata) / sizeof(kTestdata[0])); ++i) {
+    EXPECT_PRINT_TO_STRING_(kTestdata[i][0], kTestdata[i][1]);
+  }
+}
+
+#undef EXPECT_PRINT_TO_STRING_
+
+TEST(UniversalTersePrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalTersePrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalTersePrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalTersePrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalTersePrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalTersePrint(s1, &ss1);
+  EXPECT_EQ("\"abc\"", ss1.str());
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalTersePrint(s2, &ss2);
+  EXPECT_EQ("\"abc\"", ss2.str());
+
+  const char* s3 = nullptr;
+  ::std::stringstream ss3;
+  UniversalTersePrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+TEST(UniversalPrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalPrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalPrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForPairWithConst) {
+  std::pair<const Wrapper<std::string>, int> p(Wrapper<std::string>("abc"), 1);
+  ::std::stringstream ss;
+  UniversalPrint(p, &ss);
+  EXPECT_EQ("(Wrapper(\"abc\"), 1)", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalPrint(s1, &ss1);
+  EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", std::string(ss1.str()));
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalPrint(s2, &ss2);
+  EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", std::string(ss2.str()));
+
+  const char* s3 = nullptr;
+  ::std::stringstream ss3;
+  UniversalPrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+TEST(UniversalPrintTest, WorksForCharArray) {
+  const char str[] = "\"Line\0 1\"\nLine 2";
+  ::std::stringstream ss1;
+  UniversalPrint(str, &ss1);
+  EXPECT_EQ("\"\\\"Line\\0 1\\\"\\nLine 2\"", ss1.str());
+
+  const char mutable_str[] = "\"Line\0 1\"\nLine 2";
+  ::std::stringstream ss2;
+  UniversalPrint(mutable_str, &ss2);
+  EXPECT_EQ("\"\\\"Line\\0 1\\\"\\nLine 2\"", ss2.str());
+}
+
+TEST(UniversalPrintTest, IncompleteType) {
+  struct Incomplete;
+  char some_object = 0;
+  EXPECT_EQ("(incomplete type)",
+            PrintToString(reinterpret_cast<Incomplete&>(some_object)));
+}
+
+TEST(UniversalPrintTest, SmartPointers) {
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<int>()));
+  std::unique_ptr<int> p(new int(17));
+  EXPECT_EQ("(ptr = " + PrintPointer(p.get()) + ", value = 17)",
+            PrintToString(p));
+  std::unique_ptr<int[]> p2(new int[2]);
+  EXPECT_EQ("(" + PrintPointer(p2.get()) + ")", PrintToString(p2));
+
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<int>()));
+  std::shared_ptr<int> p3(new int(1979));
+  EXPECT_EQ("(ptr = " + PrintPointer(p3.get()) + ", value = 1979)",
+            PrintToString(p3));
+#if defined(__cpp_lib_shared_ptr_arrays) && \
+    (__cpp_lib_shared_ptr_arrays >= 201611L)
+  std::shared_ptr<int[]> p4(new int[2]);
+  EXPECT_EQ("(" + PrintPointer(p4.get()) + ")", PrintToString(p4));
+#endif
+
+  // modifiers
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<const int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<volatile int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<volatile const int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<int[]>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<const int[]>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<volatile int[]>()));
+  EXPECT_EQ("(nullptr)",
+            PrintToString(std::unique_ptr<volatile const int[]>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<const int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<volatile int>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<volatile const int>()));
+#if defined(__cpp_lib_shared_ptr_arrays) && \
+    (__cpp_lib_shared_ptr_arrays >= 201611L)
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<int[]>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<const int[]>()));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<volatile int[]>()));
+  EXPECT_EQ("(nullptr)",
+            PrintToString(std::shared_ptr<volatile const int[]>()));
+#endif
+
+  // void
+  EXPECT_EQ("(nullptr)", PrintToString(std::unique_ptr<void, void (*)(void*)>(
+                             nullptr, nullptr)));
+  EXPECT_EQ("(" + PrintPointer(p.get()) + ")",
+            PrintToString(
+                std::unique_ptr<void, void (*)(void*)>(p.get(), [](void*) {})));
+  EXPECT_EQ("(nullptr)", PrintToString(std::shared_ptr<void>()));
+  EXPECT_EQ("(" + PrintPointer(p.get()) + ")",
+            PrintToString(std::shared_ptr<void>(p.get(), [](void*) {})));
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
+  EXPECT_EQ(0u, result.size());
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsOneTuple) {
+  Strings result =
+      UniversalTersePrintTupleFieldsToStrings(::std::make_tuple(1));
+  ASSERT_EQ(1u, result.size());
+  EXPECT_EQ("1", result[0]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTwoTuple) {
+  Strings result =
+      UniversalTersePrintTupleFieldsToStrings(::std::make_tuple(1, 'a'));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("'a' (97, 0x61)", result[1]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
+  const int n = 1;
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::tuple<const int&, const char*>(n, "a"));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("\"a\"", result[1]);
+}
+
+#if GTEST_INTERNAL_HAS_ANY
+class PrintAnyTest : public ::testing::Test {
+ protected:
+  template <typename T>
+  static std::string ExpectedTypeName() {
+#if GTEST_HAS_RTTI
+    return internal::GetTypeName<T>();
+#else
+    return "<unknown_type>";
+#endif  // GTEST_HAS_RTTI
+  }
+};
+
+TEST_F(PrintAnyTest, Empty) {
+  internal::Any any;
+  EXPECT_EQ("no value", PrintToString(any));
+}
+
+TEST_F(PrintAnyTest, NonEmpty) {
+  internal::Any any;
+  constexpr int val1 = 10;
+  const std::string val2 = "content";
+
+  any = val1;
+  EXPECT_EQ("value of type " + ExpectedTypeName<int>(), PrintToString(any));
+
+  any = val2;
+  EXPECT_EQ("value of type " + ExpectedTypeName<std::string>(),
+            PrintToString(any));
+}
+#endif  // GTEST_INTERNAL_HAS_ANY
+
+#if GTEST_INTERNAL_HAS_OPTIONAL
+TEST(PrintOptionalTest, Basic) {
+  EXPECT_EQ("(nullopt)", PrintToString(internal::Nullopt()));
+  internal::Optional<int> value;
+  EXPECT_EQ("(nullopt)", PrintToString(value));
+  value = {7};
+  EXPECT_EQ("(7)", PrintToString(value));
+  EXPECT_EQ("(1.1)", PrintToString(internal::Optional<double>{1.1}));
+  EXPECT_EQ("(\"A\")", PrintToString(internal::Optional<std::string>{"A"}));
+}
+#endif  // GTEST_INTERNAL_HAS_OPTIONAL
+
+#if GTEST_INTERNAL_HAS_VARIANT
+struct NonPrintable {
+  unsigned char contents = 17;
+};
+
+TEST(PrintOneofTest, Basic) {
+  using Type = internal::Variant<int, StreamableInGlobal, NonPrintable>;
+  EXPECT_EQ("('int(index = 0)' with value 7)", PrintToString(Type(7)));
+  EXPECT_EQ("('StreamableInGlobal(index = 1)' with value StreamableInGlobal)",
+            PrintToString(Type(StreamableInGlobal{})));
+  EXPECT_EQ(
+      "('testing::gtest_printers_test::NonPrintable(index = 2)' with value "
+      "1-byte object <11>)",
+      PrintToString(Type(NonPrintable{})));
+}
+#endif  // GTEST_INTERNAL_HAS_VARIANT
+namespace {
+class string_ref;
+
+/**
+ * This is a synthetic pointer to a fixed size string.
+ */
+class string_ptr {
+ public:
+  string_ptr(const char* data, size_t size) : data_(data), size_(size) {}
+
+  string_ptr& operator++() noexcept {
+    data_ += size_;
+    return *this;
+  }
+
+  string_ref operator*() const noexcept;
+
+ private:
+  const char* data_;
+  size_t size_;
+};
+
+/**
+ * This is a synthetic reference of a fixed size string.
+ */
+class string_ref {
+ public:
+  string_ref(const char* data, size_t size) : data_(data), size_(size) {}
+
+  string_ptr operator&() const noexcept { return {data_, size_}; }  // NOLINT
+
+  bool operator==(const char* s) const noexcept {
+    if (size_ > 0 && data_[size_ - 1] != 0) {
+      return std::string(data_, size_) == std::string(s);
+    } else {
+      return std::string(data_) == std::string(s);
+    }
+  }
+
+ private:
+  const char* data_;
+  size_t size_;
+};
+
+string_ref string_ptr::operator*() const noexcept { return {data_, size_}; }
+
+TEST(string_ref, compare) {
+  const char* s = "alex\0davidjohn\0";
+  string_ptr ptr(s, 5);
+  EXPECT_EQ(*ptr, "alex");
+  EXPECT_TRUE(*ptr == "alex");
+  ++ptr;
+  EXPECT_EQ(*ptr, "david");
+  EXPECT_TRUE(*ptr == "david");
+  ++ptr;
+  EXPECT_EQ(*ptr, "john");
+}
+
+}  // namespace
+
+}  // namespace gtest_printers_test
+}  // namespace testing
diff --git a/3rd-party/googletest/googletest/test/googletest-setuptestsuite-test.py b/3rd-party/googletest/googletest/test/googletest-setuptestsuite-test.py
new file mode 100755
index 0000000..899531f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-setuptestsuite-test.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+#
+# Copyright 2019, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that SetUpTestSuite and TearDownTestSuite errors are noticed."""
+
+from googletest.test import gtest_test_utils
+
+COMMAND = gtest_test_utils.GetTestExecutablePath(
+    'googletest-setuptestsuite-test_'
+)
+
+
+class GTestSetUpTestSuiteTest(gtest_test_utils.TestCase):
+
+  def testSetupErrorAndTearDownError(self):
+    p = gtest_test_utils.Subprocess(COMMAND)
+    self.assertNotEqual(p.exit_code, 0, msg=p.output)
+
+    self.assertIn(
+        (
+            '[  FAILED  ] SetupFailTest: SetUpTestSuite or TearDownTestSuite\n['
+            '  FAILED  ] TearDownFailTest: SetUpTestSuite or'
+            ' TearDownTestSuite\n\n 2 FAILED TEST SUITES\n'
+        ),
+        p.output,
+    )
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-setuptestsuite-test_.cc b/3rd-party/googletest/googletest/test/googletest-setuptestsuite-test_.cc
new file mode 100644
index 0000000..d20899f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-setuptestsuite-test_.cc
@@ -0,0 +1,44 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest.h"
+
+class SetupFailTest : public ::testing::Test {
+ protected:
+  static void SetUpTestSuite() { ASSERT_EQ("", "SET_UP_FAIL"); }
+};
+
+TEST_F(SetupFailTest, NoopPassingTest) {}
+
+class TearDownFailTest : public ::testing::Test {
+ protected:
+  static void TearDownTestSuite() { ASSERT_EQ("", "TEAR_DOWN_FAIL"); }
+};
+
+TEST_F(TearDownFailTest, NoopPassingTest) {}
diff --git a/3rd-party/googletest/googletest/test/googletest-shuffle-test.py b/3rd-party/googletest/googletest/test/googletest-shuffle-test.py
new file mode 100755
index 0000000..61e3a15
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-shuffle-test.py
@@ -0,0 +1,378 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that test shuffling works."""
+
+import os
+from googletest.test import gtest_test_utils
+
+# Command to run the googletest-shuffle-test_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-shuffle-test_')
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+
+TEST_FILTER = 'A*.A:A*.B:C*'
+
+ALL_TESTS = []
+ACTIVE_TESTS = []
+FILTERED_TESTS = []
+SHARDED_TESTS = []
+
+SHUFFLED_ALL_TESTS = []
+SHUFFLED_ACTIVE_TESTS = []
+SHUFFLED_FILTERED_TESTS = []
+SHUFFLED_SHARDED_TESTS = []
+
+
+def AlsoRunDisabledTestsFlag():
+  return '--gtest_also_run_disabled_tests'
+
+
+def FilterFlag(test_filter):
+  return '--gtest_filter=%s' % (test_filter,)
+
+
+def RepeatFlag(n):
+  return '--gtest_repeat=%s' % (n,)
+
+
+def ShuffleFlag():
+  return '--gtest_shuffle'
+
+
+def RandomSeedFlag(n):
+  return '--gtest_random_seed=%s' % (n,)
+
+
+def RunAndReturnOutput(extra_env, args):
+  """Runs the test program and returns its output."""
+
+  environ_copy = os.environ.copy()
+  environ_copy.update(extra_env)
+
+  return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
+
+
+def GetTestsForAllIterations(extra_env, args):
+  """Runs the test program and returns a list of test lists.
+
+  Args:
+    extra_env: a map from environment variables to their values
+    args: command line flags to pass to googletest-shuffle-test_
+
+  Returns:
+    A list where the i-th element is the list of tests run in the i-th
+    test iteration.
+  """
+
+  test_iterations = []
+  for line in RunAndReturnOutput(extra_env, args).split('\n'):
+    if line.startswith('----'):
+      tests = []
+      test_iterations.append(tests)
+    elif line.strip():
+      tests.append(line.strip())  # 'TestCaseName.TestName'
+
+  return test_iterations
+
+
+def GetTestCases(tests):
+  """Returns a list of test cases in the given full test names.
+
+  Args:
+    tests: a list of full test names
+
+  Returns:
+    A list of test cases from 'tests', in their original order.
+    Consecutive duplicates are removed.
+  """
+
+  test_cases = []
+  for test in tests:
+    test_case = test.split('.')[0]
+    if not test_case in test_cases:
+      test_cases.append(test_case)
+
+  return test_cases
+
+
+def CalculateTestLists():
+  """Calculates the list of tests run under different flags."""
+
+  if not ALL_TESTS:
+    ALL_TESTS.extend(
+        GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0]
+    )
+
+  if not ACTIVE_TESTS:
+    ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
+
+  if not FILTERED_TESTS:
+    FILTERED_TESTS.extend(
+        GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0]
+    )
+
+  if not SHARDED_TESTS:
+    SHARDED_TESTS.extend(
+        GetTestsForAllIterations(
+            {TOTAL_SHARDS_ENV_VAR: '3', SHARD_INDEX_ENV_VAR: '1'}, []
+        )[0]
+    )
+
+  if not SHUFFLED_ALL_TESTS:
+    SHUFFLED_ALL_TESTS.extend(
+        GetTestsForAllIterations(
+            {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)]
+        )[0]
+    )
+
+  if not SHUFFLED_ACTIVE_TESTS:
+    SHUFFLED_ACTIVE_TESTS.extend(
+        GetTestsForAllIterations({}, [ShuffleFlag(), RandomSeedFlag(1)])[0]
+    )
+
+  if not SHUFFLED_FILTERED_TESTS:
+    SHUFFLED_FILTERED_TESTS.extend(
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)]
+        )[0]
+    )
+
+  if not SHUFFLED_SHARDED_TESTS:
+    SHUFFLED_SHARDED_TESTS.extend(
+        GetTestsForAllIterations(
+            {TOTAL_SHARDS_ENV_VAR: '3', SHARD_INDEX_ENV_VAR: '1'},
+            [ShuffleFlag(), RandomSeedFlag(1)],
+        )[0]
+    )
+
+
+class GTestShuffleUnitTest(gtest_test_utils.TestCase):
+  """Tests test shuffling."""
+
+  def setUp(self):
+    CalculateTestLists()
+
+  def testShufflePreservesNumberOfTests(self):
+    self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
+    self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
+    self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
+    self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
+
+  def testShuffleChangesTestOrder(self):
+    self.assertTrue(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
+    self.assertTrue(
+        SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS
+    )
+    self.assertTrue(
+        SHUFFLED_FILTERED_TESTS != FILTERED_TESTS, SHUFFLED_FILTERED_TESTS
+    )
+    self.assertTrue(
+        SHUFFLED_SHARDED_TESTS != SHARDED_TESTS, SHUFFLED_SHARDED_TESTS
+    )
+
+  def testShuffleChangesTestCaseOrder(self):
+    self.assertTrue(
+        GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
+        GetTestCases(SHUFFLED_ALL_TESTS),
+    )
+    self.assertTrue(
+        GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
+        GetTestCases(SHUFFLED_ACTIVE_TESTS),
+    )
+    self.assertTrue(
+        GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
+        GetTestCases(SHUFFLED_FILTERED_TESTS),
+    )
+    self.assertTrue(
+        GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
+        GetTestCases(SHUFFLED_SHARDED_TESTS),
+    )
+
+  def testShuffleDoesNotRepeatTest(self):
+    for test in SHUFFLED_ALL_TESTS:
+      self.assertEqual(
+          1,
+          SHUFFLED_ALL_TESTS.count(test),
+          '%s appears more than once' % (test,),
+      )
+    for test in SHUFFLED_ACTIVE_TESTS:
+      self.assertEqual(
+          1,
+          SHUFFLED_ACTIVE_TESTS.count(test),
+          '%s appears more than once' % (test,),
+      )
+    for test in SHUFFLED_FILTERED_TESTS:
+      self.assertEqual(
+          1,
+          SHUFFLED_FILTERED_TESTS.count(test),
+          '%s appears more than once' % (test,),
+      )
+    for test in SHUFFLED_SHARDED_TESTS:
+      self.assertEqual(
+          1,
+          SHUFFLED_SHARDED_TESTS.count(test),
+          '%s appears more than once' % (test,),
+      )
+
+  def testShuffleDoesNotCreateNewTest(self):
+    for test in SHUFFLED_ALL_TESTS:
+      self.assertTrue(test in ALL_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_ACTIVE_TESTS:
+      self.assertTrue(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_FILTERED_TESTS:
+      self.assertTrue(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_SHARDED_TESTS:
+      self.assertTrue(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
+
+  def testShuffleIncludesAllTests(self):
+    for test in ALL_TESTS:
+      self.assertTrue(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
+    for test in ACTIVE_TESTS:
+      self.assertTrue(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
+    for test in FILTERED_TESTS:
+      self.assertTrue(
+          test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,)
+      )
+    for test in SHARDED_TESTS:
+      self.assertTrue(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
+
+  def testShuffleLeavesDeathTestsAtFront(self):
+    non_death_test_found = False
+    for test in SHUFFLED_ACTIVE_TESTS:
+      if 'DeathTest.' in test:
+        self.assertTrue(
+            not non_death_test_found,
+            '%s appears after a non-death test' % (test,),
+        )
+      else:
+        non_death_test_found = True
+
+  def _VerifyTestCasesDoNotInterleave(self, tests):
+    test_cases = []
+    for test in tests:
+      [test_case, _] = test.split('.')
+      if test_cases and test_cases[-1] != test_case:
+        test_cases.append(test_case)
+        self.assertEqual(
+            1,
+            test_cases.count(test_case),
+            'Test case %s is not grouped together in %s' % (test_case, tests),
+        )
+
+  def testShuffleDoesNotInterleaveTestCases(self):
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
+
+  def testShuffleRestoresOrderAfterEachIteration(self):
+    # Get the test lists in all 3 iterations, using random seed 1, 2,
+    # and 3 respectively.  Google Test picks a different seed in each
+    # iteration, and this test depends on the current implementation
+    # picking successive numbers.  This dependency is not ideal, but
+    # makes the test much easier to write.
+    # pylint: disable-next=unbalanced-tuple-unpacking
+    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]
+        )
+    )
+
+    # Make sure running the tests with random seed 1 gets the same
+    # order as in iteration 1 above.
+    tests_with_seed1 = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1)]
+    )[0]
+    self.assertEqual(tests_in_iteration1, tests_with_seed1)
+
+    # Make sure running the tests with random seed 2 gets the same
+    # order as in iteration 2 above.  Success means that Google Test
+    # correctly restores the test order before re-shuffling at the
+    # beginning of iteration 2.
+    tests_with_seed2 = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(2)]
+    )[0]
+    self.assertEqual(tests_in_iteration2, tests_with_seed2)
+
+    # Make sure running the tests with random seed 3 gets the same
+    # order as in iteration 3 above.  Success means that Google Test
+    # correctly restores the test order before re-shuffling at the
+    # beginning of iteration 3.
+    tests_with_seed3 = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(3)]
+    )[0]
+    self.assertEqual(tests_in_iteration3, tests_with_seed3)
+
+  def testShuffleGeneratesNewOrderInEachIteration(self):
+    # pylint: disable-next=unbalanced-tuple-unpacking
+    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]
+        )
+    )
+
+    self.assertTrue(
+        tests_in_iteration1 != tests_in_iteration2, tests_in_iteration1
+    )
+    self.assertTrue(
+        tests_in_iteration1 != tests_in_iteration3, tests_in_iteration1
+    )
+    self.assertTrue(
+        tests_in_iteration2 != tests_in_iteration3, tests_in_iteration2
+    )
+
+  def testShuffleShardedTestsPreservesPartition(self):
+    # If we run M tests on N shards, the same M tests should be run in
+    # total, regardless of the random seeds used by the shards.
+    tests1 = GetTestsForAllIterations(
+        {TOTAL_SHARDS_ENV_VAR: '3', SHARD_INDEX_ENV_VAR: '0'},
+        [ShuffleFlag(), RandomSeedFlag(1)],
+    )[0]
+    tests2 = GetTestsForAllIterations(
+        {TOTAL_SHARDS_ENV_VAR: '3', SHARD_INDEX_ENV_VAR: '1'},
+        [ShuffleFlag(), RandomSeedFlag(20)],
+    )[0]
+    tests3 = GetTestsForAllIterations(
+        {TOTAL_SHARDS_ENV_VAR: '3', SHARD_INDEX_ENV_VAR: '2'},
+        [ShuffleFlag(), RandomSeedFlag(25)],
+    )[0]
+    sorted_sharded_tests = tests1 + tests2 + tests3
+    sorted_sharded_tests.sort()
+    sorted_active_tests = []
+    sorted_active_tests.extend(ACTIVE_TESTS)
+    sorted_active_tests.sort()
+    self.assertEqual(sorted_active_tests, sorted_sharded_tests)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-shuffle-test_.cc b/3rd-party/googletest/googletest/test/googletest-shuffle-test_.cc
new file mode 100644
index 0000000..b570c48
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-shuffle-test_.cc
@@ -0,0 +1,99 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Verifies that test shuffling works.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::UnitTest;
+
+// The test methods are empty, as the sole purpose of this program is
+// to print the test names before/after shuffling.
+
+class A : public Test {};
+TEST_F(A, A) {}
+TEST_F(A, B) {}
+
+TEST(ADeathTest, A) {}
+TEST(ADeathTest, B) {}
+TEST(ADeathTest, C) {}
+
+TEST(B, A) {}
+TEST(B, B) {}
+TEST(B, C) {}
+TEST(B, DISABLED_D) {}
+TEST(B, DISABLED_E) {}
+
+TEST(BDeathTest, A) {}
+TEST(BDeathTest, B) {}
+
+TEST(C, A) {}
+TEST(C, B) {}
+TEST(C, C) {}
+TEST(C, DISABLED_D) {}
+
+TEST(CDeathTest, A) {}
+
+TEST(DISABLED_D, A) {}
+TEST(DISABLED_D, DISABLED_B) {}
+
+// This printer prints the full test names only, starting each test
+// iteration with a "----" marker.
+class TestNamePrinter : public EmptyTestEventListener {
+ public:
+  void OnTestIterationStart(const UnitTest& /* unit_test */,
+                            int /* iteration */) override {
+    printf("----\n");
+  }
+
+  void OnTestStart(const TestInfo& test_info) override {
+    printf("%s.%s\n", test_info.test_suite_name(), test_info.name());
+  }
+};
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  // Replaces the default printer with TestNamePrinter, which prints
+  // the test name only.
+  TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new TestNamePrinter);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-test-part-test.cc b/3rd-party/googletest/googletest/test/googletest-test-part-test.cc
new file mode 100644
index 0000000..076e5be
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-test-part-test.cc
@@ -0,0 +1,220 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest.h"
+
+using testing::Message;
+using testing::Test;
+using testing::TestPartResult;
+using testing::TestPartResultArray;
+
+namespace {
+
+// Tests the TestPartResult class.
+
+// The test fixture for testing TestPartResult.
+class TestPartResultTest : public Test {
+ protected:
+  TestPartResultTest()
+      : r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"),
+        r2_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure!"),
+        r3_(TestPartResult::kFatalFailure, nullptr, -1, "Failure!"),
+        r4_(TestPartResult::kSkip, "foo/bar.cc", 2, "Skipped!") {}
+
+  TestPartResult r1_, r2_, r3_, r4_;
+};
+
+TEST_F(TestPartResultTest, ConstructorWorks) {
+  Message message;
+  message << "something is terribly wrong";
+  message << static_cast<const char*>(testing::internal::kStackTraceMarker);
+  message << "some unimportant stack trace";
+
+  const TestPartResult result(TestPartResult::kNonFatalFailure, "some_file.cc",
+                              42, message.GetString().c_str());
+
+  EXPECT_EQ(TestPartResult::kNonFatalFailure, result.type());
+  EXPECT_STREQ("some_file.cc", result.file_name());
+  EXPECT_EQ(42, result.line_number());
+  EXPECT_STREQ(message.GetString().c_str(), result.message());
+  EXPECT_STREQ("something is terribly wrong", result.summary());
+}
+
+TEST_F(TestPartResultTest, ResultAccessorsWork) {
+  const TestPartResult success(TestPartResult::kSuccess, "file.cc", 42,
+                               "message");
+  EXPECT_TRUE(success.passed());
+  EXPECT_FALSE(success.failed());
+  EXPECT_FALSE(success.nonfatally_failed());
+  EXPECT_FALSE(success.fatally_failed());
+  EXPECT_FALSE(success.skipped());
+
+  const TestPartResult nonfatal_failure(TestPartResult::kNonFatalFailure,
+                                        "file.cc", 42, "message");
+  EXPECT_FALSE(nonfatal_failure.passed());
+  EXPECT_TRUE(nonfatal_failure.failed());
+  EXPECT_TRUE(nonfatal_failure.nonfatally_failed());
+  EXPECT_FALSE(nonfatal_failure.fatally_failed());
+  EXPECT_FALSE(nonfatal_failure.skipped());
+
+  const TestPartResult fatal_failure(TestPartResult::kFatalFailure, "file.cc",
+                                     42, "message");
+  EXPECT_FALSE(fatal_failure.passed());
+  EXPECT_TRUE(fatal_failure.failed());
+  EXPECT_FALSE(fatal_failure.nonfatally_failed());
+  EXPECT_TRUE(fatal_failure.fatally_failed());
+  EXPECT_FALSE(fatal_failure.skipped());
+
+  const TestPartResult skip(TestPartResult::kSkip, "file.cc", 42, "message");
+  EXPECT_FALSE(skip.passed());
+  EXPECT_FALSE(skip.failed());
+  EXPECT_FALSE(skip.nonfatally_failed());
+  EXPECT_FALSE(skip.fatally_failed());
+  EXPECT_TRUE(skip.skipped());
+}
+
+// Tests TestPartResult::type().
+TEST_F(TestPartResultTest, type) {
+  EXPECT_EQ(TestPartResult::kSuccess, r1_.type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure, r2_.type());
+  EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type());
+  EXPECT_EQ(TestPartResult::kSkip, r4_.type());
+}
+
+// Tests TestPartResult::file_name().
+TEST_F(TestPartResultTest, file_name) {
+  EXPECT_STREQ("foo/bar.cc", r1_.file_name());
+  EXPECT_STREQ(nullptr, r3_.file_name());
+  EXPECT_STREQ("foo/bar.cc", r4_.file_name());
+}
+
+// Tests TestPartResult::line_number().
+TEST_F(TestPartResultTest, line_number) {
+  EXPECT_EQ(10, r1_.line_number());
+  EXPECT_EQ(-1, r2_.line_number());
+  EXPECT_EQ(2, r4_.line_number());
+}
+
+// Tests TestPartResult::message().
+TEST_F(TestPartResultTest, message) {
+  EXPECT_STREQ("Success!", r1_.message());
+  EXPECT_STREQ("Skipped!", r4_.message());
+}
+
+// Tests TestPartResult::passed().
+TEST_F(TestPartResultTest, Passed) {
+  EXPECT_TRUE(r1_.passed());
+  EXPECT_FALSE(r2_.passed());
+  EXPECT_FALSE(r3_.passed());
+  EXPECT_FALSE(r4_.passed());
+}
+
+// Tests TestPartResult::failed().
+TEST_F(TestPartResultTest, Failed) {
+  EXPECT_FALSE(r1_.failed());
+  EXPECT_TRUE(r2_.failed());
+  EXPECT_TRUE(r3_.failed());
+  EXPECT_FALSE(r4_.failed());
+}
+
+// Tests TestPartResult::failed().
+TEST_F(TestPartResultTest, Skipped) {
+  EXPECT_FALSE(r1_.skipped());
+  EXPECT_FALSE(r2_.skipped());
+  EXPECT_FALSE(r3_.skipped());
+  EXPECT_TRUE(r4_.skipped());
+}
+
+// Tests TestPartResult::fatally_failed().
+TEST_F(TestPartResultTest, FatallyFailed) {
+  EXPECT_FALSE(r1_.fatally_failed());
+  EXPECT_FALSE(r2_.fatally_failed());
+  EXPECT_TRUE(r3_.fatally_failed());
+  EXPECT_FALSE(r4_.fatally_failed());
+}
+
+// Tests TestPartResult::nonfatally_failed().
+TEST_F(TestPartResultTest, NonfatallyFailed) {
+  EXPECT_FALSE(r1_.nonfatally_failed());
+  EXPECT_TRUE(r2_.nonfatally_failed());
+  EXPECT_FALSE(r3_.nonfatally_failed());
+  EXPECT_FALSE(r4_.nonfatally_failed());
+}
+
+// Tests the TestPartResultArray class.
+
+class TestPartResultArrayTest : public Test {
+ protected:
+  TestPartResultArrayTest()
+      : r1_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure 1"),
+        r2_(TestPartResult::kFatalFailure, "foo/bar.cc", -1, "Failure 2") {}
+
+  const TestPartResult r1_, r2_;
+};
+
+// Tests that TestPartResultArray initially has size 0.
+TEST_F(TestPartResultArrayTest, InitialSizeIsZero) {
+  TestPartResultArray results;
+  EXPECT_EQ(0, results.size());
+}
+
+// Tests that TestPartResultArray contains the given TestPartResult
+// after one Append() operation.
+TEST_F(TestPartResultArrayTest, ContainsGivenResultAfterAppend) {
+  TestPartResultArray results;
+  results.Append(r1_);
+  EXPECT_EQ(1, results.size());
+  EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
+}
+
+// Tests that TestPartResultArray contains the given TestPartResults
+// after two Append() operations.
+TEST_F(TestPartResultArrayTest, ContainsGivenResultsAfterTwoAppends) {
+  TestPartResultArray results;
+  results.Append(r1_);
+  results.Append(r2_);
+  EXPECT_EQ(2, results.size());
+  EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
+  EXPECT_STREQ("Failure 2", results.GetTestPartResult(1).message());
+}
+
+typedef TestPartResultArrayTest TestPartResultArrayDeathTest;
+
+// Tests that the program dies when GetTestPartResult() is called with
+// an invalid index.
+TEST_F(TestPartResultArrayDeathTest, DiesWhenIndexIsOutOfBound) {
+  TestPartResultArray results;
+  results.Append(r1_);
+
+  EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(-1), "");
+  EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(1), "");
+}
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/test/googletest-throw-on-failure-test.py b/3rd-party/googletest/googletest/test/googletest-throw-on-failure-test.py
new file mode 100755
index 0000000..106b004
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-throw-on-failure-test.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests Google Test's throw-on-failure mode with exceptions disabled.
+
+This script invokes googletest-throw-on-failure-test_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+import os
+from googletest.test import gtest_test_utils
+
+
+# Constants.
+
+# The command line flag for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE = 'gtest_throw_on_failure'
+
+# Path to the googletest-throw-on-failure-test_ program, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'googletest-throw-on-failure-test_'
+)
+
+
+# Utilities.
+
+
+def SetEnvVar(env_var, value):
+  """Sets an environment variable.
+
+  Sets an environment variable to a given value; unsets it when the
+  given value is None.
+
+  Args:
+    env_var: environment variable.
+    value: value to set.
+  """
+
+  env_var = env_var.upper()
+  if value is not None:
+    os.environ[env_var] = value
+  elif env_var in os.environ:
+    del os.environ[env_var]
+
+
+def Run(command):
+  """Runs a command; returns True/False if its exit code is/isn't 0."""
+
+  print('Running "%s". . .' % ' '.join(command))
+  p = gtest_test_utils.Subprocess(command)
+  return p.exited and p.exit_code == 0
+
+
+# The tests.
+class ThrowOnFailureTest(gtest_test_utils.TestCase):
+  """Tests the throw-on-failure mode."""
+
+  def RunAndVerify(self, env_var_value, flag_value, should_fail):
+    """Runs googletest-throw-on-failure-test_ and verifies its behavior.
+
+    Runs googletest-throw-on-failure-test_ and verifies that it does
+    (or does not) exit with a non-zero code.
+
+    Args:
+      env_var_value:    value of the GTEST_BREAK_ON_FAILURE environment
+        variable; None if the variable should be unset.
+      flag_value:       value of the --gtest_break_on_failure flag; None if the
+        flag should not be present.
+      should_fail:      True if and only if the program is expected to fail.
+    """
+
+    SetEnvVar(THROW_ON_FAILURE, env_var_value)
+
+    if env_var_value is None:
+      env_var_value_msg = ' is not set'
+    else:
+      env_var_value_msg = '=' + env_var_value
+
+    if flag_value is None:
+      flag = ''
+    elif flag_value == '0':
+      flag = '--%s=0' % THROW_ON_FAILURE
+    else:
+      flag = '--%s' % THROW_ON_FAILURE
+
+    command = [EXE_PATH]
+    if flag:
+      command.append(flag)
+
+    if should_fail:
+      should_or_not = 'should'
+    else:
+      should_or_not = 'should not'
+
+    failed = not Run(command)
+
+    SetEnvVar(THROW_ON_FAILURE, None)
+
+    msg = (
+        'when %s%s, an assertion failure in "%s" %s cause a non-zero exit code.'
+        % (
+            THROW_ON_FAILURE,
+            env_var_value_msg,
+            ' '.join(command),
+            should_or_not,
+        )
+    )
+    self.assertTrue(failed == should_fail, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(env_var_value=None, flag_value=None, should_fail=False)
+
+  def testThrowOnFailureEnvVar(self):
+    """Tests using the GTEST_THROW_ON_FAILURE environment variable."""
+
+    self.RunAndVerify(env_var_value='0', flag_value=None, should_fail=False)
+    self.RunAndVerify(env_var_value='1', flag_value=None, should_fail=True)
+
+  def testThrowOnFailureFlag(self):
+    """Tests using the --gtest_throw_on_failure flag."""
+
+    self.RunAndVerify(env_var_value=None, flag_value='0', should_fail=False)
+    self.RunAndVerify(env_var_value=None, flag_value='1', should_fail=True)
+
+  def testThrowOnFailureFlagOverridesEnvVar(self):
+    """Tests that --gtest_throw_on_failure overrides GTEST_THROW_ON_FAILURE."""
+
+    self.RunAndVerify(env_var_value='0', flag_value='0', should_fail=False)
+    self.RunAndVerify(env_var_value='0', flag_value='1', should_fail=True)
+    self.RunAndVerify(env_var_value='1', flag_value='0', should_fail=False)
+    self.RunAndVerify(env_var_value='1', flag_value='1', should_fail=True)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-throw-on-failure-test_.cc b/3rd-party/googletest/googletest/test/googletest-throw-on-failure-test_.cc
new file mode 100644
index 0000000..3b81a5a
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-throw-on-failure-test_.cc
@@ -0,0 +1,71 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests Google Test's throw-on-failure mode with exceptions disabled.
+//
+// This program must be compiled with exceptions disabled.  It will be
+// invoked by googletest-throw-on-failure-test.py, and is expected to exit
+// with non-zero in the throw-on-failure mode or 0 otherwise.
+
+#include <stdio.h>   // for fflush, fprintf, NULL, etc.
+#include <stdlib.h>  // for exit
+
+#include <exception>  // for set_terminate
+
+#include "gtest/gtest.h"
+
+// This terminate handler aborts the program using exit() rather than abort().
+// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
+// ones.
+void TerminateHandler() {
+  fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
+  fflush(nullptr);
+  exit(1);
+}
+
+int main(int argc, char** argv) {
+#if GTEST_HAS_EXCEPTIONS
+  std::set_terminate(&TerminateHandler);
+#endif
+  testing::InitGoogleTest(&argc, argv);
+
+  // We want to ensure that people can use Google Test assertions in
+  // other testing frameworks, as long as they initialize Google Test
+  // properly and set the throw-on-failure mode.  Therefore, we don't
+  // use Google Test's constructs for defining and running tests
+  // (e.g. TEST and RUN_ALL_TESTS) here.
+
+  // In the throw-on-failure mode with exceptions disabled, this
+  // assertion will cause the program to exit with a non-zero code.
+  EXPECT_EQ(2, 3);
+
+  // When not in the throw-on-failure mode, the control will reach
+  // here.
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/googletest-uninitialized-test.py b/3rd-party/googletest/googletest/test/googletest-uninitialized-test.py
new file mode 100755
index 0000000..e5af7c8
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-uninitialized-test.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test warns the user when not initialized properly."""
+
+from googletest.test import gtest_test_utils
+
+COMMAND = gtest_test_utils.GetTestExecutablePath(
+    'googletest-uninitialized-test_'
+)
+
+
+def Assert(condition):
+  if not condition:
+    raise AssertionError
+
+
+def AssertEq(expected, actual):
+  if expected != actual:
+    print('Expected: %s' % (expected,))
+    print('  Actual: %s' % (actual,))
+    raise AssertionError
+
+
+def TestExitCodeAndOutput(command):
+  """Runs the given command and verifies its exit code and output."""
+
+  # Verifies that 'command' exits with code 1.
+  p = gtest_test_utils.Subprocess(command)
+  if p.exited and p.exit_code == 0:
+    Assert('IMPORTANT NOTICE' in p.output)
+  Assert('InitGoogleTest' in p.output)
+
+
+class GTestUninitializedTest(gtest_test_utils.TestCase):
+
+  def testExitCodeAndOutput(self):
+    TestExitCodeAndOutput(COMMAND)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/googletest-uninitialized-test_.cc b/3rd-party/googletest/googletest/test/googletest-uninitialized-test_.cc
new file mode 100644
index 0000000..88b61fc
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/googletest-uninitialized-test_.cc
@@ -0,0 +1,39 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest.h"
+
+TEST(DummyTest, Dummy) {
+  // This test doesn't verify anything.  We just need it to create a
+  // realistic stage for testing the behavior of Google Test when
+  // RUN_ALL_TESTS() is called without
+  // testing::InitGoogleTest() being called first.
+}
+
+int main() { return RUN_ALL_TESTS(); }
diff --git a/3rd-party/googletest/googletest/test/gtest-typed-test2_test.cc b/3rd-party/googletest/googletest/test/gtest-typed-test2_test.cc
new file mode 100644
index 0000000..f2eae12
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest-typed-test2_test.cc
@@ -0,0 +1,39 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "test/gtest-typed-test_test.h"
+
+// Tests that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
+INSTANTIATE_TYPED_TEST_SUITE_P(Vector, ContainerTest,
+                               testing::Types<std::vector<int> >);
diff --git a/3rd-party/googletest/googletest/test/gtest-typed-test_test.cc b/3rd-party/googletest/googletest/test/gtest-typed-test_test.cc
new file mode 100644
index 0000000..0cc8b21
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest-typed-test_test.cc
@@ -0,0 +1,423 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "test/gtest-typed-test_test.h"
+
+#include <set>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127 /* conditional expression is constant */)
+
+using testing::Test;
+
+// Used for testing that SetUpTestSuite()/TearDownTestSuite(), fixture
+// ctor/dtor, and SetUp()/TearDown() work correctly in typed tests and
+// type-parameterized test.
+template <typename T>
+class CommonTest : public Test {
+  // For some technical reason, SetUpTestSuite() and TearDownTestSuite()
+  // must be public.
+ public:
+  static void SetUpTestSuite() { shared_ = new T(5); }
+
+  static void TearDownTestSuite() {
+    delete shared_;
+    shared_ = nullptr;
+  }
+
+  // This 'protected:' is optional.  There's no harm in making all
+  // members of this fixture class template public.
+ protected:
+  // We used to use std::list here, but switched to std::vector since
+  // MSVC's <list> doesn't compile cleanly with /W4.
+  typedef std::vector<T> Vector;
+  typedef std::set<int> IntSet;
+
+  CommonTest() : value_(1) {}
+
+  ~CommonTest() override { EXPECT_EQ(3, value_); }
+
+  void SetUp() override {
+    EXPECT_EQ(1, value_);
+    value_++;
+  }
+
+  void TearDown() override {
+    EXPECT_EQ(2, value_);
+    value_++;
+  }
+
+  T value_;
+  static T* shared_;
+};
+
+template <typename T>
+T* CommonTest<T>::shared_ = nullptr;
+
+using testing::Types;
+
+// Tests that SetUpTestSuite()/TearDownTestSuite(), fixture ctor/dtor,
+// and SetUp()/TearDown() work correctly in typed tests
+
+typedef Types<char, int> TwoTypes;
+TYPED_TEST_SUITE(CommonTest, TwoTypes);
+
+TYPED_TEST(CommonTest, ValuesAreCorrect) {
+  // Static members of the fixture class template can be visited via
+  // the TestFixture:: prefix.
+  EXPECT_EQ(5, *TestFixture::shared_);
+
+  // Typedefs in the fixture class template can be visited via the
+  // "typename TestFixture::" prefix.
+  typename TestFixture::Vector empty;
+  EXPECT_EQ(0U, empty.size());
+
+  typename TestFixture::IntSet empty2;
+  EXPECT_EQ(0U, empty2.size());
+
+  // Non-static members of the fixture class must be visited via
+  // 'this', as required by C++ for class templates.
+  EXPECT_EQ(2, this->value_);
+}
+
+// The second test makes sure shared_ is not deleted after the first
+// test.
+TYPED_TEST(CommonTest, ValuesAreStillCorrect) {
+  // Static members of the fixture class template can also be visited
+  // via 'this'.
+  ASSERT_TRUE(this->shared_ != nullptr);
+  EXPECT_EQ(5, *this->shared_);
+
+  // TypeParam can be used to refer to the type parameter.
+  EXPECT_EQ(static_cast<TypeParam>(2), this->value_);
+}
+
+// Tests that multiple TYPED_TEST_SUITE's can be defined in the same
+// translation unit.
+
+template <typename T>
+class TypedTest1 : public Test {};
+
+// Verifies that the second argument of TYPED_TEST_SUITE can be a
+// single type.
+TYPED_TEST_SUITE(TypedTest1, int);
+TYPED_TEST(TypedTest1, A) {}
+
+template <typename T>
+class TypedTest2 : public Test {};
+
+// Verifies that the second argument of TYPED_TEST_SUITE can be a
+// Types<...> type list.
+TYPED_TEST_SUITE(TypedTest2, Types<int>);
+
+// This also verifies that tests from different typed test cases can
+// share the same name.
+TYPED_TEST(TypedTest2, A) {}
+
+// Tests that a typed test case can be defined in a namespace.
+
+namespace library1 {
+
+template <typename T>
+class NumericTest : public Test {};
+
+typedef Types<int, long> NumericTypes;
+TYPED_TEST_SUITE(NumericTest, NumericTypes);
+
+TYPED_TEST(NumericTest, DefaultIsZero) { EXPECT_EQ(0, TypeParam()); }
+
+}  // namespace library1
+
+// Tests that custom names work.
+template <typename T>
+class TypedTestWithNames : public Test {};
+
+class TypedTestNames {
+ public:
+  template <typename T>
+  static std::string GetName(int i) {
+    if (std::is_same<T, char>::value) {
+      return std::string("char") + ::testing::PrintToString(i);
+    }
+    if (std::is_same<T, int>::value) {
+      return std::string("int") + ::testing::PrintToString(i);
+    }
+  }
+};
+
+TYPED_TEST_SUITE(TypedTestWithNames, TwoTypes, TypedTestNames);
+
+TYPED_TEST(TypedTestWithNames, TestSuiteName) {
+  if (std::is_same<TypeParam, char>::value) {
+    EXPECT_STREQ(::testing::UnitTest::GetInstance()
+                     ->current_test_info()
+                     ->test_suite_name(),
+                 "TypedTestWithNames/char0");
+  }
+  if (std::is_same<TypeParam, int>::value) {
+    EXPECT_STREQ(::testing::UnitTest::GetInstance()
+                     ->current_test_info()
+                     ->test_suite_name(),
+                 "TypedTestWithNames/int1");
+  }
+}
+
+using testing::Types;
+using testing::internal::TypedTestSuitePState;
+
+// Tests TypedTestSuitePState.
+
+class TypedTestSuitePStateTest : public Test {
+ protected:
+  void SetUp() override {
+    state_.AddTestName("foo.cc", 0, "FooTest", "A");
+    state_.AddTestName("foo.cc", 0, "FooTest", "B");
+    state_.AddTestName("foo.cc", 0, "FooTest", "C");
+  }
+
+  TypedTestSuitePState state_;
+};
+
+TEST_F(TypedTestSuitePStateTest, SucceedsForMatchingList) {
+  const char* tests = "A, B, C";
+  EXPECT_EQ(tests,
+            state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, tests));
+}
+
+// Makes sure that the order of the tests and spaces around the names
+// don't matter.
+TEST_F(TypedTestSuitePStateTest, IgnoresOrderAndSpaces) {
+  const char* tests = "A,C,   B";
+  EXPECT_EQ(tests,
+            state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, tests));
+}
+
+using TypedTestSuitePStateDeathTest = TypedTestSuitePStateTest;
+
+TEST_F(TypedTestSuitePStateDeathTest, DetectsDuplicates) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, A, C"),
+      "foo\\.cc.1.?: Test A is listed more than once\\.");
+}
+
+TEST_F(TypedTestSuitePStateDeathTest, DetectsExtraTest) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, C, D"),
+      "foo\\.cc.1.?: No test named D can be found in this test suite\\.");
+}
+
+TEST_F(TypedTestSuitePStateDeathTest, DetectsMissedTest) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, C"),
+      "foo\\.cc.1.?: You forgot to list test B\\.");
+}
+
+// Tests that defining a test for a parameterized test case generates
+// a run-time error if the test case has been registered.
+TEST_F(TypedTestSuitePStateDeathTest, DetectsTestAfterRegistration) {
+  state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, C");
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.AddTestName("foo.cc", 2, "FooTest", "D"),
+      "foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_SUITE_P"
+      "\\(FooTest, \\.\\.\\.\\)\\.");
+}
+
+// Tests that SetUpTestSuite()/TearDownTestSuite(), fixture ctor/dtor,
+// and SetUp()/TearDown() work correctly in type-parameterized tests.
+
+template <typename T>
+class DerivedTest : public CommonTest<T> {};
+
+TYPED_TEST_SUITE_P(DerivedTest);
+
+TYPED_TEST_P(DerivedTest, ValuesAreCorrect) {
+  // Static members of the fixture class template can be visited via
+  // the TestFixture:: prefix.
+  EXPECT_EQ(5, *TestFixture::shared_);
+
+  // Non-static members of the fixture class must be visited via
+  // 'this', as required by C++ for class templates.
+  EXPECT_EQ(2, this->value_);
+}
+
+// The second test makes sure shared_ is not deleted after the first
+// test.
+TYPED_TEST_P(DerivedTest, ValuesAreStillCorrect) {
+  // Static members of the fixture class template can also be visited
+  // via 'this'.
+  ASSERT_TRUE(this->shared_ != nullptr);
+  EXPECT_EQ(5, *this->shared_);
+  EXPECT_EQ(2, this->value_);
+}
+
+REGISTER_TYPED_TEST_SUITE_P(DerivedTest, ValuesAreCorrect,
+                            ValuesAreStillCorrect);
+
+typedef Types<short, long> MyTwoTypes;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, DerivedTest, MyTwoTypes);
+
+// Tests that custom names work with type parametrized tests. We reuse the
+// TwoTypes from above here.
+template <typename T>
+class TypeParametrizedTestWithNames : public Test {};
+
+TYPED_TEST_SUITE_P(TypeParametrizedTestWithNames);
+
+TYPED_TEST_P(TypeParametrizedTestWithNames, TestSuiteName) {
+  if (std::is_same<TypeParam, char>::value) {
+    EXPECT_STREQ(::testing::UnitTest::GetInstance()
+                     ->current_test_info()
+                     ->test_suite_name(),
+                 "CustomName/TypeParametrizedTestWithNames/parChar0");
+  }
+  if (std::is_same<TypeParam, int>::value) {
+    EXPECT_STREQ(::testing::UnitTest::GetInstance()
+                     ->current_test_info()
+                     ->test_suite_name(),
+                 "CustomName/TypeParametrizedTestWithNames/parInt1");
+  }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(TypeParametrizedTestWithNames, TestSuiteName);
+
+class TypeParametrizedTestNames {
+ public:
+  template <typename T>
+  static std::string GetName(int i) {
+    if (std::is_same<T, char>::value) {
+      return std::string("parChar") + ::testing::PrintToString(i);
+    }
+    if (std::is_same<T, int>::value) {
+      return std::string("parInt") + ::testing::PrintToString(i);
+    }
+  }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(CustomName, TypeParametrizedTestWithNames,
+                               TwoTypes, TypeParametrizedTestNames);
+
+// Tests that multiple TYPED_TEST_SUITE_P's can be defined in the same
+// translation unit.
+
+template <typename T>
+class TypedTestP1 : public Test {};
+
+TYPED_TEST_SUITE_P(TypedTestP1);
+
+// For testing that the code between TYPED_TEST_SUITE_P() and
+// TYPED_TEST_P() is not enclosed in a namespace.
+using IntAfterTypedTestSuiteP = int;
+
+TYPED_TEST_P(TypedTestP1, A) {}
+TYPED_TEST_P(TypedTestP1, B) {}
+
+// For testing that the code between TYPED_TEST_P() and
+// REGISTER_TYPED_TEST_SUITE_P() is not enclosed in a namespace.
+using IntBeforeRegisterTypedTestSuiteP = int;
+
+REGISTER_TYPED_TEST_SUITE_P(TypedTestP1, A, B);
+
+template <typename T>
+class TypedTestP2 : public Test {};
+
+TYPED_TEST_SUITE_P(TypedTestP2);
+
+// This also verifies that tests from different type-parameterized
+// test cases can share the same name.
+TYPED_TEST_P(TypedTestP2, A) {}
+
+REGISTER_TYPED_TEST_SUITE_P(TypedTestP2, A);
+
+// Verifies that the code between TYPED_TEST_SUITE_P() and
+// REGISTER_TYPED_TEST_SUITE_P() is not enclosed in a namespace.
+IntAfterTypedTestSuiteP after = 0;
+IntBeforeRegisterTypedTestSuiteP before = 0;
+
+// Verifies that the last argument of INSTANTIATE_TYPED_TEST_SUITE_P()
+// can be either a single type or a Types<...> type list.
+INSTANTIATE_TYPED_TEST_SUITE_P(Int, TypedTestP1, int);
+INSTANTIATE_TYPED_TEST_SUITE_P(Int, TypedTestP2, Types<int>);
+
+// Tests that the same type-parameterized test case can be
+// instantiated more than once in the same translation unit.
+INSTANTIATE_TYPED_TEST_SUITE_P(Double, TypedTestP2, Types<double>);
+
+// Tests that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
+typedef Types<std::vector<double>, std::set<char> > MyContainers;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, ContainerTest, MyContainers);
+
+// Tests that a type-parameterized test case can be defined and
+// instantiated in a namespace.
+
+namespace library2 {
+
+template <typename T>
+class NumericTest : public Test {};
+
+TYPED_TEST_SUITE_P(NumericTest);
+
+TYPED_TEST_P(NumericTest, DefaultIsZero) { EXPECT_EQ(0, TypeParam()); }
+
+TYPED_TEST_P(NumericTest, ZeroIsLessThanOne) {
+  EXPECT_LT(TypeParam(0), TypeParam(1));
+}
+
+REGISTER_TYPED_TEST_SUITE_P(NumericTest, DefaultIsZero, ZeroIsLessThanOne);
+typedef Types<int, double> NumericTypes;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, NumericTest, NumericTypes);
+
+static const char* GetTestName() {
+  return testing::UnitTest::GetInstance()->current_test_info()->name();
+}
+// Test the stripping of space from test names
+template <typename T>
+class TrimmedTest : public Test {};
+TYPED_TEST_SUITE_P(TrimmedTest);
+TYPED_TEST_P(TrimmedTest, Test1) { EXPECT_STREQ("Test1", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test2) { EXPECT_STREQ("Test2", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test3) { EXPECT_STREQ("Test3", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test4) { EXPECT_STREQ("Test4", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test5) { EXPECT_STREQ("Test5", GetTestName()); }
+REGISTER_TYPED_TEST_SUITE_P(TrimmedTest, Test1, Test2, Test3, Test4,
+                            Test5);  // NOLINT
+template <typename T1, typename T2>
+struct MyPair {};
+// Be sure to try a type with a comma in its name just in case it matters.
+typedef Types<int, double, MyPair<int, int> > TrimTypes;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, TrimmedTest, TrimTypes);
+
+}  // namespace library2
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4127
diff --git a/3rd-party/googletest/googletest/test/gtest-typed-test_test.h b/3rd-party/googletest/googletest/test/gtest-typed-test_test.h
new file mode 100644
index 0000000..f3ef0a5
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest-typed-test_test.h
@@ -0,0 +1,57 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLETEST_TEST_GTEST_TYPED_TEST_TEST_H_
+#define GOOGLETEST_TEST_GTEST_TYPED_TEST_TEST_H_
+
+#include "gtest/gtest.h"
+
+using testing::Test;
+
+// For testing that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// ContainerTest will be instantiated in both gtest-typed-test_test.cc
+// and gtest-typed-test2_test.cc.
+
+template <typename T>
+class ContainerTest : public Test {};
+
+TYPED_TEST_SUITE_P(ContainerTest);
+
+TYPED_TEST_P(ContainerTest, CanBeDefaultConstructed) { TypeParam container; }
+
+TYPED_TEST_P(ContainerTest, InitialSizeIsZero) {
+  TypeParam container;
+  EXPECT_EQ(0U, container.size());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(ContainerTest, CanBeDefaultConstructed,
+                            InitialSizeIsZero);
+
+#endif  // GOOGLETEST_TEST_GTEST_TYPED_TEST_TEST_H_
diff --git a/3rd-party/googletest/googletest/test/gtest-unittest-api_test.cc b/3rd-party/googletest/googletest/test/gtest-unittest-api_test.cc
new file mode 100644
index 0000000..2ea6927
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest-unittest-api_test.cc
@@ -0,0 +1,328 @@
+// Copyright 2009 Google Inc.  All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file contains tests verifying correctness of data provided via
+// UnitTest's public methods.
+
+#include <string.h>  // For strcmp.
+
+#include <algorithm>
+
+#include "gtest/gtest.h"
+
+using ::testing::InitGoogleTest;
+
+namespace testing {
+namespace internal {
+
+template <typename T>
+struct LessByName {
+  bool operator()(const T* a, const T* b) {
+    return strcmp(a->name(), b->name()) < 0;
+  }
+};
+
+class UnitTestHelper {
+ public:
+  // Returns the array of pointers to all test suites sorted by the test suite
+  // name.  The caller is responsible for deleting the array.
+  static TestSuite const** GetSortedTestSuites() {
+    UnitTest& unit_test = *UnitTest::GetInstance();
+    auto const** const test_suites = new const TestSuite*[static_cast<size_t>(
+        unit_test.total_test_suite_count())];
+
+    for (int i = 0; i < unit_test.total_test_suite_count(); ++i)
+      test_suites[i] = unit_test.GetTestSuite(i);
+
+    std::sort(test_suites, test_suites + unit_test.total_test_suite_count(),
+              LessByName<TestSuite>());
+    return test_suites;
+  }
+
+  // Returns the test suite by its name.  The caller doesn't own the returned
+  // pointer.
+  static const TestSuite* FindTestSuite(const char* name) {
+    UnitTest& unit_test = *UnitTest::GetInstance();
+    for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+      const TestSuite* test_suite = unit_test.GetTestSuite(i);
+      if (0 == strcmp(test_suite->name(), name)) return test_suite;
+    }
+    return nullptr;
+  }
+
+  // Returns the array of pointers to all tests in a particular test suite
+  // sorted by the test name.  The caller is responsible for deleting the
+  // array.
+  static TestInfo const** GetSortedTests(const TestSuite* test_suite) {
+    TestInfo const** const tests = new const TestInfo*[static_cast<size_t>(
+        test_suite->total_test_count())];
+
+    for (int i = 0; i < test_suite->total_test_count(); ++i)
+      tests[i] = test_suite->GetTestInfo(i);
+
+    std::sort(tests, tests + test_suite->total_test_count(),
+              LessByName<TestInfo>());
+    return tests;
+  }
+};
+
+template <typename T>
+class TestSuiteWithCommentTest : public Test {};
+TYPED_TEST_SUITE(TestSuiteWithCommentTest, Types<int>);
+TYPED_TEST(TestSuiteWithCommentTest, Dummy) {}
+
+const int kTypedTestSuites = 1;
+const int kTypedTests = 1;
+
+// We can only test the accessors that do not change value while tests run.
+// Since tests can be run in any order, the values the accessors that track
+// test execution (such as failed_test_count) can not be predicted.
+TEST(ApiTest, UnitTestImmutableAccessorsWork) {
+  const auto& unit_test = UnitTest::GetInstance();
+
+  ASSERT_EQ(2 + kTypedTestSuites, unit_test->total_test_suite_count());
+  EXPECT_EQ(1 + kTypedTestSuites, unit_test->test_suite_to_run_count());
+  EXPECT_EQ(2, unit_test->disabled_test_count());
+  EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
+  EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());
+
+  const TestSuite** const test_suites = UnitTestHelper::GetSortedTestSuites();
+
+  EXPECT_STREQ("ApiTest", test_suites[0]->name());
+  EXPECT_STREQ("DISABLED_Test", test_suites[1]->name());
+  EXPECT_STREQ("TestSuiteWithCommentTest/0", test_suites[2]->name());
+
+  delete[] test_suites;
+
+  // The following lines initiate actions to verify certain methods in
+  // FinalSuccessChecker::TearDown.
+
+  // Records a test property to verify TestResult::GetTestProperty().
+  RecordProperty("key", "value");
+}
+
+AssertionResult IsNull(const char* str) {
+  if (str != nullptr) {
+    return testing::AssertionFailure() << "argument is " << str;
+  }
+  return AssertionSuccess();
+}
+
+TEST(ApiTest, TestSuiteImmutableAccessorsWork) {
+  const TestSuite* test_suite = UnitTestHelper::FindTestSuite("ApiTest");
+  ASSERT_TRUE(test_suite != nullptr);
+
+  EXPECT_STREQ("ApiTest", test_suite->name());
+  EXPECT_TRUE(IsNull(test_suite->type_param()));
+  EXPECT_TRUE(test_suite->should_run());
+  EXPECT_EQ(1, test_suite->disabled_test_count());
+  EXPECT_EQ(3, test_suite->test_to_run_count());
+  ASSERT_EQ(4, test_suite->total_test_count());
+
+  const TestInfo** tests = UnitTestHelper::GetSortedTests(test_suite);
+
+  EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
+  EXPECT_STREQ("ApiTest", tests[0]->test_suite_name());
+  EXPECT_TRUE(IsNull(tests[0]->value_param()));
+  EXPECT_TRUE(IsNull(tests[0]->type_param()));
+  EXPECT_FALSE(tests[0]->should_run());
+
+  EXPECT_STREQ("TestSuiteDisabledAccessorsWork", tests[1]->name());
+  EXPECT_STREQ("ApiTest", tests[1]->test_suite_name());
+  EXPECT_TRUE(IsNull(tests[1]->value_param()));
+  EXPECT_TRUE(IsNull(tests[1]->type_param()));
+  EXPECT_TRUE(tests[1]->should_run());
+
+  EXPECT_STREQ("TestSuiteImmutableAccessorsWork", tests[2]->name());
+  EXPECT_STREQ("ApiTest", tests[2]->test_suite_name());
+  EXPECT_TRUE(IsNull(tests[2]->value_param()));
+  EXPECT_TRUE(IsNull(tests[2]->type_param()));
+  EXPECT_TRUE(tests[2]->should_run());
+
+  EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
+  EXPECT_STREQ("ApiTest", tests[3]->test_suite_name());
+  EXPECT_TRUE(IsNull(tests[3]->value_param()));
+  EXPECT_TRUE(IsNull(tests[3]->type_param()));
+  EXPECT_TRUE(tests[3]->should_run());
+
+  delete[] tests;
+  tests = nullptr;
+
+  test_suite = UnitTestHelper::FindTestSuite("TestSuiteWithCommentTest/0");
+  ASSERT_TRUE(test_suite != nullptr);
+
+  EXPECT_STREQ("TestSuiteWithCommentTest/0", test_suite->name());
+  EXPECT_STREQ(GetTypeName<Types<int>>().c_str(), test_suite->type_param());
+  EXPECT_TRUE(test_suite->should_run());
+  EXPECT_EQ(0, test_suite->disabled_test_count());
+  EXPECT_EQ(1, test_suite->test_to_run_count());
+  ASSERT_EQ(1, test_suite->total_test_count());
+
+  tests = UnitTestHelper::GetSortedTests(test_suite);
+
+  EXPECT_STREQ("Dummy", tests[0]->name());
+  EXPECT_STREQ("TestSuiteWithCommentTest/0", tests[0]->test_suite_name());
+  EXPECT_TRUE(IsNull(tests[0]->value_param()));
+  EXPECT_STREQ(GetTypeName<Types<int>>().c_str(), tests[0]->type_param());
+  EXPECT_TRUE(tests[0]->should_run());
+
+  delete[] tests;
+}
+
+TEST(ApiTest, TestSuiteDisabledAccessorsWork) {
+  const TestSuite* test_suite = UnitTestHelper::FindTestSuite("DISABLED_Test");
+  ASSERT_TRUE(test_suite != nullptr);
+
+  EXPECT_STREQ("DISABLED_Test", test_suite->name());
+  EXPECT_TRUE(IsNull(test_suite->type_param()));
+  EXPECT_FALSE(test_suite->should_run());
+  EXPECT_EQ(1, test_suite->disabled_test_count());
+  EXPECT_EQ(0, test_suite->test_to_run_count());
+  ASSERT_EQ(1, test_suite->total_test_count());
+
+  const TestInfo* const test_info = test_suite->GetTestInfo(0);
+  EXPECT_STREQ("Dummy2", test_info->name());
+  EXPECT_STREQ("DISABLED_Test", test_info->test_suite_name());
+  EXPECT_TRUE(IsNull(test_info->value_param()));
+  EXPECT_TRUE(IsNull(test_info->type_param()));
+  EXPECT_FALSE(test_info->should_run());
+}
+
+// These two tests are here to provide support for testing
+// test_suite_to_run_count, disabled_test_count, and test_to_run_count.
+TEST(ApiTest, DISABLED_Dummy1) {}
+TEST(DISABLED_Test, Dummy2) {}
+
+class FinalSuccessChecker : public Environment {
+ protected:
+  void TearDown() override {
+    const auto& unit_test = UnitTest::GetInstance();
+
+    EXPECT_EQ(1 + kTypedTestSuites, unit_test->successful_test_suite_count());
+    EXPECT_EQ(3 + kTypedTests, unit_test->successful_test_count());
+    EXPECT_EQ(0, unit_test->failed_test_suite_count());
+    EXPECT_EQ(0, unit_test->failed_test_count());
+    EXPECT_TRUE(unit_test->Passed());
+    EXPECT_FALSE(unit_test->Failed());
+    ASSERT_EQ(2 + kTypedTestSuites, unit_test->total_test_suite_count());
+
+    const TestSuite** const test_suites = UnitTestHelper::GetSortedTestSuites();
+
+    EXPECT_STREQ("ApiTest", test_suites[0]->name());
+    EXPECT_TRUE(IsNull(test_suites[0]->type_param()));
+    EXPECT_TRUE(test_suites[0]->should_run());
+    EXPECT_EQ(1, test_suites[0]->disabled_test_count());
+    ASSERT_EQ(4, test_suites[0]->total_test_count());
+    EXPECT_EQ(3, test_suites[0]->successful_test_count());
+    EXPECT_EQ(0, test_suites[0]->failed_test_count());
+    EXPECT_TRUE(test_suites[0]->Passed());
+    EXPECT_FALSE(test_suites[0]->Failed());
+
+    EXPECT_STREQ("DISABLED_Test", test_suites[1]->name());
+    EXPECT_TRUE(IsNull(test_suites[1]->type_param()));
+    EXPECT_FALSE(test_suites[1]->should_run());
+    EXPECT_EQ(1, test_suites[1]->disabled_test_count());
+    ASSERT_EQ(1, test_suites[1]->total_test_count());
+    EXPECT_EQ(0, test_suites[1]->successful_test_count());
+    EXPECT_EQ(0, test_suites[1]->failed_test_count());
+
+    EXPECT_STREQ("TestSuiteWithCommentTest/0", test_suites[2]->name());
+    EXPECT_STREQ(GetTypeName<Types<int>>().c_str(),
+                 test_suites[2]->type_param());
+    EXPECT_TRUE(test_suites[2]->should_run());
+    EXPECT_EQ(0, test_suites[2]->disabled_test_count());
+    ASSERT_EQ(1, test_suites[2]->total_test_count());
+    EXPECT_EQ(1, test_suites[2]->successful_test_count());
+    EXPECT_EQ(0, test_suites[2]->failed_test_count());
+    EXPECT_TRUE(test_suites[2]->Passed());
+    EXPECT_FALSE(test_suites[2]->Failed());
+
+    const TestSuite* test_suite = UnitTestHelper::FindTestSuite("ApiTest");
+    const TestInfo** tests = UnitTestHelper::GetSortedTests(test_suite);
+    EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
+    EXPECT_STREQ("ApiTest", tests[0]->test_suite_name());
+    EXPECT_FALSE(tests[0]->should_run());
+
+    EXPECT_STREQ("TestSuiteDisabledAccessorsWork", tests[1]->name());
+    EXPECT_STREQ("ApiTest", tests[1]->test_suite_name());
+    EXPECT_TRUE(IsNull(tests[1]->value_param()));
+    EXPECT_TRUE(IsNull(tests[1]->type_param()));
+    EXPECT_TRUE(tests[1]->should_run());
+    EXPECT_TRUE(tests[1]->result()->Passed());
+    EXPECT_EQ(0, tests[1]->result()->test_property_count());
+
+    EXPECT_STREQ("TestSuiteImmutableAccessorsWork", tests[2]->name());
+    EXPECT_STREQ("ApiTest", tests[2]->test_suite_name());
+    EXPECT_TRUE(IsNull(tests[2]->value_param()));
+    EXPECT_TRUE(IsNull(tests[2]->type_param()));
+    EXPECT_TRUE(tests[2]->should_run());
+    EXPECT_TRUE(tests[2]->result()->Passed());
+    EXPECT_EQ(0, tests[2]->result()->test_property_count());
+
+    EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
+    EXPECT_STREQ("ApiTest", tests[3]->test_suite_name());
+    EXPECT_TRUE(IsNull(tests[3]->value_param()));
+    EXPECT_TRUE(IsNull(tests[3]->type_param()));
+    EXPECT_TRUE(tests[3]->should_run());
+    EXPECT_TRUE(tests[3]->result()->Passed());
+    EXPECT_EQ(1, tests[3]->result()->test_property_count());
+    const TestProperty& property = tests[3]->result()->GetTestProperty(0);
+    EXPECT_STREQ("key", property.key());
+    EXPECT_STREQ("value", property.value());
+
+    delete[] tests;
+
+    test_suite = UnitTestHelper::FindTestSuite("TestSuiteWithCommentTest/0");
+    tests = UnitTestHelper::GetSortedTests(test_suite);
+
+    EXPECT_STREQ("Dummy", tests[0]->name());
+    EXPECT_STREQ("TestSuiteWithCommentTest/0", tests[0]->test_suite_name());
+    EXPECT_TRUE(IsNull(tests[0]->value_param()));
+    EXPECT_STREQ(GetTypeName<Types<int>>().c_str(), tests[0]->type_param());
+    EXPECT_TRUE(tests[0]->should_run());
+    EXPECT_TRUE(tests[0]->result()->Passed());
+    EXPECT_EQ(0, tests[0]->result()->test_property_count());
+
+    delete[] tests;
+    delete[] test_suites;
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_all_test.cc b/3rd-party/googletest/googletest/test/gtest_all_test.cc
new file mode 100644
index 0000000..615b29b
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_all_test.cc
@@ -0,0 +1,46 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for Google C++ Testing and Mocking Framework (Google Test)
+//
+// Sometimes it's desirable to build most of Google Test's own tests
+// by compiling a single file.  This file serves this purpose.
+#include "test/googletest-filepath-test.cc"
+#include "test/googletest-message-test.cc"
+#include "test/googletest-options-test.cc"
+#include "test/googletest-port-test.cc"
+#include "test/googletest-test-part-test.cc"
+#include "test/gtest-typed-test2_test.cc"
+#include "test/gtest-typed-test_test.cc"
+#include "test/gtest_pred_impl_unittest.cc"
+#include "test/gtest_prod_test.cc"
+#include "test/gtest_skip_test.cc"
+#include "test/gtest_unittest.cc"
+#include "test/production.cc"
diff --git a/3rd-party/googletest/googletest/test/gtest_assert_by_exception_test.cc b/3rd-party/googletest/googletest/test/gtest_assert_by_exception_test.cc
new file mode 100644
index 0000000..f507eac
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_assert_by_exception_test.cc
@@ -0,0 +1,112 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests Google Test's assert-by-exception mode with exceptions enabled.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdexcept>
+
+#include "gtest/gtest.h"
+
+class ThrowListener : public testing::EmptyTestEventListener {
+  void OnTestPartResult(const testing::TestPartResult& result) override {
+    if (result.type() == testing::TestPartResult::kFatalFailure) {
+      throw testing::AssertionException(result);
+    }
+  }
+};
+
+// Prints the given failure message and exits the program with
+// non-zero.  We use this instead of a Google Test assertion to
+// indicate a failure, as the latter is been tested and cannot be
+// relied on.
+void Fail(const char* msg) {
+  printf("FAILURE: %s\n", msg);
+  fflush(stdout);
+  exit(1);
+}
+
+static void AssertFalse() { ASSERT_EQ(2, 3) << "Expected failure"; }
+
+// Tests that an assertion failure throws a subclass of
+// std::runtime_error.
+TEST(Test, Test) {
+  // A successful assertion shouldn't throw.
+  try {
+    EXPECT_EQ(3, 3);
+  } catch (...) {
+    Fail("A successful assertion wrongfully threw.");
+  }
+
+  // A successful assertion shouldn't throw.
+  try {
+    EXPECT_EQ(3, 4);
+  } catch (...) {
+    Fail("A failed non-fatal assertion wrongfully threw.");
+  }
+
+  // A failed assertion should throw.
+  try {
+    AssertFalse();
+  } catch (const testing::AssertionException& e) {
+    if (strstr(e.what(), "Expected failure") != nullptr) throw;
+
+    printf("%s",
+           "A failed assertion did throw an exception of the right type, "
+           "but the message is incorrect.  Instead of containing \"Expected "
+           "failure\", it is:\n");
+    Fail(e.what());
+  } catch (...) {
+    Fail("A failed assertion threw the wrong type of exception.");
+  }
+  Fail("A failed assertion should've thrown but didn't.");
+}
+
+int kTestForContinuingTest = 0;
+
+TEST(Test, Test2) { kTestForContinuingTest = 1; }
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
+
+  int result = RUN_ALL_TESTS();
+  if (result == 0) {
+    printf("RUN_ALL_TESTS returned %d\n", result);
+    Fail("Expected failure instead.");
+  }
+
+  if (kTestForContinuingTest == 0) {
+    Fail("Should have continued with other tests, but did not.");
+  }
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_dirs_test.cc b/3rd-party/googletest/googletest/test/gtest_dirs_test.cc
new file mode 100644
index 0000000..1a5b63d
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_dirs_test.cc
@@ -0,0 +1,101 @@
+#include <sys/stat.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_FILE_SYSTEM
+
+namespace {
+
+class SetEnv {
+ public:
+  // Sets the environment value with name `name` to `value`, unless `value` is
+  // nullptr, in which case it unsets it. Restores the original value on
+  // destruction.
+  SetEnv(const char* name, const char* value) : name_(name) {
+    const char* old_value = getenv(name);
+    if (old_value != nullptr) {
+      saved_value_ = old_value;
+      have_saved_value_ = true;
+    }
+    if (value == nullptr) {
+      GTEST_CHECK_POSIX_SUCCESS_(unsetenv(name));
+    } else {
+      GTEST_CHECK_POSIX_SUCCESS_(setenv(name, value, 1 /*overwrite*/));
+    }
+  }
+
+  ~SetEnv() {
+    if (have_saved_value_) {
+      GTEST_CHECK_POSIX_SUCCESS_(
+          setenv(name_.c_str(), saved_value_.c_str(), 1 /*overwrite*/));
+    } else {
+      GTEST_CHECK_POSIX_SUCCESS_(unsetenv(name_.c_str()));
+    }
+  }
+
+ private:
+  std::string name_;
+  bool have_saved_value_ = false;
+  std::string saved_value_;
+};
+
+class MakeTempDir {
+ public:
+  // Creates a directory with a unique name including `testname`.
+  // The destructor removes it.
+  explicit MakeTempDir(const std::string& testname) {
+    // mkdtemp requires that the last 6 characters of the input pattern
+    // are Xs, and the string is modified by replacing those characters.
+    std::string pattern = "/tmp/" + testname + "_XXXXXX";
+    GTEST_CHECK_(mkdtemp(pattern.data()) != nullptr);
+    dirname_ = pattern;
+  }
+
+  ~MakeTempDir() { GTEST_CHECK_POSIX_SUCCESS_(rmdir(dirname_.c_str())); }
+
+  const char* DirName() const { return dirname_.c_str(); }
+
+ private:
+  std::string dirname_;
+};
+
+bool StartsWith(const std::string& str, const std::string& prefix) {
+  return str.substr(0, prefix.size()) == prefix;
+}
+
+TEST(TempDirTest, InEnvironment) {
+  // Since the test infrastructure might be verifying directory existence or
+  // even creating subdirectories, we need to be careful that the directories we
+  // specify are actually valid.
+  MakeTempDir temp_dir("TempDirTest_InEnvironment");
+  SetEnv set_env("TEST_TMPDIR", temp_dir.DirName());
+  EXPECT_TRUE(StartsWith(testing::TempDir(), temp_dir.DirName()));
+}
+
+TEST(TempDirTest, NotInEnvironment) {
+  SetEnv set_env("TEST_TMPDIR", nullptr);
+  EXPECT_NE(testing::TempDir(), "");
+}
+
+TEST(SrcDirTest, InEnvironment) {
+  // Since the test infrastructure might be verifying directory existence or
+  // even creating subdirectories, we need to be careful that the directories we
+  // specify are actually valid.
+  MakeTempDir temp_dir("SrcDirTest_InEnvironment");
+  SetEnv set_env("TEST_SRCDIR", temp_dir.DirName());
+  EXPECT_TRUE(StartsWith(testing::SrcDir(), temp_dir.DirName()));
+}
+
+TEST(SrcDirTest, NotInEnvironment) {
+  SetEnv set_env("TEST_SRCDIR", nullptr);
+  EXPECT_NE(testing::SrcDir(), "");
+}
+
+#endif  // GTEST_HAS_FILE_SYSTEM
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/test/gtest_environment_test.cc b/3rd-party/googletest/googletest/test/gtest_environment_test.cc
new file mode 100644
index 0000000..03657c7
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_environment_test.cc
@@ -0,0 +1,187 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests using global test environments.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+namespace {
+
+enum FailureType { NO_FAILURE, NON_FATAL_FAILURE, FATAL_FAILURE };
+
+// Was SetUp run?
+bool set_up_was_run;
+// Was TearDown run?
+bool tear_down_was_run;
+// Was the TEST run?
+bool test_was_run;
+
+// For testing using global test environments.
+class MyEnvironment : public testing::Environment {
+ public:
+  // Depending on the value of failure_in_set_up_, SetUp() will
+  // generate a non-fatal failure, generate a fatal failure, or
+  // succeed.
+  void SetUp() override {
+    set_up_was_run = true;
+
+    switch (failure_in_set_up_) {
+      case NON_FATAL_FAILURE:
+        ADD_FAILURE() << "Expected non-fatal failure in global set-up.";
+        break;
+      case FATAL_FAILURE:
+        FAIL() << "Expected fatal failure in global set-up.";
+        break;
+      default:
+        break;
+    }
+  }
+
+  // Generates a non-fatal failure.
+  void TearDown() override {
+    tear_down_was_run = true;
+    ADD_FAILURE() << "Expected non-fatal failure in global tear-down.";
+  }
+
+  // We call this function to set the type of failure SetUp() should
+  // generate.
+  void set_failure_in_set_up(FailureType type) { failure_in_set_up_ = type; }
+
+ private:
+  FailureType failure_in_set_up_;
+};
+
+// The sole purpose of this TEST is to enable us to check whether it
+// was run.
+TEST(FooTest, Bar) { test_was_run = true; }
+
+// Prints the message and aborts the program if condition is false.
+void Check(bool condition, const char* msg) {
+  if (!condition) {
+    printf("FAILED: %s\n", msg);
+    testing::internal::posix::Abort();
+  }
+}
+
+// Runs the tests.  Return true if and only if successful.
+//
+// The 'failure' parameter specifies the type of failure that should
+// be generated by the global set-up.
+int RunAllTests(MyEnvironment* env, FailureType failure) {
+  set_up_was_run = false;
+  tear_down_was_run = false;
+  test_was_run = false;
+  env->set_failure_in_set_up(failure);
+  testing::internal::GetUnitTestImpl()->ClearAdHocTestResult();
+  return RUN_ALL_TESTS();
+}
+
+// Registers a global test environment, and verifies that the
+// registration function returns its argument.
+MyEnvironment* RegisterTestEnv() {
+  MyEnvironment* const env = new MyEnvironment;
+  Check(testing::AddGlobalTestEnvironment(env) == env,
+        "AddGlobalTestEnvironment() should return its argument.");
+  return env;
+}
+
+// Verifies that RUN_ALL_TESTS() runs the tests when the global
+// set-up is successful.
+void TestGlobalSetUp() {
+  MyEnvironment* const env = RegisterTestEnv();
+  Check(RunAllTests(env, NO_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global tear-down "
+        "should generate a failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "failure");
+  Check(tear_down_was_run,
+        "The global tear-down should run, as the global set-up was run.");
+}
+
+// Verifies that RUN_ALL_TESTS() runs the tests when the global
+// set-up generates no fatal failure.
+void TestTestsRun() {
+  MyEnvironment* const env = RegisterTestEnv();
+  Check(RunAllTests(env, NON_FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as both the global set-up "
+        "and the global tear-down should generate a non-fatal failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "fatal failure.");
+  Check(tear_down_was_run,
+        "The global tear-down should run, as the global set-up was run.");
+}
+
+// Verifies that RUN_ALL_TESTS() runs no test when the global set-up
+// generates a fatal failure.
+void TestNoTestsRunSetUpFailure() {
+  MyEnvironment* const env = RegisterTestEnv();
+  Check(RunAllTests(env, FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global set-up "
+        "should generate a fatal failure.");
+  Check(!test_was_run,
+        "The tests should not run, as the global set-up should generate "
+        "a fatal failure.");
+  Check(tear_down_was_run,
+        "The global tear-down should run, as the global set-up was run.");
+}
+
+// Verifies that RUN_ALL_TESTS() doesn't do global set-up or
+// tear-down when there is no test to run.
+void TestNoTestsSkipsSetUp() {
+  MyEnvironment* const env = RegisterTestEnv();
+  GTEST_FLAG_SET(filter, "-*");
+  Check(RunAllTests(env, NO_FAILURE) == 0,
+        "RUN_ALL_TESTS() should return zero, as there is no test to run.");
+  Check(!set_up_was_run,
+        "The global set-up should not run, as there is no test to run.");
+  Check(!tear_down_was_run,
+        "The global tear-down should not run, "
+        "as the global set-up was not run.");
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  TestGlobalSetUp();
+  TestTestsRun();
+  TestNoTestsRunSetUpFailure();
+  TestNoTestsSkipsSetUp();
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_help_test.py b/3rd-party/googletest/googletest/test/gtest_help_test.py
new file mode 100755
index 0000000..38fc90f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_help_test.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests the --help flag of Google C++ Testing and Mocking Framework.
+
+SYNOPSIS
+       gtest_help_test.py --build_dir=BUILD/DIR
+         # where BUILD/DIR contains the built gtest_help_test_ file.
+       gtest_help_test.py
+"""
+
+import os
+import re
+import sys
+from googletest.test import gtest_test_utils
+
+
+FREEBSD = ('FreeBSD', 'GNU/kFreeBSD')
+NETBSD = ('NetBSD',)
+OPENBSD = ('OpenBSD',)
+
+
+def is_bsd_based_os() -> bool:
+  """Determine whether or not the OS is BSD-based."""
+  if os.name != 'posix':
+    return False
+
+  return os.uname()[0] in (FREEBSD + NETBSD + OPENBSD)
+
+
+IS_DARWIN = os.name == 'posix' and os.uname()[0] == 'Darwin'
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+IS_GNUHURD = os.name == 'posix' and os.uname()[0] == 'GNU'
+IS_WINDOWS = os.name == 'nt'
+
+PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_')
+FLAG_PREFIX = '--gtest_'
+DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style'
+STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to'
+LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
+INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing'
+
+SUPPORTS_DEATH_TESTS = (
+    'DeathTest'
+    in gtest_test_utils.Subprocess([PROGRAM_PATH, LIST_TESTS_FLAG]).output
+)
+
+HAS_ABSL_FLAGS = '--has_absl_flags' in sys.argv
+
+# The help message must match this regex.
+HELP_REGEX = re.compile(
+    FLAG_PREFIX
+    + r'list_tests.*'
+    + FLAG_PREFIX
+    + r'filter=.*'
+    + FLAG_PREFIX
+    + r'also_run_disabled_tests.*'
+    + FLAG_PREFIX
+    + r'repeat=.*'
+    + FLAG_PREFIX
+    + r'shuffle.*'
+    + FLAG_PREFIX
+    + r'random_seed=.*'
+    + FLAG_PREFIX
+    + r'color=.*'
+    + FLAG_PREFIX
+    + r'brief.*'
+    + FLAG_PREFIX
+    + r'print_time.*'
+    + FLAG_PREFIX
+    + r'output=.*'
+    + FLAG_PREFIX
+    + r'break_on_failure.*'
+    + FLAG_PREFIX
+    + r'throw_on_failure.*'
+    + FLAG_PREFIX
+    + r'catch_exceptions=0.*',
+    re.DOTALL,
+)
+
+
+def run_with_flag(flag):
+  """Runs gtest_help_test_ with the given flag.
+
+  Returns:
+    the exit code and the text output as a tuple.
+  Args:
+    flag: the command-line flag to pass to gtest_help_test_, or None.
+  """
+
+  if flag is None:
+    command = [PROGRAM_PATH]
+  else:
+    command = [PROGRAM_PATH, flag]
+  child = gtest_test_utils.Subprocess(command)
+  return child.exit_code, child.output
+
+
+class GTestHelpTest(gtest_test_utils.TestCase):
+  """Tests the --help flag and its equivalent forms."""
+
+  def test_prints_help_with_full_flag(self):
+    """Verifies correct behavior when help flag is specified.
+
+    The right message must be printed and the tests must
+    skipped when the given flag is specified.
+    """
+
+    exit_code, output = run_with_flag('--help')
+    if HAS_ABSL_FLAGS:
+      # The Abseil flags library prints the ProgramUsageMessage() with
+      # --help and returns 1.
+      self.assertEqual(1, exit_code)
+    else:
+      self.assertEqual(0, exit_code)
+
+    self.assertTrue(HELP_REGEX.search(output), output)
+
+    if IS_DARWIN or IS_LINUX or IS_GNUHURD or is_bsd_based_os():
+      self.assertIn(STREAM_RESULT_TO_FLAG, output)
+    else:
+      self.assertNotIn(STREAM_RESULT_TO_FLAG, output)
+
+    if SUPPORTS_DEATH_TESTS and not IS_WINDOWS:
+      self.assertIn(DEATH_TEST_STYLE_FLAG, output)
+    else:
+      self.assertNotIn(DEATH_TEST_STYLE_FLAG, output)
+
+  def test_runs_tests_without_help_flag(self):
+    """Verifies correct behavior when no help flag is specified.
+
+    Verifies that when no help flag is specified, the tests are run
+    and the help message is not printed.
+    """
+
+    exit_code, output = run_with_flag(None)
+    self.assertNotEqual(exit_code, 0)
+    self.assertFalse(HELP_REGEX.search(output), output)
+
+  def test_runs_tests_with_gtest_internal_flag(self):
+    """Verifies correct behavior when internal testing flag is specified.
+
+    Verifies that the tests are run and no help message is printed when
+    a flag starting with Google Test prefix and 'internal_' is supplied.
+    """
+
+    exit_code, output = run_with_flag(INTERNAL_FLAG_FOR_TESTING)
+    self.assertNotEqual(exit_code, 0)
+    self.assertFalse(HELP_REGEX.search(output), output)
+
+
+if __name__ == '__main__':
+  if '--has_absl_flags' in sys.argv:
+    sys.argv.remove('--has_absl_flags')
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_help_test_.cc b/3rd-party/googletest/googletest/test/gtest_help_test_.cc
new file mode 100644
index 0000000..18b5f3c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_help_test_.cc
@@ -0,0 +1,44 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This program is meant to be run by gtest_help_test.py.  Do not run
+// it directly.
+
+#include "gtest/gtest.h"
+
+// When a help flag is specified, this program should skip the tests
+// and exit with 0; otherwise the following test will be executed,
+// causing this program to exit with a non-zero code.
+TEST(HelpFlagTest, ShouldNotBeRun) {
+  ASSERT_TRUE(false) << "Tests shouldn't be run when --help is specified.";
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+TEST(DeathTest, UsedByPythonScriptToDetectSupportForDeathTestsInThisBinary) {}
+#endif
diff --git a/3rd-party/googletest/googletest/test/gtest_json_test_utils.py b/3rd-party/googletest/googletest/test/gtest_json_test_utils.py
new file mode 100644
index 0000000..694a7a6
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_json_test_utils.py
@@ -0,0 +1,67 @@
+# Copyright 2018, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for gtest_json_output."""
+
+import re
+
+
+def normalize(obj):
+  """Normalize output object.
+
+  Args:
+     obj: Google Test's JSON output object to normalize.
+
+  Returns:
+     Normalized output without any references to transient information that may
+     change from run to run.
+  """
+
+  def _normalize(key, value):
+    if key == 'time':
+      return re.sub(r'^\d+(\.\d+)?s$', '*', value)
+    elif key == 'timestamp':
+      return re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ$', '*', value)
+    elif key == 'failure':
+      value = re.sub(r'^.*[/\\](.*:)\d+\n', '\\1*\n', value)
+      return re.sub(r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', value)
+    elif key == 'message':
+      value = re.sub(r'^.*[/\\](.*:)\d+\n', '\\1*\n', value)
+      return re.sub(r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', value)
+    elif key == 'file':
+      return re.sub(r'^.*[/\\](.*)', '\\1', value)
+    else:
+      return normalize(value)
+
+  if isinstance(obj, dict):
+    return {k: _normalize(k, v) for k, v in obj.items()}
+  if isinstance(obj, list):
+    return [normalize(x) for x in obj]
+  else:
+    return obj
diff --git a/3rd-party/googletest/googletest/test/gtest_list_output_unittest.py b/3rd-party/googletest/googletest/test/gtest_list_output_unittest.py
new file mode 100644
index 0000000..afd521d
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_list_output_unittest.py
@@ -0,0 +1,289 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Unit test for Google Test's --gtest_list_tests flag.
+
+A user can ask Google Test to list all tests by specifying the
+--gtest_list_tests flag. If output is requested, via --gtest_output=xml
+or --gtest_output=json, the tests are listed, with extra information in the
+output file.
+This script tests such functionality by invoking gtest_list_output_unittest_
+ (a program written with Google Test) the command line flags.
+"""
+
+import os
+import re
+from googletest.test import gtest_test_utils
+
+GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
+GTEST_OUTPUT_FLAG = '--gtest_output'
+
+EXPECTED_XML = """<\?xml version="1.0" encoding="UTF-8"\?>
+<testsuites tests="16" name="AllTests">
+  <testsuite name="FooTest" tests="2">
+    <testcase name="Test1" file=".*gtest_list_output_unittest_.cc" line="43" />
+    <testcase name="Test2" file=".*gtest_list_output_unittest_.cc" line="45" />
+  </testsuite>
+  <testsuite name="FooTestFixture" tests="2">
+    <testcase name="Test3" file=".*gtest_list_output_unittest_.cc" line="48" />
+    <testcase name="Test4" file=".*gtest_list_output_unittest_.cc" line="49" />
+  </testsuite>
+  <testsuite name="TypedTest/0" tests="2">
+    <testcase name="Test7" type_param="int" file=".*gtest_list_output_unittest_.cc" line="60" />
+    <testcase name="Test8" type_param="int" file=".*gtest_list_output_unittest_.cc" line="61" />
+  </testsuite>
+  <testsuite name="TypedTest/1" tests="2">
+    <testcase name="Test7" type_param="bool" file=".*gtest_list_output_unittest_.cc" line="60" />
+    <testcase name="Test8" type_param="bool" file=".*gtest_list_output_unittest_.cc" line="61" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestSuite/0" tests="2">
+    <testcase name="Test9" type_param="int" file=".*gtest_list_output_unittest_.cc" line="66" />
+    <testcase name="Test10" type_param="int" file=".*gtest_list_output_unittest_.cc" line="67" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestSuite/1" tests="2">
+    <testcase name="Test9" type_param="bool" file=".*gtest_list_output_unittest_.cc" line="66" />
+    <testcase name="Test10" type_param="bool" file=".*gtest_list_output_unittest_.cc" line="67" />
+  </testsuite>
+  <testsuite name="ValueParam/ValueParamTest" tests="4">
+    <testcase name="Test5/0" value_param="33" file=".*gtest_list_output_unittest_.cc" line="52" />
+    <testcase name="Test5/1" value_param="42" file=".*gtest_list_output_unittest_.cc" line="52" />
+    <testcase name="Test6/0" value_param="33" file=".*gtest_list_output_unittest_.cc" line="53" />
+    <testcase name="Test6/1" value_param="42" file=".*gtest_list_output_unittest_.cc" line="53" />
+  </testsuite>
+</testsuites>
+"""
+
+EXPECTED_JSON = """{
+  "tests": 16,
+  "name": "AllTests",
+  "testsuites": \[
+    {
+      "name": "FooTest",
+      "tests": 2,
+      "testsuite": \[
+        {
+          "name": "Test1",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 43
+        },
+        {
+          "name": "Test2",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 45
+        }
+      \]
+    },
+    {
+      "name": "FooTestFixture",
+      "tests": 2,
+      "testsuite": \[
+        {
+          "name": "Test3",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 48
+        },
+        {
+          "name": "Test4",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 49
+        }
+      \]
+    },
+    {
+      "name": "TypedTest\\\\/0",
+      "tests": 2,
+      "testsuite": \[
+        {
+          "name": "Test7",
+          "type_param": "int",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 60
+        },
+        {
+          "name": "Test8",
+          "type_param": "int",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 61
+        }
+      \]
+    },
+    {
+      "name": "TypedTest\\\\/1",
+      "tests": 2,
+      "testsuite": \[
+        {
+          "name": "Test7",
+          "type_param": "bool",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 60
+        },
+        {
+          "name": "Test8",
+          "type_param": "bool",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 61
+        }
+      \]
+    },
+    {
+      "name": "Single\\\\/TypeParameterizedTestSuite\\\\/0",
+      "tests": 2,
+      "testsuite": \[
+        {
+          "name": "Test9",
+          "type_param": "int",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 66
+        },
+        {
+          "name": "Test10",
+          "type_param": "int",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 67
+        }
+      \]
+    },
+    {
+      "name": "Single\\\\/TypeParameterizedTestSuite\\\\/1",
+      "tests": 2,
+      "testsuite": \[
+        {
+          "name": "Test9",
+          "type_param": "bool",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 66
+        },
+        {
+          "name": "Test10",
+          "type_param": "bool",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 67
+        }
+      \]
+    },
+    {
+      "name": "ValueParam\\\\/ValueParamTest",
+      "tests": 4,
+      "testsuite": \[
+        {
+          "name": "Test5\\\\/0",
+          "value_param": "33",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 52
+        },
+        {
+          "name": "Test5\\\\/1",
+          "value_param": "42",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 52
+        },
+        {
+          "name": "Test6\\\\/0",
+          "value_param": "33",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 53
+        },
+        {
+          "name": "Test6\\\\/1",
+          "value_param": "42",
+          "file": ".*gtest_list_output_unittest_.cc",
+          "line": 53
+        }
+      \]
+    }
+  \]
+}
+"""
+
+
+class GTestListTestsOutputUnitTest(gtest_test_utils.TestCase):
+  """Unit test for Google Test's list tests with output to file functionality."""
+
+  def testXml(self):
+    """Verifies XML output for listing tests in a Google Test binary.
+
+    Runs a test program that generates an empty XML output, and
+    tests that the XML output is expected.
+    """
+    self._TestOutput('xml', EXPECTED_XML)
+
+  def testJSON(self):
+    """Verifies XML output for listing tests in a Google Test binary.
+
+    Runs a test program that generates an empty XML output, and
+    tests that the XML output is expected.
+    """
+    self._TestOutput('json', EXPECTED_JSON)
+
+  def _GetOutput(self, out_format):
+    file_path = os.path.join(
+        gtest_test_utils.GetTempDir(), 'test_out.' + out_format
+    )
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
+        'gtest_list_output_unittest_'
+    )
+
+    command = [
+        gtest_prog_path,
+        '%s=%s:%s' % (GTEST_OUTPUT_FLAG, out_format, file_path),
+        '--gtest_list_tests',
+    ]
+    environ_copy = os.environ.copy()
+    p = gtest_test_utils.Subprocess(
+        command, env=environ_copy, working_dir=gtest_test_utils.GetTempDir()
+    )
+
+    self.assertTrue(p.exited)
+    self.assertEqual(0, p.exit_code)
+    self.assertTrue(os.path.isfile(file_path))
+    with open(file_path) as f:
+      result = f.read()
+    return result
+
+  def _TestOutput(self, test_format, expected_output):
+    actual = self._GetOutput(test_format)
+    actual_lines = actual.splitlines()
+    expected_lines = expected_output.splitlines()
+    line_count = 0
+    for actual_line in actual_lines:
+      expected_line = expected_lines[line_count]
+      expected_line_re = re.compile(expected_line.strip())
+      self.assertTrue(
+          expected_line_re.match(actual_line.strip()),
+          'actual output of "%s",\n'
+          'which does not match expected regex of "%s"\n'
+          'on line %d' % (actual, expected_output, line_count),
+      )
+      line_count = line_count + 1
+
+
+if __name__ == '__main__':
+  os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_list_output_unittest_.cc b/3rd-party/googletest/googletest/test/gtest_list_output_unittest_.cc
new file mode 100644
index 0000000..92b9d4f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_list_output_unittest_.cc
@@ -0,0 +1,77 @@
+// Copyright 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: david.schuldenfrei@gmail.com (David Schuldenfrei)
+
+// Unit test for Google Test's --gtest_list_tests and --gtest_output flag.
+//
+// A user can ask Google Test to list all tests that will run,
+// and have the output saved in a Json/Xml file.
+// The tests will not be run after listing.
+//
+// This program will be invoked from a Python unit test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+TEST(FooTest, Test1) {}
+
+TEST(FooTest, Test2) {}
+
+class FooTestFixture : public ::testing::Test {};
+TEST_F(FooTestFixture, Test3) {}
+TEST_F(FooTestFixture, Test4) {}
+
+class ValueParamTest : public ::testing::TestWithParam<int> {};
+TEST_P(ValueParamTest, Test5) {}
+TEST_P(ValueParamTest, Test6) {}
+INSTANTIATE_TEST_SUITE_P(ValueParam, ValueParamTest, ::testing::Values(33, 42));
+
+template <typename T>
+class TypedTest : public ::testing::Test {};
+typedef testing::Types<int, bool> TypedTestTypes;
+TYPED_TEST_SUITE(TypedTest, TypedTestTypes);
+TYPED_TEST(TypedTest, Test7) {}
+TYPED_TEST(TypedTest, Test8) {}
+
+template <typename T>
+class TypeParameterizedTestSuite : public ::testing::Test {};
+TYPED_TEST_SUITE_P(TypeParameterizedTestSuite);
+TYPED_TEST_P(TypeParameterizedTestSuite, Test9) {}
+TYPED_TEST_P(TypeParameterizedTestSuite, Test10) {}
+REGISTER_TYPED_TEST_SUITE_P(TypeParameterizedTestSuite, Test9, Test10);
+typedef testing::Types<int, bool> TypeParameterizedTestSuiteTypes;  // NOLINT
+INSTANTIATE_TYPED_TEST_SUITE_P(Single, TypeParameterizedTestSuite,
+                               TypeParameterizedTestSuiteTypes);
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_main_unittest.cc b/3rd-party/googletest/googletest/test/gtest_main_unittest.cc
new file mode 100644
index 0000000..29cd551
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_main_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest.h"
+
+// Tests that we don't have to define main() when we link to
+// gtest_main instead of gtest.
+
+namespace {
+
+TEST(GTestMainTest, ShouldSucceed) {}
+
+}  // namespace
+
+// We are using the main() function defined in gtest_main.cc, so we
+// don't define it here.
diff --git a/3rd-party/googletest/googletest/test/gtest_no_test_unittest.cc b/3rd-party/googletest/googletest/test/gtest_no_test_unittest.cc
new file mode 100644
index 0000000..d4f88db
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_no_test_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests that a Google Test program that has no test defined can run
+// successfully.
+
+#include "gtest/gtest.h"
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // An ad-hoc assertion outside of all tests.
+  //
+  // This serves three purposes:
+  //
+  // 1. It verifies that an ad-hoc assertion can be executed even if
+  //    no test is defined.
+  // 2. It verifies that a failed ad-hoc assertion causes the test
+  //    program to fail.
+  // 3. We had a bug where the XML output won't be generated if an
+  //    assertion is executed before RUN_ALL_TESTS() is called, even
+  //    though --gtest_output=xml is specified.  This makes sure the
+  //    bug is fixed and doesn't regress.
+  EXPECT_EQ(1, 2);
+
+  // The above EXPECT_EQ() should cause RUN_ALL_TESTS() to return non-zero.
+  return RUN_ALL_TESTS() ? 0 : 1;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_pred_impl_unittest.cc b/3rd-party/googletest/googletest/test/gtest_pred_impl_unittest.cc
new file mode 100644
index 0000000..033e2d9
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_pred_impl_unittest.cc
@@ -0,0 +1,2070 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Regression test for gtest_pred_impl.h
+//
+// This file is generated by a script and quite long.  If you intend to
+// learn how Google Test works by reading its unit tests, read
+// gtest_unittest.cc instead.
+//
+// This is intended as a regression test for the Google Test predicate
+// assertions.  We compile it as part of the gtest_unittest target
+// only to keep the implementation tidy and compact, as it is quite
+// involved to set up the stage for testing Google Test using Google
+// Test itself.
+//
+// Currently, gtest_unittest takes ~11 seconds to run in the testing
+// daemon.  In the future, if it grows too large and needs much more
+// time to finish, we should consider separating this file into a
+// stand-alone regression test.
+
+#include <iostream>
+#include <ostream>
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+// A user-defined data type.
+struct Bool {
+  explicit Bool(int val) : value(val != 0) {}
+
+  bool operator>(int n) const { return value > Bool(n).value; }
+
+  Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
+
+  bool operator==(const Bool& rhs) const { return value == rhs.value; }
+
+  bool value;
+};
+
+// Enables Bool to be used in assertions.
+std::ostream& operator<<(std::ostream& os, const Bool& x) {
+  return os << (x.value ? "true" : "false");
+}
+
+// Sample functions/functors for testing unary predicate assertions.
+
+// A unary predicate function.
+template <typename T1>
+bool PredFunction1(T1 v1) {
+  return v1 > 0;
+}
+
+// The following two functions are needed because a compiler doesn't have
+// a context yet to know which template function must be instantiated.
+bool PredFunction1Int(int v1) { return v1 > 0; }
+bool PredFunction1Bool(Bool v1) { return v1 > 0; }
+
+// A unary predicate functor.
+struct PredFunctor1 {
+  template <typename T1>
+  bool operator()(const T1& v1) {
+    return v1 > 0;
+  }
+};
+
+// A unary predicate-formatter function.
+template <typename T1>
+testing::AssertionResult PredFormatFunction1(const char* e1, const T1& v1) {
+  if (PredFunction1(v1)) return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+         << e1 << " is expected to be positive, but evaluates to " << v1 << ".";
+}
+
+// A unary predicate-formatter functor.
+struct PredFormatFunctor1 {
+  template <typename T1>
+  testing::AssertionResult operator()(const char* e1, const T1& v1) const {
+    return PredFormatFunction1(e1, v1);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT1.
+
+class Predicate1Test : public testing::Test {
+ protected:
+  void SetUp() override {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = 0;
+  }
+
+  void TearDown() override {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) << "The predicate assertion didn't evaluate argument 2 "
+                         "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpectedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true if and only if the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true if and only if the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+};
+
+bool Predicate1Test::expected_to_finish_;
+bool Predicate1Test::finished_;
+int Predicate1Test::n1_;
+
+typedef Predicate1Test EXPECT_PRED_FORMAT1Test;
+typedef Predicate1Test ASSERT_PRED_FORMAT1Test;
+typedef Predicate1Test EXPECT_PRED1Test;
+typedef Predicate1Test ASSERT_PRED1Test;
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED1(PredFunction1Int, ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED1(PredFunction1Bool, Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED1(PredFunctor1(), ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED1(PredFunctor1(), Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED1(PredFunction1Int, n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED1(PredFunction1Bool, Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED1(PredFunctor1(), n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED1(PredFunctor1(), Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED1(PredFunction1Int, ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED1(PredFunction1Bool, Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED1(PredFunctor1(), ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED1(PredFunctor1(), Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED1(PredFunction1Int, n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED1(PredFunction1Bool, Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED1(PredFunctor1(), n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED1(PredFunctor1(), Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunction1, ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunction1, Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunctor1(), ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunctor1(), Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT1(PredFormatFunction1, n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT1(PredFormatFunction1, Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT1(PredFormatFunctor1(), n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT1(PredFormatFunctor1(), Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunction1, ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunction1, Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunctor1(), ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunctor1(), Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT1(PredFormatFunction1, n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT1(PredFormatFunction1, Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT1(PredFormatFunctor1(), n1_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT1(PredFormatFunctor1(), Bool(n1_++));
+        finished_ = true;
+      },
+      "");
+}
+// Sample functions/functors for testing binary predicate assertions.
+
+// A binary predicate function.
+template <typename T1, typename T2>
+bool PredFunction2(T1 v1, T2 v2) {
+  return v1 + v2 > 0;
+}
+
+// The following two functions are needed because a compiler doesn't have
+// a context yet to know which template function must be instantiated.
+bool PredFunction2Int(int v1, int v2) { return v1 + v2 > 0; }
+bool PredFunction2Bool(Bool v1, Bool v2) { return v1 + v2 > 0; }
+
+// A binary predicate functor.
+struct PredFunctor2 {
+  template <typename T1, typename T2>
+  bool operator()(const T1& v1, const T2& v2) {
+    return v1 + v2 > 0;
+  }
+};
+
+// A binary predicate-formatter function.
+template <typename T1, typename T2>
+testing::AssertionResult PredFormatFunction2(const char* e1, const char* e2,
+                                             const T1& v1, const T2& v2) {
+  if (PredFunction2(v1, v2)) return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+         << e1 << " + " << e2
+         << " is expected to be positive, but evaluates to " << v1 + v2 << ".";
+}
+
+// A binary predicate-formatter functor.
+struct PredFormatFunctor2 {
+  template <typename T1, typename T2>
+  testing::AssertionResult operator()(const char* e1, const char* e2,
+                                      const T1& v1, const T2& v2) const {
+    return PredFormatFunction2(e1, e2, v1, v2);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT2.
+
+class Predicate2Test : public testing::Test {
+ protected:
+  void SetUp() override {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = 0;
+  }
+
+  void TearDown() override {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) << "The predicate assertion didn't evaluate argument 2 "
+                         "exactly once.";
+    EXPECT_EQ(1, n2_) << "The predicate assertion didn't evaluate argument 3 "
+                         "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpectedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true if and only if the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true if and only if the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+};
+
+bool Predicate2Test::expected_to_finish_;
+bool Predicate2Test::finished_;
+int Predicate2Test::n1_;
+int Predicate2Test::n2_;
+
+typedef Predicate2Test EXPECT_PRED_FORMAT2Test;
+typedef Predicate2Test ASSERT_PRED_FORMAT2Test;
+typedef Predicate2Test EXPECT_PRED2Test;
+typedef Predicate2Test ASSERT_PRED2Test;
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED2(PredFunction2Int, ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED2(PredFunction2Bool, Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED2(PredFunctor2(), ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED2(PredFunctor2(), Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED2(PredFunction2Int, n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED2(PredFunction2Bool, Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED2(PredFunctor2(), n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED2(PredFunctor2(), Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED2(PredFunction2Int, ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED2(PredFunction2Bool, Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED2(PredFunctor2(), ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED2(PredFunctor2(), Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED2(PredFunction2Int, n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED2(PredFunction2Bool, Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED2(PredFunctor2(), n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED2(PredFunctor2(), Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunction2, ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunction2, Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunctor2(), ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunctor2(), Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(PredFormatFunction2, n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(PredFormatFunction2, Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(PredFormatFunctor2(), n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(PredFormatFunctor2(), Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunction2, ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunction2, Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunctor2(), ++n1_, ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunctor2(), Bool(++n1_), Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT2(PredFormatFunction2, n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT2(PredFormatFunction2, Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT2(PredFormatFunctor2(), n1_++, n2_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT2(PredFormatFunctor2(), Bool(n1_++), Bool(n2_++));
+        finished_ = true;
+      },
+      "");
+}
+// Sample functions/functors for testing ternary predicate assertions.
+
+// A ternary predicate function.
+template <typename T1, typename T2, typename T3>
+bool PredFunction3(T1 v1, T2 v2, T3 v3) {
+  return v1 + v2 + v3 > 0;
+}
+
+// The following two functions are needed because a compiler doesn't have
+// a context yet to know which template function must be instantiated.
+bool PredFunction3Int(int v1, int v2, int v3) { return v1 + v2 + v3 > 0; }
+bool PredFunction3Bool(Bool v1, Bool v2, Bool v3) { return v1 + v2 + v3 > 0; }
+
+// A ternary predicate functor.
+struct PredFunctor3 {
+  template <typename T1, typename T2, typename T3>
+  bool operator()(const T1& v1, const T2& v2, const T3& v3) {
+    return v1 + v2 + v3 > 0;
+  }
+};
+
+// A ternary predicate-formatter function.
+template <typename T1, typename T2, typename T3>
+testing::AssertionResult PredFormatFunction3(const char* e1, const char* e2,
+                                             const char* e3, const T1& v1,
+                                             const T2& v2, const T3& v3) {
+  if (PredFunction3(v1, v2, v3)) return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+         << e1 << " + " << e2 << " + " << e3
+         << " is expected to be positive, but evaluates to " << v1 + v2 + v3
+         << ".";
+}
+
+// A ternary predicate-formatter functor.
+struct PredFormatFunctor3 {
+  template <typename T1, typename T2, typename T3>
+  testing::AssertionResult operator()(const char* e1, const char* e2,
+                                      const char* e3, const T1& v1,
+                                      const T2& v2, const T3& v3) const {
+    return PredFormatFunction3(e1, e2, e3, v1, v2, v3);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT3.
+
+class Predicate3Test : public testing::Test {
+ protected:
+  void SetUp() override {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = 0;
+  }
+
+  void TearDown() override {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) << "The predicate assertion didn't evaluate argument 2 "
+                         "exactly once.";
+    EXPECT_EQ(1, n2_) << "The predicate assertion didn't evaluate argument 3 "
+                         "exactly once.";
+    EXPECT_EQ(1, n3_) << "The predicate assertion didn't evaluate argument 4 "
+                         "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpectedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true if and only if the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true if and only if the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+};
+
+bool Predicate3Test::expected_to_finish_;
+bool Predicate3Test::finished_;
+int Predicate3Test::n1_;
+int Predicate3Test::n2_;
+int Predicate3Test::n3_;
+
+typedef Predicate3Test EXPECT_PRED_FORMAT3Test;
+typedef Predicate3Test ASSERT_PRED_FORMAT3Test;
+typedef Predicate3Test EXPECT_PRED3Test;
+typedef Predicate3Test ASSERT_PRED3Test;
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED3(PredFunction3Int, ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED3(PredFunction3Bool, Bool(++n1_), Bool(++n2_), Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED3(PredFunctor3(), ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED3(PredFunctor3(), Bool(++n1_), Bool(++n2_), Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED3(PredFunction3Int, n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED3(PredFunction3Bool, Bool(n1_++), Bool(n2_++), Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED3(PredFunctor3(), n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED3(PredFunctor3(), Bool(n1_++), Bool(n2_++), Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED3(PredFunction3Int, ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED3(PredFunction3Bool, Bool(++n1_), Bool(++n2_), Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED3(PredFunctor3(), ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED3(PredFunctor3(), Bool(++n1_), Bool(++n2_), Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED3(PredFunction3Int, n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED3(PredFunction3Bool, Bool(n1_++), Bool(n2_++), Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED3(PredFunctor3(), n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED3(PredFunctor3(), Bool(n1_++), Bool(n2_++), Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunction3, ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunction3, Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunctor3(), ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunctor3(), Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT3(PredFormatFunction3, n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT3(PredFormatFunction3, Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT3(PredFormatFunctor3(), n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT3(PredFormatFunctor3(), Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunction3, ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunction3, Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunctor3(), ++n1_, ++n2_, ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunctor3(), Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT3(PredFormatFunction3, n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT3(PredFormatFunction3, Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT3(PredFormatFunctor3(), n1_++, n2_++, n3_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT3(PredFormatFunctor3(), Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++));
+        finished_ = true;
+      },
+      "");
+}
+// Sample functions/functors for testing 4-ary predicate assertions.
+
+// A 4-ary predicate function.
+template <typename T1, typename T2, typename T3, typename T4>
+bool PredFunction4(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+
+// The following two functions are needed because a compiler doesn't have
+// a context yet to know which template function must be instantiated.
+bool PredFunction4Int(int v1, int v2, int v3, int v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+bool PredFunction4Bool(Bool v1, Bool v2, Bool v3, Bool v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+
+// A 4-ary predicate functor.
+struct PredFunctor4 {
+  template <typename T1, typename T2, typename T3, typename T4>
+  bool operator()(const T1& v1, const T2& v2, const T3& v3, const T4& v4) {
+    return v1 + v2 + v3 + v4 > 0;
+  }
+};
+
+// A 4-ary predicate-formatter function.
+template <typename T1, typename T2, typename T3, typename T4>
+testing::AssertionResult PredFormatFunction4(const char* e1, const char* e2,
+                                             const char* e3, const char* e4,
+                                             const T1& v1, const T2& v2,
+                                             const T3& v3, const T4& v4) {
+  if (PredFunction4(v1, v2, v3, v4)) return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+         << e1 << " + " << e2 << " + " << e3 << " + " << e4
+         << " is expected to be positive, but evaluates to "
+         << v1 + v2 + v3 + v4 << ".";
+}
+
+// A 4-ary predicate-formatter functor.
+struct PredFormatFunctor4 {
+  template <typename T1, typename T2, typename T3, typename T4>
+  testing::AssertionResult operator()(const char* e1, const char* e2,
+                                      const char* e3, const char* e4,
+                                      const T1& v1, const T2& v2, const T3& v3,
+                                      const T4& v4) const {
+    return PredFormatFunction4(e1, e2, e3, e4, v1, v2, v3, v4);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT4.
+
+class Predicate4Test : public testing::Test {
+ protected:
+  void SetUp() override {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = n4_ = 0;
+  }
+
+  void TearDown() override {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) << "The predicate assertion didn't evaluate argument 2 "
+                         "exactly once.";
+    EXPECT_EQ(1, n2_) << "The predicate assertion didn't evaluate argument 3 "
+                         "exactly once.";
+    EXPECT_EQ(1, n3_) << "The predicate assertion didn't evaluate argument 4 "
+                         "exactly once.";
+    EXPECT_EQ(1, n4_) << "The predicate assertion didn't evaluate argument 5 "
+                         "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpectedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true if and only if the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true if and only if the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+  static int n4_;
+};
+
+bool Predicate4Test::expected_to_finish_;
+bool Predicate4Test::finished_;
+int Predicate4Test::n1_;
+int Predicate4Test::n2_;
+int Predicate4Test::n3_;
+int Predicate4Test::n4_;
+
+typedef Predicate4Test EXPECT_PRED_FORMAT4Test;
+typedef Predicate4Test ASSERT_PRED_FORMAT4Test;
+typedef Predicate4Test EXPECT_PRED4Test;
+typedef Predicate4Test ASSERT_PRED4Test;
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED4(PredFunction4Int, ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED4(PredFunction4Bool, Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED4(PredFunctor4(), ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED4(PredFunctor4(), Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED4(PredFunction4Int, n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED4(PredFunction4Bool, Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED4(PredFunctor4(), n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED4(PredFunctor4(), Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED4(PredFunction4Int, ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED4(PredFunction4Bool, Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED4(PredFunctor4(), ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED4(PredFunctor4(), Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED4(PredFunction4Int, n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED4(PredFunction4Bool, Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED4(PredFunctor4(), n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED4(PredFunctor4(), Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunction4, ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunction4, Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunctor4(), ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunctor4(), Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT4(PredFormatFunction4, n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT4(PredFormatFunction4, Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT4(PredFormatFunctor4(), n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT4(PredFormatFunctor4(), Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunction4, ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunction4, Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunctor4(), ++n1_, ++n2_, ++n3_, ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunctor4(), Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT4(PredFormatFunction4, n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT4(PredFormatFunction4, Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT4(PredFormatFunctor4(), n1_++, n2_++, n3_++, n4_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT4(PredFormatFunctor4(), Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++));
+        finished_ = true;
+      },
+      "");
+}
+// Sample functions/functors for testing 5-ary predicate assertions.
+
+// A 5-ary predicate function.
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+bool PredFunction5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+
+// The following two functions are needed because a compiler doesn't have
+// a context yet to know which template function must be instantiated.
+bool PredFunction5Int(int v1, int v2, int v3, int v4, int v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+bool PredFunction5Bool(Bool v1, Bool v2, Bool v3, Bool v4, Bool v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+
+// A 5-ary predicate functor.
+struct PredFunctor5 {
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  bool operator()(const T1& v1, const T2& v2, const T3& v3, const T4& v4,
+                  const T5& v5) {
+    return v1 + v2 + v3 + v4 + v5 > 0;
+  }
+};
+
+// A 5-ary predicate-formatter function.
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+testing::AssertionResult PredFormatFunction5(const char* e1, const char* e2,
+                                             const char* e3, const char* e4,
+                                             const char* e5, const T1& v1,
+                                             const T2& v2, const T3& v3,
+                                             const T4& v4, const T5& v5) {
+  if (PredFunction5(v1, v2, v3, v4, v5)) return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+         << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
+         << " is expected to be positive, but evaluates to "
+         << v1 + v2 + v3 + v4 + v5 << ".";
+}
+
+// A 5-ary predicate-formatter functor.
+struct PredFormatFunctor5 {
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  testing::AssertionResult operator()(const char* e1, const char* e2,
+                                      const char* e3, const char* e4,
+                                      const char* e5, const T1& v1,
+                                      const T2& v2, const T3& v3, const T4& v4,
+                                      const T5& v5) const {
+    return PredFormatFunction5(e1, e2, e3, e4, e5, v1, v2, v3, v4, v5);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT5.
+
+class Predicate5Test : public testing::Test {
+ protected:
+  void SetUp() override {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = n4_ = n5_ = 0;
+  }
+
+  void TearDown() override {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) << "The predicate assertion didn't evaluate argument 2 "
+                         "exactly once.";
+    EXPECT_EQ(1, n2_) << "The predicate assertion didn't evaluate argument 3 "
+                         "exactly once.";
+    EXPECT_EQ(1, n3_) << "The predicate assertion didn't evaluate argument 4 "
+                         "exactly once.";
+    EXPECT_EQ(1, n4_) << "The predicate assertion didn't evaluate argument 5 "
+                         "exactly once.";
+    EXPECT_EQ(1, n5_) << "The predicate assertion didn't evaluate argument 6 "
+                         "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpectedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true if and only if the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true if and only if the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+  static int n4_;
+  static int n5_;
+};
+
+bool Predicate5Test::expected_to_finish_;
+bool Predicate5Test::finished_;
+int Predicate5Test::n1_;
+int Predicate5Test::n2_;
+int Predicate5Test::n3_;
+int Predicate5Test::n4_;
+int Predicate5Test::n5_;
+
+typedef Predicate5Test EXPECT_PRED_FORMAT5Test;
+typedef Predicate5Test ASSERT_PRED_FORMAT5Test;
+typedef Predicate5Test EXPECT_PRED5Test;
+typedef Predicate5Test ASSERT_PRED5Test;
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED5(PredFunction5Int, ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED5(PredFunction5Bool, Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED5(PredFunctor5(), ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED5(PredFunctor5(), Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED5(PredFunction5Int, n1_++, n2_++, n3_++, n4_++, n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED5(PredFunction5Bool, Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED5(PredFunctor5(), n1_++, n2_++, n3_++, n4_++, n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED5(PredFunctor5(), Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED5(PredFunction5Int, ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED5(PredFunction5Bool, Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED5(PredFunctor5(), ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED5(PredFunctor5(), Bool(++n1_), Bool(++n2_), Bool(++n3_),
+               Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED5(PredFunction5Int, n1_++, n2_++, n3_++, n4_++, n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED5(PredFunction5Bool, Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED5(PredFunctor5(), n1_++, n2_++, n3_++, n4_++, n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED5(PredFunctor5(), Bool(n1_++), Bool(n2_++), Bool(n3_++),
+                     Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunction5, ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunction5, Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunctor5(), ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunctor5(), Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT5(PredFormatFunction5, n1_++, n2_++, n3_++, n4_++,
+                            n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT5(PredFormatFunction5, Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT5(PredFormatFunctor5(), n1_++, n2_++, n3_++, n4_++,
+                            n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT5(PredFormatFunctor5(), Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunction5, ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunction5, Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunctor5(), ++n1_, ++n2_, ++n3_, ++n4_, ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunctor5(), Bool(++n1_), Bool(++n2_),
+                      Bool(++n3_), Bool(++n4_), Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT5(PredFormatFunction5, n1_++, n2_++, n3_++, n4_++,
+                            n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT5(PredFormatFunction5, Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT5(PredFormatFunctor5(), n1_++, n2_++, n3_++, n4_++,
+                            n5_++);
+        finished_ = true;
+      },
+      "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT5(PredFormatFunctor5(), Bool(n1_++), Bool(n2_++),
+                            Bool(n3_++), Bool(n4_++), Bool(n5_++));
+        finished_ = true;
+      },
+      "");
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_premature_exit_test.cc b/3rd-party/googletest/googletest/test/gtest_premature_exit_test.cc
new file mode 100644
index 0000000..1a0c5ea
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_premature_exit_test.cc
@@ -0,0 +1,128 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests that Google Test manipulates the premature-exit-detection
+// file correctly.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::internal::posix::GetEnv;
+using ::testing::internal::posix::Stat;
+using ::testing::internal::posix::StatStruct;
+
+namespace {
+
+class PrematureExitTest : public Test {
+ public:
+  // Returns true if and only if the given file exists.
+  static bool FileExists(const char* filepath) {
+    StatStruct stat;
+    return Stat(filepath, &stat) == 0;
+  }
+
+ protected:
+  PrematureExitTest() {
+    premature_exit_file_path_ = GetEnv("TEST_PREMATURE_EXIT_FILE");
+
+    // Normalize NULL to "" for ease of handling.
+    if (premature_exit_file_path_ == nullptr) {
+      premature_exit_file_path_ = "";
+    }
+  }
+
+  // Returns true if and only if the premature-exit file exists.
+  bool PrematureExitFileExists() const {
+    return FileExists(premature_exit_file_path_);
+  }
+
+  const char* premature_exit_file_path_;
+};
+
+typedef PrematureExitTest PrematureExitDeathTest;
+
+// Tests that:
+//   - the premature-exit file exists during the execution of a
+//     death test (EXPECT_DEATH*), and
+//   - a death test doesn't interfere with the main test process's
+//     handling of the premature-exit file.
+TEST_F(PrematureExitDeathTest, FileExistsDuringExecutionOfDeathTest) {
+  if (*premature_exit_file_path_ == '\0') {
+    return;
+  }
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        // If the file exists, crash the process such that the main test
+        // process will catch the (expected) crash and report a success;
+        // otherwise don't crash, which will cause the main test process
+        // to report that the death test has failed.
+        if (PrematureExitFileExists()) {
+          exit(1);
+        }
+      },
+      "");
+}
+
+// Tests that the premature-exit file exists during the execution of a
+// normal (non-death) test.
+TEST_F(PrematureExitTest, PrematureExitFileExistsDuringTestExecution) {
+  if (*premature_exit_file_path_ == '\0') {
+    return;
+  }
+
+  EXPECT_TRUE(PrematureExitFileExists())
+      << " file " << premature_exit_file_path_
+      << " should exist during test execution, but doesn't.";
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+  const int exit_code = RUN_ALL_TESTS();
+
+  // Test that the premature-exit file is deleted upon return from
+  // RUN_ALL_TESTS().
+  const char* const filepath = GetEnv("TEST_PREMATURE_EXIT_FILE");
+  if (filepath != nullptr && *filepath != '\0') {
+    if (PrematureExitTest::FileExists(filepath)) {
+      printf(
+          "File %s shouldn't exist after the test program finishes, but does.",
+          filepath);
+      return 1;
+    }
+  }
+
+  return exit_code;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_prod_test.cc b/3rd-party/googletest/googletest/test/gtest_prod_test.cc
new file mode 100644
index 0000000..ede81a0
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_prod_test.cc
@@ -0,0 +1,56 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Unit test for gtest_prod.h.
+
+#include "production.h"
+#include "gtest/gtest.h"
+
+// Tests that private members can be accessed from a TEST declared as
+// a friend of the class.
+TEST(PrivateCodeTest, CanAccessPrivateMembers) {
+  PrivateCode a;
+  EXPECT_EQ(0, a.x_);
+
+  a.set_x(1);
+  EXPECT_EQ(1, a.x_);
+}
+
+typedef testing::Test PrivateCodeFixtureTest;
+
+// Tests that private members can be accessed from a TEST_F declared
+// as a friend of the class.
+TEST_F(PrivateCodeFixtureTest, CanAccessPrivateMembers) {
+  PrivateCode a;
+  EXPECT_EQ(0, a.x_);
+
+  a.set_x(2);
+  EXPECT_EQ(2, a.x_);
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_repeat_test.cc b/3rd-party/googletest/googletest/test/gtest_repeat_test.cc
new file mode 100644
index 0000000..55103d0
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_repeat_test.cc
@@ -0,0 +1,220 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests the --gtest_repeat=number flag.
+
+#include <stdlib.h>
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+namespace {
+
+// We need this when we are testing Google Test itself and therefore
+// cannot use Google Test assertions.
+#define GTEST_CHECK_INT_EQ_(expected, actual)                      \
+  do {                                                             \
+    const int expected_val = (expected);                           \
+    const int actual_val = (actual);                               \
+    if (::testing::internal::IsTrue(expected_val != actual_val)) { \
+      ::std::cout << "Value of: " #actual "\n"                     \
+                  << "  Actual: " << actual_val << "\n"            \
+                  << "Expected: " #expected "\n"                   \
+                  << "Which is: " << expected_val << "\n";         \
+      ::testing::internal::posix::Abort();                         \
+    }                                                              \
+  } while (::testing::internal::AlwaysFalse())
+
+// Used for verifying that global environment set-up and tear-down are
+// inside the --gtest_repeat loop.
+
+int g_environment_set_up_count = 0;
+int g_environment_tear_down_count = 0;
+
+class MyEnvironment : public testing::Environment {
+ public:
+  void SetUp() override { g_environment_set_up_count++; }
+  void TearDown() override { g_environment_tear_down_count++; }
+};
+
+// A test that should fail.
+
+int g_should_fail_count = 0;
+
+TEST(FooTest, ShouldFail) {
+  g_should_fail_count++;
+  EXPECT_EQ(0, 1) << "Expected failure.";
+}
+
+// A test that should pass.
+
+int g_should_pass_count = 0;
+
+TEST(FooTest, ShouldPass) { g_should_pass_count++; }
+
+// A test that contains a thread-safe death test and a fast death
+// test.  It should pass.
+
+int g_death_test_count = 0;
+
+TEST(BarDeathTest, ThreadSafeAndFast) {
+  g_death_test_count++;
+
+  GTEST_FLAG_SET(death_test_style, "threadsafe");
+  EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
+
+  GTEST_FLAG_SET(death_test_style, "fast");
+  EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
+}
+
+int g_param_test_count = 0;
+
+const int kNumberOfParamTests = 10;
+
+class MyParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(MyParamTest, ShouldPass) {
+  GTEST_CHECK_INT_EQ_(g_param_test_count % kNumberOfParamTests, GetParam());
+  g_param_test_count++;
+}
+INSTANTIATE_TEST_SUITE_P(MyParamSequence, MyParamTest,
+                         testing::Range(0, kNumberOfParamTests));
+
+// Resets the count for each test.
+void ResetCounts() {
+  g_environment_set_up_count = 0;
+  g_environment_tear_down_count = 0;
+  g_should_fail_count = 0;
+  g_should_pass_count = 0;
+  g_death_test_count = 0;
+  g_param_test_count = 0;
+  testing::AddGlobalTestEnvironment(new MyEnvironment);
+}
+
+// Checks that the count for each test is expected.
+void CheckCounts(int expected) {
+  GTEST_CHECK_INT_EQ_(expected, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(expected, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(expected, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(expected, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(expected, g_death_test_count);
+  GTEST_CHECK_INT_EQ_(expected * kNumberOfParamTests, g_param_test_count);
+}
+
+// Tests the behavior of Google Test when --gtest_repeat is not specified.
+void TestRepeatUnspecified() {
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
+  CheckCounts(1);
+}
+
+// Tests the behavior of Google Test when --gtest_repeat has the given value.
+void TestRepeat(int repeat) {
+  GTEST_FLAG_SET(repeat, repeat);
+  GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(repeat > 0 ? 1 : 0, RUN_ALL_TESTS());
+  CheckCounts(repeat);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies an empty
+// set of tests.
+void TestRepeatWithEmptyFilter(int repeat) {
+  GTEST_FLAG_SET(repeat, repeat);
+  GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+  GTEST_FLAG_SET(filter, "None");
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
+  CheckCounts(0);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies a set of
+// successful tests.
+void TestRepeatWithFilterForSuccessfulTests(int repeat) {
+  GTEST_FLAG_SET(repeat, repeat);
+  GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+  GTEST_FLAG_SET(filter, "*-*ShouldFail");
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(0, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_death_test_count);
+  GTEST_CHECK_INT_EQ_(repeat * kNumberOfParamTests, g_param_test_count);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies a set of
+// failed tests.
+void TestRepeatWithFilterForFailedTests(int repeat) {
+  GTEST_FLAG_SET(repeat, repeat);
+  GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+  GTEST_FLAG_SET(filter, "*ShouldFail");
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(0, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(0, g_death_test_count);
+  GTEST_CHECK_INT_EQ_(0, g_param_test_count);
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  TestRepeatUnspecified();
+  TestRepeat(0);
+  TestRepeat(1);
+  TestRepeat(5);
+
+  TestRepeatWithEmptyFilter(2);
+  TestRepeatWithEmptyFilter(3);
+
+  TestRepeatWithFilterForSuccessfulTests(3);
+
+  TestRepeatWithFilterForFailedTests(4);
+
+  // It would be nice to verify that the tests indeed loop forever
+  // when GTEST_FLAG(repeat) is negative, but this test will be quite
+  // complicated to write.  Since this flag is for interactive
+  // debugging only and doesn't affect the normal test result, such a
+  // test would be an overkill.
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_skip_check_output_test.py b/3rd-party/googletest/googletest/test/gtest_skip_check_output_test.py
new file mode 100755
index 0000000..b30a165
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_skip_check_output_test.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 Google LLC.  All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Tests Google Test's gtest skip in environment setup  behavior.
+
+This script invokes gtest_skip_in_environment_setup_test_ and verifies its
+output.
+"""
+
+import re
+
+from googletest.test import gtest_test_utils
+
+# Path to the gtest_skip_in_environment_setup_test binary
+EXE_PATH = gtest_test_utils.GetTestExecutablePath('gtest_skip_test')
+
+OUTPUT = gtest_test_utils.Subprocess([EXE_PATH]).output
+
+
+# Test.
+class SkipEntireEnvironmentTest(gtest_test_utils.TestCase):
+
+  def testSkipEntireEnvironmentTest(self):
+    self.assertIn('Skipped\nskipping single test\n', OUTPUT)
+    skip_fixture = 'Skipped\nskipping all tests for this fixture\n'
+    self.assertIsNotNone(
+        re.search(skip_fixture + '.*' + skip_fixture, OUTPUT, flags=re.DOTALL),
+        repr(OUTPUT),
+    )
+    self.assertNotIn('FAILED', OUTPUT)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_skip_environment_check_output_test.py b/3rd-party/googletest/googletest/test/gtest_skip_environment_check_output_test.py
new file mode 100755
index 0000000..388a4e9
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_skip_environment_check_output_test.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 Google LLC.  All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Tests Google Test's gtest skip in environment setup  behavior.
+
+This script invokes gtest_skip_in_environment_setup_test_ and verifies its
+output.
+"""
+
+from googletest.test import gtest_test_utils
+
+# Path to the gtest_skip_in_environment_setup_test binary
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_skip_in_environment_setup_test'
+)
+
+OUTPUT = gtest_test_utils.Subprocess([EXE_PATH]).output
+
+
+# Test.
+class SkipEntireEnvironmentTest(gtest_test_utils.TestCase):
+
+  def testSkipEntireEnvironmentTest(self):
+    self.assertIn('Skipping the entire environment', OUTPUT)
+    self.assertNotIn('FAILED', OUTPUT)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_skip_in_environment_setup_test.cc b/3rd-party/googletest/googletest/test/gtest_skip_in_environment_setup_test.cc
new file mode 100644
index 0000000..5f21c27
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_skip_in_environment_setup_test.cc
@@ -0,0 +1,50 @@
+// Copyright 2019, Google LLC.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google LLC. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This test verifies that skipping in the environment results in the
+// testcases being skipped.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+
+class SetupEnvironment : public testing::Environment {
+ public:
+  void SetUp() override { GTEST_SKIP() << "Skipping the entire environment"; }
+};
+
+TEST(Test, AlwaysFails) { EXPECT_EQ(true, false); }
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  testing::AddGlobalTestEnvironment(new SetupEnvironment());
+
+  return RUN_ALL_TESTS();
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_skip_test.cc b/3rd-party/googletest/googletest/test/gtest_skip_test.cc
new file mode 100644
index 0000000..e1b8d65
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_skip_test.cc
@@ -0,0 +1,51 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: arseny.aprelev@gmail.com (Arseny Aprelev)
+//
+
+#include "gtest/gtest.h"
+
+using ::testing::Test;
+
+TEST(SkipTest, DoesSkip) {
+  GTEST_SKIP() << "skipping single test";
+  EXPECT_EQ(0, 1);
+}
+
+class Fixture : public Test {
+ protected:
+  void SetUp() override {
+    GTEST_SKIP() << "skipping all tests for this fixture";
+  }
+};
+
+TEST_F(Fixture, SkipsOneTest) { EXPECT_EQ(5, 7); }
+
+TEST_F(Fixture, SkipsAnotherTest) { EXPECT_EQ(99, 100); }
diff --git a/3rd-party/googletest/googletest/test/gtest_sole_header_test.cc b/3rd-party/googletest/googletest/test/gtest_sole_header_test.cc
new file mode 100644
index 0000000..e8e22a8
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_sole_header_test.cc
@@ -0,0 +1,54 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// This test verifies that it's possible to use Google Test by including
+// the gtest.h header file alone.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+void Subroutine() { EXPECT_EQ(42, 42); }
+
+TEST(NoFatalFailureTest, ExpectNoFatalFailure) {
+  EXPECT_NO_FATAL_FAILURE(;);
+  EXPECT_NO_FATAL_FAILURE(SUCCEED());
+  EXPECT_NO_FATAL_FAILURE(Subroutine());
+  EXPECT_NO_FATAL_FAILURE({ SUCCEED(); });
+}
+
+TEST(NoFatalFailureTest, AssertNoFatalFailure) {
+  ASSERT_NO_FATAL_FAILURE(;);
+  ASSERT_NO_FATAL_FAILURE(SUCCEED());
+  ASSERT_NO_FATAL_FAILURE(Subroutine());
+  ASSERT_NO_FATAL_FAILURE({ SUCCEED(); });
+}
+
+}  // namespace
diff --git a/3rd-party/googletest/googletest/test/gtest_stress_test.cc b/3rd-party/googletest/googletest/test/gtest_stress_test.cc
new file mode 100644
index 0000000..af8e757
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_stress_test.cc
@@ -0,0 +1,245 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests that SCOPED_TRACE() and various Google Test assertions can be
+// used in a large number of threads concurrently.
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "src/gtest-internal-inl.h"
+
+#ifdef GTEST_IS_THREADSAFE
+
+namespace testing {
+namespace {
+
+using internal::Notification;
+using internal::TestPropertyKeyIs;
+using internal::ThreadWithParam;
+
+// In order to run tests in this file, for platforms where Google Test is
+// thread safe, implement ThreadWithParam. See the description of its API
+// in gtest-port.h, where it is defined for already supported platforms.
+
+// How many threads to create?
+const int kThreadCount = 50;
+
+std::string IdToKey(int id, const char* suffix) {
+  Message key;
+  key << "key_" << id << "_" << suffix;
+  return key.GetString();
+}
+
+std::string IdToString(int id) {
+  Message id_message;
+  id_message << id;
+  return id_message.GetString();
+}
+
+void ExpectKeyAndValueWereRecordedForId(
+    const std::vector<TestProperty>& properties, int id, const char* suffix) {
+  TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str());
+  const std::vector<TestProperty>::const_iterator property =
+      std::find_if(properties.begin(), properties.end(), matches_key);
+  ASSERT_TRUE(property != properties.end())
+      << "expecting " << suffix << " value for id " << id;
+  EXPECT_STREQ(IdToString(id).c_str(), property->value());
+}
+
+// Calls a large number of Google Test assertions, where exactly one of them
+// will fail.
+void ManyAsserts(int id) {
+  GTEST_LOG_(INFO) << "Thread #" << id << " running...";
+
+  SCOPED_TRACE(Message() << "Thread #" << id);
+
+  for (int i = 0; i < kThreadCount; i++) {
+    SCOPED_TRACE(Message() << "Iteration #" << i);
+
+    // A bunch of assertions that should succeed.
+    EXPECT_TRUE(true);
+    ASSERT_FALSE(false) << "This shouldn't fail.";
+    EXPECT_STREQ("a", "a");
+    ASSERT_LE(5, 6);
+    EXPECT_EQ(i, i) << "This shouldn't fail.";
+
+    // RecordProperty() should interact safely with other threads as well.
+    // The shared_key forces property updates.
+    Test::RecordProperty(IdToKey(id, "string").c_str(), IdToString(id).c_str());
+    Test::RecordProperty(IdToKey(id, "int").c_str(), id);
+    Test::RecordProperty("shared_key", IdToString(id).c_str());
+
+    // This assertion should fail kThreadCount times per thread.  It
+    // is for testing whether Google Test can handle failed assertions in a
+    // multi-threaded context.
+    EXPECT_LT(i, 0) << "This should always fail.";
+  }
+}
+
+void CheckTestFailureCount(int expected_failures) {
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult* const result = info->result();
+  GTEST_CHECK_(expected_failures == result->total_part_count())
+      << "Logged " << result->total_part_count() << " failures "
+      << " vs. " << expected_failures << " expected";
+}
+
+// Tests using SCOPED_TRACE() and Google Test assertions in many threads
+// concurrently.
+TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
+  {
+    std::unique_ptr<ThreadWithParam<int> > threads[kThreadCount];
+    Notification threads_can_start;
+    for (int i = 0; i != kThreadCount; i++)
+      threads[i] = std::make_unique<ThreadWithParam<int>>(&ManyAsserts, i,
+                                                          &threads_can_start);
+
+    threads_can_start.Notify();
+
+    // Blocks until all the threads are done.
+    for (int i = 0; i != kThreadCount; i++) threads[i]->Join();
+  }
+
+  // Ensures that kThreadCount*kThreadCount failures have been reported.
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult* const result = info->result();
+
+  std::vector<TestProperty> properties;
+  // We have no access to the TestResult's list of properties but we can
+  // copy them one by one.
+  for (int i = 0; i < result->test_property_count(); ++i)
+    properties.push_back(result->GetTestProperty(i));
+
+  EXPECT_EQ(kThreadCount * 2 + 1, result->test_property_count())
+      << "String and int values recorded on each thread, "
+      << "as well as one shared_key";
+  for (int i = 0; i < kThreadCount; ++i) {
+    ExpectKeyAndValueWereRecordedForId(properties, i, "string");
+    ExpectKeyAndValueWereRecordedForId(properties, i, "int");
+  }
+  CheckTestFailureCount(kThreadCount * kThreadCount);
+}
+
+void FailingThread(bool is_fatal) {
+  if (is_fatal)
+    FAIL() << "Fatal failure in some other thread. "
+           << "(This failure is expected.)";
+  else
+    ADD_FAILURE() << "Non-fatal failure in some other thread. "
+                  << "(This failure is expected.)";
+}
+
+void GenerateFatalFailureInAnotherThread(bool is_fatal) {
+  ThreadWithParam<bool> thread(&FailingThread, is_fatal, nullptr);
+  thread.Join();
+}
+
+TEST(NoFatalFailureTest, ExpectNoFatalFailureIgnoresFailuresInOtherThreads) {
+  EXPECT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
+  // We should only have one failure (the one from
+  // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
+  // should succeed.
+  CheckTestFailureCount(1);
+}
+
+void AssertNoFatalFailureIgnoresFailuresInOtherThreads() {
+  ASSERT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
+}
+TEST(NoFatalFailureTest, AssertNoFatalFailureIgnoresFailuresInOtherThreads) {
+  // Using a subroutine, to make sure, that the test continues.
+  AssertNoFatalFailureIgnoresFailuresInOtherThreads();
+  // We should only have one failure (the one from
+  // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
+  // should succeed.
+  CheckTestFailureCount(1);
+}
+
+TEST(FatalFailureTest, ExpectFatalFailureIgnoresFailuresInOtherThreads) {
+  // This statement should fail, since the current thread doesn't generate a
+  // fatal failure, only another one does.
+  EXPECT_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true), "expected");
+  CheckTestFailureCount(2);
+}
+
+TEST(FatalFailureOnAllThreadsTest, ExpectFatalFailureOnAllThreads) {
+  // This statement should succeed, because failures in all threads are
+  // considered.
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(GenerateFatalFailureInAnotherThread(true),
+                                      "expected");
+  CheckTestFailureCount(0);
+  // We need to add a failure, because main() checks that there are failures.
+  // But when only this test is run, we shouldn't have any failures.
+  ADD_FAILURE() << "This is an expected non-fatal failure.";
+}
+
+TEST(NonFatalFailureTest, ExpectNonFatalFailureIgnoresFailuresInOtherThreads) {
+  // This statement should fail, since the current thread doesn't generate a
+  // fatal failure, only another one does.
+  EXPECT_NONFATAL_FAILURE(GenerateFatalFailureInAnotherThread(false),
+                          "expected");
+  CheckTestFailureCount(2);
+}
+
+TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) {
+  // This statement should succeed, because failures in all threads are
+  // considered.
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      GenerateFatalFailureInAnotherThread(false), "expected");
+  CheckTestFailureCount(0);
+  // We need to add a failure, because main() checks that there are failures,
+  // But when only this test is run, we shouldn't have any failures.
+  ADD_FAILURE() << "This is an expected non-fatal failure.";
+}
+
+}  // namespace
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  const int result = RUN_ALL_TESTS();  // Expected to fail.
+  GTEST_CHECK_(result == 1) << "RUN_ALL_TESTS() did not fail as expected";
+
+  printf("\nPASS\n");
+  return 0;
+}
+
+#else
+TEST(StressTest,
+     DISABLED_ThreadSafetyTestsAreSkippedWhenGoogleTestIsNotThreadSafe) {}
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+#endif  // GTEST_IS_THREADSAFE
diff --git a/3rd-party/googletest/googletest/test/gtest_test_macro_stack_footprint_test.cc b/3rd-party/googletest/googletest/test/gtest_test_macro_stack_footprint_test.cc
new file mode 100644
index 0000000..45f368b
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_test_macro_stack_footprint_test.cc
@@ -0,0 +1,89 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Each TEST() expands to some static registration logic.  GCC puts all
+// such static initialization logic for a translation unit in a common,
+// internal function.  Since Google's build system restricts how much
+// stack space a function can use, there's a limit on how many TEST()s
+// one can put in a single C++ test file.  This test ensures that a large
+// number of TEST()s can be defined in the same translation unit.
+
+#include "gtest/gtest.h"
+
+// This macro defines 10 dummy tests.
+#define TEN_TESTS_(test_case_name) \
+  TEST(test_case_name, T0) {}      \
+  TEST(test_case_name, T1) {}      \
+  TEST(test_case_name, T2) {}      \
+  TEST(test_case_name, T3) {}      \
+  TEST(test_case_name, T4) {}      \
+  TEST(test_case_name, T5) {}      \
+  TEST(test_case_name, T6) {}      \
+  TEST(test_case_name, T7) {}      \
+  TEST(test_case_name, T8) {}      \
+  TEST(test_case_name, T9) {}
+
+// This macro defines 100 dummy tests.
+#define HUNDRED_TESTS_(test_case_name_prefix) \
+  TEN_TESTS_(test_case_name_prefix##0)        \
+  TEN_TESTS_(test_case_name_prefix##1)        \
+  TEN_TESTS_(test_case_name_prefix##2)        \
+  TEN_TESTS_(test_case_name_prefix##3)        \
+  TEN_TESTS_(test_case_name_prefix##4)        \
+  TEN_TESTS_(test_case_name_prefix##5)        \
+  TEN_TESTS_(test_case_name_prefix##6)        \
+  TEN_TESTS_(test_case_name_prefix##7)        \
+  TEN_TESTS_(test_case_name_prefix##8)        \
+  TEN_TESTS_(test_case_name_prefix##9)
+
+// This macro defines 1000 dummy tests.
+#define THOUSAND_TESTS_(test_case_name_prefix) \
+  HUNDRED_TESTS_(test_case_name_prefix##0)     \
+  HUNDRED_TESTS_(test_case_name_prefix##1)     \
+  HUNDRED_TESTS_(test_case_name_prefix##2)     \
+  HUNDRED_TESTS_(test_case_name_prefix##3)     \
+  HUNDRED_TESTS_(test_case_name_prefix##4)     \
+  HUNDRED_TESTS_(test_case_name_prefix##5)     \
+  HUNDRED_TESTS_(test_case_name_prefix##6)     \
+  HUNDRED_TESTS_(test_case_name_prefix##7)     \
+  HUNDRED_TESTS_(test_case_name_prefix##8)     \
+  HUNDRED_TESTS_(test_case_name_prefix##9)
+
+// Ensures that we can define 1000 TEST()s in the same translation
+// unit.
+THOUSAND_TESTS_(T)
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // We don't actually need to run the dummy tests - the purpose is to
+  // ensure that they compile.
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_test_utils.py b/3rd-party/googletest/googletest/test/gtest_test_utils.py
new file mode 100755
index 0000000..964fa9f
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_test_utils.py
@@ -0,0 +1,262 @@
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for Google C++ Testing and Mocking Framework."""
+# Suppresses the 'Import not at the top of the file' lint complaint.
+# pylint: disable=g-import-not-at-top
+
+import os
+import subprocess
+import sys
+
+IS_WINDOWS = os.name == 'nt'
+IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
+IS_OS2 = os.name == 'os2'
+
+import atexit
+import shutil
+import tempfile
+import unittest as _test_module
+# pylint: enable=g-import-not-at-top
+
+GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
+
+# The environment variable for specifying the path to the premature-exit file.
+PREMATURE_EXIT_FILE_ENV_VAR = 'TEST_PREMATURE_EXIT_FILE'
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets/unsets an environment variable to a given value."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+# Here we expose a class from a particular module, depending on the
+# environment.
+TestCase = _test_module.TestCase
+
+# Initially maps a flag to its default value. After
+# _ParseAndStripGTestFlags() is called, maps a flag to its actual value.
+_flag_map = {
+    'source_dir': os.path.dirname(sys.argv[0]),
+    'build_dir': os.path.dirname(sys.argv[0]),
+}
+_gtest_flags_are_parsed = False
+
+
+def _ParseAndStripGTestFlags(argv):
+  """Parses and strips Google Test flags from argv.  This is idempotent."""
+
+  global _gtest_flags_are_parsed
+  if _gtest_flags_are_parsed:
+    return
+
+  _gtest_flags_are_parsed = True
+  for flag in _flag_map:
+    # The environment variable overrides the default value.
+    if flag.upper() in os.environ:
+      _flag_map[flag] = os.environ[flag.upper()]
+
+    # The command line flag overrides the environment variable.
+    i = 1  # Skips the program name.
+    while i < len(argv):
+      prefix = '--' + flag + '='
+      if argv[i].startswith(prefix):
+        _flag_map[flag] = argv[i][len(prefix) :]
+        del argv[i]
+        break
+      else:
+        # We don't increment i in case we just found a --gtest_* flag
+        # and removed it from argv.
+        i += 1
+
+
+def GetFlag(flag):
+  """Returns the value of the given flag."""
+
+  # In case GetFlag() is called before Main(), we always call
+  # _ParseAndStripGTestFlags() here to make sure the --gtest_* flags
+  # are parsed.
+  _ParseAndStripGTestFlags(sys.argv)
+
+  return _flag_map[flag]
+
+
+def GetSourceDir():
+  """Returns the absolute path of the directory where the .py files are."""
+
+  return os.path.abspath(GetFlag('source_dir'))
+
+
+def GetBuildDir():
+  """Returns the absolute path of the directory where the test binaries are."""
+
+  return os.path.abspath(GetFlag('build_dir'))
+
+
+_temp_dir = None
+
+def _RemoveTempDir():
+  if _temp_dir:
+    shutil.rmtree(_temp_dir, ignore_errors=True)
+
+atexit.register(_RemoveTempDir)
+
+
+def GetTempDir():
+  global _temp_dir
+  if not _temp_dir:
+    _temp_dir = tempfile.mkdtemp()
+  return _temp_dir
+
+
+def GetTestExecutablePath(executable_name, build_dir=None):
+  """Returns the absolute path of the test binary given its name.
+
+  The function will print a message and abort the program if the resulting file
+  doesn't exist.
+
+  Args:
+    executable_name: name of the test binary that the test script runs.
+    build_dir:       directory where to look for executables, by default the
+      result of GetBuildDir().
+
+  Returns:
+    The absolute path of the test binary.
+  """
+
+  path = os.path.abspath(
+      os.path.join(build_dir or GetBuildDir(), executable_name)
+  )
+  if (IS_WINDOWS or IS_CYGWIN or IS_OS2) and not path.endswith('.exe'):
+    path += '.exe'
+
+  if not os.path.exists(path):
+    message = (
+        'Unable to find the test binary "%s". Please make sure to provide\n'
+        'a path to the binary via the --build_dir flag or the BUILD_DIR\n'
+        'environment variable.' % path
+    )
+    print(message, file=sys.stderr)
+    sys.exit(1)
+
+  return path
+
+
+def GetExitStatus(exit_code):
+  """Returns the argument to exit(), or -1 if exit() wasn't called.
+
+  Args:
+    exit_code: the result value of os.system(command).
+  """
+
+  if os.name == 'nt':
+    # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns
+    # the argument to exit() directly.
+    return exit_code
+  else:
+    # On Unix, os.WEXITSTATUS() must be used to extract the exit status
+    # from the result of os.system().
+    if os.WIFEXITED(exit_code):
+      return os.WEXITSTATUS(exit_code)
+    else:
+      return -1
+
+
+class Subprocess:
+
+  def __init__(self, command, working_dir=None, capture_stderr=True, env=None):
+    """Changes into a specified directory, if provided, and executes a command.
+
+    Restores the old directory afterwards.
+
+    Args:
+      command:        The command to run, in the form of sys.argv.
+      working_dir:    The directory to change into.
+      capture_stderr: Determines whether to capture stderr in the output member
+        or to discard it.
+      env:            Dictionary with environment to pass to the subprocess.
+
+    Returns:
+      An object that represents outcome of the executed process. It has the
+      following attributes:
+        terminated_by_signal   True if and only if the child process has been
+                               terminated by a signal.
+        exited                 True if and only if the child process exited
+                               normally.
+        exit_code              The code with which the child process exited.
+        output                 Child process's stdout and stderr output
+                               combined in a string.
+    """
+
+    if capture_stderr:
+      stderr = subprocess.STDOUT
+    else:
+      stderr = subprocess.PIPE
+
+    p = subprocess.Popen(
+        command,
+        stdout=subprocess.PIPE,
+        stderr=stderr,
+        cwd=working_dir,
+        universal_newlines=True,
+        env=env,
+    )
+    # communicate returns a tuple with the file object for the child's
+    # output.
+    self.output = p.communicate()[0]
+    self._return_code = p.returncode
+
+    if bool(self._return_code & 0x80000000):
+      self.terminated_by_signal = True
+      self.exited = False
+    else:
+      self.terminated_by_signal = False
+      self.exited = True
+      self.exit_code = self._return_code
+
+
+def Main():
+  """Runs the unit test."""
+
+  # We must call _ParseAndStripGTestFlags() before calling
+  # unittest.main().  Otherwise the latter will be confused by the
+  # --gtest_* flags.
+  _ParseAndStripGTestFlags(sys.argv)
+  # The tested binaries should not be writing XML output files unless the
+  # script explicitly instructs them to.
+  if GTEST_OUTPUT_VAR_NAME in os.environ:
+    del os.environ[GTEST_OUTPUT_VAR_NAME]
+
+  _test_module.main()
diff --git a/3rd-party/googletest/googletest/test/gtest_testbridge_test.py b/3rd-party/googletest/googletest/test/gtest_testbridge_test.py
new file mode 100755
index 0000000..0d58758
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_testbridge_test.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 Google LLC. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Verifies that Google Test uses filter provided via testbridge."""
+
+import os
+
+from googletest.test import gtest_test_utils
+
+binary_name = 'gtest_testbridge_test_'
+COMMAND = gtest_test_utils.GetTestExecutablePath(binary_name)
+TESTBRIDGE_NAME = 'TESTBRIDGE_TEST_ONLY'
+
+
+def Assert(condition):
+  if not condition:
+    raise AssertionError
+
+
+class GTestTestFilterTest(gtest_test_utils.TestCase):
+
+  def testTestExecutionIsFiltered(self):
+    """Tests that the test filter is picked up from the testbridge env var."""
+    subprocess_env = os.environ.copy()
+
+    subprocess_env[TESTBRIDGE_NAME] = '*.TestThatSucceeds'
+    p = gtest_test_utils.Subprocess(COMMAND, env=subprocess_env)
+
+    self.assertEqual(0, p.exit_code)
+
+    Assert('filter = *.TestThatSucceeds' in p.output)
+    Assert('[       OK ] TestFilterTest.TestThatSucceeds' in p.output)
+    Assert('[  PASSED  ] 1 test.' in p.output)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_testbridge_test_.cc b/3rd-party/googletest/googletest/test/gtest_testbridge_test_.cc
new file mode 100644
index 0000000..c2c000d
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_testbridge_test_.cc
@@ -0,0 +1,42 @@
+// Copyright 2018, Google LLC.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This program is meant to be run by gtest_test_filter_test.py.  Do not run
+// it directly.
+
+#include "gtest/gtest.h"
+
+// These tests are used to detect if filtering is working. Only
+// 'TestThatSucceeds' should ever run.
+
+TEST(TestFilterTest, TestThatSucceeds) {}
+
+TEST(TestFilterTest, TestThatFails) {
+  ASSERT_TRUE(false) << "This test should never be run.";
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc b/3rd-party/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc
new file mode 100644
index 0000000..25d7c79
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc
@@ -0,0 +1,90 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests Google Test's throw-on-failure mode with exceptions enabled.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdexcept>
+
+#include "gtest/gtest.h"
+
+// Prints the given failure message and exits the program with
+// non-zero.  We use this instead of a Google Test assertion to
+// indicate a failure, as the latter is been tested and cannot be
+// relied on.
+void Fail(const char* msg) {
+  printf("FAILURE: %s\n", msg);
+  fflush(stdout);
+  exit(1);
+}
+
+// Tests that an assertion failure throws a subclass of
+// std::runtime_error.
+void TestFailureThrowsRuntimeError() {
+  GTEST_FLAG_SET(throw_on_failure, true);
+
+  // A successful assertion shouldn't throw.
+  try {
+    EXPECT_EQ(3, 3);
+  } catch (...) {
+    Fail("A successful assertion wrongfully threw.");
+  }
+
+  // A failed assertion should throw a subclass of std::runtime_error.
+  try {
+    EXPECT_EQ(2, 3) << "Expected failure";
+  } catch (const std::runtime_error& e) {
+    if (strstr(e.what(), "Expected failure") != nullptr) return;
+
+    printf("%s",
+           "A failed assertion did throw an exception of the right type, "
+           "but the message is incorrect.  Instead of containing \"Expected "
+           "failure\", it is:\n");
+    Fail(e.what());
+  } catch (...) {
+    Fail("A failed assertion threw the wrong type of exception.");
+  }
+  Fail("A failed assertion should've thrown but didn't.");
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // We want to ensure that people can use Google Test assertions in
+  // other testing frameworks, as long as they initialize Google Test
+  // properly and set the thrown-on-failure mode.  Therefore, we don't
+  // use Google Test's constructs for defining and running tests
+  // (e.g. TEST and RUN_ALL_TESTS) here.
+
+  TestFailureThrowsRuntimeError();
+  return 0;
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_unittest.cc b/3rd-party/googletest/googletest/test/gtest_unittest.cc
new file mode 100644
index 0000000..5ded865
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_unittest.cc
@@ -0,0 +1,7775 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Tests for Google Test itself.  This verifies that the basic constructs of
+// Google Test work.
+
+#include "gtest/gtest.h"
+
+// Verifies that the command line flag variables can be accessed in
+// code once "gtest.h" has been #included.
+// Do not move it after other gtest #includes.
+TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
+  bool dummy =
+      GTEST_FLAG_GET(also_run_disabled_tests) ||
+      GTEST_FLAG_GET(break_on_failure) || GTEST_FLAG_GET(catch_exceptions) ||
+      GTEST_FLAG_GET(color) != "unknown" || GTEST_FLAG_GET(fail_fast) ||
+      GTEST_FLAG_GET(filter) != "unknown" || GTEST_FLAG_GET(list_tests) ||
+      GTEST_FLAG_GET(output) != "unknown" || GTEST_FLAG_GET(brief) ||
+      GTEST_FLAG_GET(print_time) || GTEST_FLAG_GET(random_seed) ||
+      GTEST_FLAG_GET(repeat) > 0 ||
+      GTEST_FLAG_GET(recreate_environments_when_repeating) ||
+      GTEST_FLAG_GET(show_internal_stack_frames) || GTEST_FLAG_GET(shuffle) ||
+      GTEST_FLAG_GET(stack_trace_depth) > 0 ||
+      GTEST_FLAG_GET(stream_result_to) != "unknown" ||
+      GTEST_FLAG_GET(throw_on_failure);
+  EXPECT_TRUE(dummy || !dummy);  // Suppresses warning that dummy is unused.
+}
+
+#include <limits.h>  // For INT_MAX.
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest-spi.h"
+#include "src/gtest-internal-inl.h"
+
+struct ConvertibleGlobalType {
+  // The inner enable_if is to ensure invoking is_constructible doesn't fail.
+  // The outer enable_if is to ensure the overload resolution doesn't encounter
+  // an ambiguity.
+  template <
+      class T,
+      std::enable_if_t<
+          false, std::enable_if_t<std::is_constructible<T>::value, int>> = 0>
+  operator T() const;  // NOLINT(google-explicit-constructor)
+};
+void operator<<(ConvertibleGlobalType&, int);
+static_assert(sizeof(decltype(std::declval<ConvertibleGlobalType&>()
+                              << 1)(*)()) > 0,
+              "error in operator<< overload resolution");
+
+namespace testing {
+namespace internal {
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+class StreamingListenerTest : public Test {
+ public:
+  class FakeSocketWriter : public StreamingListener::AbstractSocketWriter {
+   public:
+    // Sends a string to the socket.
+    void Send(const std::string& message) override { output_ += message; }
+
+    std::string output_;
+  };
+
+  StreamingListenerTest()
+      : fake_sock_writer_(new FakeSocketWriter),
+        streamer_(fake_sock_writer_),
+        test_info_obj_("FooTest", "Bar", nullptr, nullptr,
+                       CodeLocation(__FILE__, __LINE__), nullptr, nullptr) {}
+
+ protected:
+  std::string* output() { return &(fake_sock_writer_->output_); }
+
+  FakeSocketWriter* const fake_sock_writer_;
+  StreamingListener streamer_;
+  UnitTest unit_test_;
+  TestInfo test_info_obj_;  // The name test_info_ was taken by testing::Test.
+};
+
+TEST_F(StreamingListenerTest, OnTestProgramEnd) {
+  *output() = "";
+  streamer_.OnTestProgramEnd(unit_test_);
+  EXPECT_EQ("event=TestProgramEnd&passed=1\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestIterationEnd) {
+  *output() = "";
+  streamer_.OnTestIterationEnd(unit_test_, 42);
+  EXPECT_EQ("event=TestIterationEnd&passed=1&elapsed_time=0ms\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestSuiteStart) {
+  *output() = "";
+  streamer_.OnTestSuiteStart(TestSuite("FooTest", "Bar", nullptr, nullptr));
+  EXPECT_EQ("event=TestCaseStart&name=FooTest\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestSuiteEnd) {
+  *output() = "";
+  streamer_.OnTestSuiteEnd(TestSuite("FooTest", "Bar", nullptr, nullptr));
+  EXPECT_EQ("event=TestCaseEnd&passed=1&elapsed_time=0ms\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestStart) {
+  *output() = "";
+  streamer_.OnTestStart(test_info_obj_);
+  EXPECT_EQ("event=TestStart&name=Bar\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestEnd) {
+  *output() = "";
+  streamer_.OnTestEnd(test_info_obj_);
+  EXPECT_EQ("event=TestEnd&passed=1&elapsed_time=0ms\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestPartResult) {
+  *output() = "";
+  streamer_.OnTestPartResult(TestPartResult(TestPartResult::kFatalFailure,
+                                            "foo.cc", 42, "failed=\n&%"));
+
+  // Meta characters in the failure message should be properly escaped.
+  EXPECT_EQ(
+      "event=TestPartResult&file=foo.cc&line=42&message=failed%3D%0A%26%25\n",
+      *output());
+}
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Provides access to otherwise private parts of the TestEventListeners class
+// that are needed to test it.
+class TestEventListenersAccessor {
+ public:
+  static TestEventListener* GetRepeater(TestEventListeners* listeners) {
+    return listeners->repeater();
+  }
+
+  static void SetDefaultResultPrinter(TestEventListeners* listeners,
+                                      TestEventListener* listener) {
+    listeners->SetDefaultResultPrinter(listener);
+  }
+  static void SetDefaultXmlGenerator(TestEventListeners* listeners,
+                                     TestEventListener* listener) {
+    listeners->SetDefaultXmlGenerator(listener);
+  }
+
+  static bool EventForwardingEnabled(const TestEventListeners& listeners) {
+    return listeners.EventForwardingEnabled();
+  }
+
+  static void SuppressEventForwarding(TestEventListeners* listeners) {
+    listeners->SuppressEventForwarding(true);
+  }
+};
+
+class UnitTestRecordPropertyTestHelper : public Test {
+ protected:
+  UnitTestRecordPropertyTestHelper() {}
+
+  // Forwards to UnitTest::RecordProperty() to bypass access controls.
+  void UnitTestRecordProperty(const char* key, const std::string& value) {
+    unit_test_.RecordProperty(key, value);
+  }
+
+  UnitTest unit_test_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+using testing::AssertionFailure;
+using testing::AssertionResult;
+using testing::AssertionSuccess;
+using testing::DoubleLE;
+using testing::EmptyTestEventListener;
+using testing::Environment;
+using testing::FloatLE;
+using testing::IsNotSubstring;
+using testing::IsSubstring;
+using testing::kMaxStackTraceDepth;
+using testing::Message;
+using testing::ScopedFakeTestPartResultReporter;
+using testing::StaticAssertTypeEq;
+using testing::Test;
+using testing::TestEventListeners;
+using testing::TestInfo;
+using testing::TestPartResult;
+using testing::TestPartResultArray;
+using testing::TestProperty;
+using testing::TestResult;
+using testing::TimeInMillis;
+using testing::UnitTest;
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+using testing::internal::AppendUserMessage;
+using testing::internal::ArrayAwareFind;
+using testing::internal::ArrayEq;
+using testing::internal::CodePointToUtf8;
+using testing::internal::CopyArray;
+using testing::internal::CountIf;
+using testing::internal::EqFailure;
+using testing::internal::FloatingPoint;
+using testing::internal::ForEach;
+using testing::internal::FormatEpochTimeInMillisAsIso8601;
+using testing::internal::FormatTimeInMillisAsSeconds;
+using testing::internal::GetElementOr;
+using testing::internal::GetNextRandomSeed;
+using testing::internal::GetRandomSeedFromFlag;
+using testing::internal::GetTestTypeId;
+using testing::internal::GetTimeInMillis;
+using testing::internal::GetTypeId;
+using testing::internal::GetUnitTestImpl;
+using testing::internal::GTestFlagSaver;
+using testing::internal::HasDebugStringAndShortDebugString;
+using testing::internal::Int32FromEnvOrDie;
+using testing::internal::IsContainer;
+using testing::internal::IsContainerTest;
+using testing::internal::IsNotContainer;
+using testing::internal::kMaxRandomSeed;
+using testing::internal::kTestTypeIdInGoogleTest;
+using testing::internal::NativeArray;
+using testing::internal::ParseFlag;
+using testing::internal::RelationToSourceCopy;
+using testing::internal::RelationToSourceReference;
+using testing::internal::ShouldRunTestOnShard;
+using testing::internal::ShouldShard;
+using testing::internal::ShouldUseColor;
+using testing::internal::Shuffle;
+using testing::internal::ShuffleRange;
+using testing::internal::SkipPrefix;
+using testing::internal::StreamableToString;
+using testing::internal::String;
+using testing::internal::TestEventListenersAccessor;
+using testing::internal::TestResultAccessor;
+using testing::internal::WideStringToUtf8;
+using testing::internal::edit_distance::CalculateOptimalEdits;
+using testing::internal::edit_distance::CreateUnifiedDiff;
+using testing::internal::edit_distance::EditType;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using testing::internal::CaptureStdout;
+using testing::internal::GetCapturedStdout;
+#endif
+
+#ifdef GTEST_IS_THREADSAFE
+using testing::internal::ThreadWithParam;
+#endif
+
+class TestingVector : public std::vector<int> {};
+
+::std::ostream& operator<<(::std::ostream& os, const TestingVector& vector) {
+  os << "{ ";
+  for (size_t i = 0; i < vector.size(); i++) {
+    os << vector[i] << " ";
+  }
+  os << "}";
+  return os;
+}
+
+// This line tests that we can define tests in an unnamed namespace.
+namespace {
+
+TEST(GetRandomSeedFromFlagTest, HandlesZero) {
+  const int seed = GetRandomSeedFromFlag(0);
+  EXPECT_LE(1, seed);
+  EXPECT_LE(seed, static_cast<int>(kMaxRandomSeed));
+}
+
+TEST(GetRandomSeedFromFlagTest, PreservesValidSeed) {
+  EXPECT_EQ(1, GetRandomSeedFromFlag(1));
+  EXPECT_EQ(2, GetRandomSeedFromFlag(2));
+  EXPECT_EQ(kMaxRandomSeed - 1, GetRandomSeedFromFlag(kMaxRandomSeed - 1));
+  EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
+            GetRandomSeedFromFlag(kMaxRandomSeed));
+}
+
+TEST(GetRandomSeedFromFlagTest, NormalizesInvalidSeed) {
+  const int seed1 = GetRandomSeedFromFlag(-1);
+  EXPECT_LE(1, seed1);
+  EXPECT_LE(seed1, static_cast<int>(kMaxRandomSeed));
+
+  const int seed2 = GetRandomSeedFromFlag(kMaxRandomSeed + 1);
+  EXPECT_LE(1, seed2);
+  EXPECT_LE(seed2, static_cast<int>(kMaxRandomSeed));
+}
+
+TEST(GetNextRandomSeedTest, WorksForValidInput) {
+  EXPECT_EQ(2, GetNextRandomSeed(1));
+  EXPECT_EQ(3, GetNextRandomSeed(2));
+  EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
+            GetNextRandomSeed(kMaxRandomSeed - 1));
+  EXPECT_EQ(1, GetNextRandomSeed(kMaxRandomSeed));
+
+  // We deliberately don't test GetNextRandomSeed() with invalid
+  // inputs, as that requires death tests, which are expensive.  This
+  // is fine as GetNextRandomSeed() is internal and has a
+  // straightforward definition.
+}
+
+static void ClearCurrentTestPartResults() {
+  TestResultAccessor::ClearTestPartResults(
+      GetUnitTestImpl()->current_test_result());
+}
+
+// Tests GetTypeId.
+
+TEST(GetTypeIdTest, ReturnsSameValueForSameType) {
+  EXPECT_EQ(GetTypeId<int>(), GetTypeId<int>());
+  EXPECT_EQ(GetTypeId<Test>(), GetTypeId<Test>());
+}
+
+class SubClassOfTest : public Test {};
+class AnotherSubClassOfTest : public Test {};
+
+TEST(GetTypeIdTest, ReturnsDifferentValuesForDifferentTypes) {
+  EXPECT_NE(GetTypeId<int>(), GetTypeId<const int>());
+  EXPECT_NE(GetTypeId<int>(), GetTypeId<char>());
+  EXPECT_NE(GetTypeId<int>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<SubClassOfTest>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTypeId<SubClassOfTest>());
+}
+
+// Verifies that GetTestTypeId() returns the same value, no matter it
+// is called from inside Google Test or outside of it.
+TEST(GetTestTypeIdTest, ReturnsTheSameValueInsideOrOutsideOfGoogleTest) {
+  EXPECT_EQ(kTestTypeIdInGoogleTest, GetTestTypeId());
+}
+
+// Tests CanonicalizeForStdLibVersioning.
+
+using ::testing::internal::CanonicalizeForStdLibVersioning;
+
+TEST(CanonicalizeForStdLibVersioning, LeavesUnversionedNamesUnchanged) {
+  EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::bind"));
+  EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::_"));
+  EXPECT_EQ("std::__foo", CanonicalizeForStdLibVersioning("std::__foo"));
+  EXPECT_EQ("gtl::__1::x", CanonicalizeForStdLibVersioning("gtl::__1::x"));
+  EXPECT_EQ("__1::x", CanonicalizeForStdLibVersioning("__1::x"));
+  EXPECT_EQ("::__1::x", CanonicalizeForStdLibVersioning("::__1::x"));
+}
+
+TEST(CanonicalizeForStdLibVersioning, ElidesDoubleUnderNames) {
+  EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::__1::bind"));
+  EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::__1::_"));
+
+  EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::__g::bind"));
+  EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::__g::_"));
+
+  EXPECT_EQ("std::bind",
+            CanonicalizeForStdLibVersioning("std::__google::bind"));
+  EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::__google::_"));
+}
+
+// Tests FormatTimeInMillisAsSeconds().
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsZero) {
+  EXPECT_EQ("0.", FormatTimeInMillisAsSeconds(0));
+}
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsPositiveNumber) {
+  EXPECT_EQ("0.003", FormatTimeInMillisAsSeconds(3));
+  EXPECT_EQ("0.01", FormatTimeInMillisAsSeconds(10));
+  EXPECT_EQ("0.2", FormatTimeInMillisAsSeconds(200));
+  EXPECT_EQ("1.2", FormatTimeInMillisAsSeconds(1200));
+  EXPECT_EQ("3.", FormatTimeInMillisAsSeconds(3000));
+  EXPECT_EQ("10.", FormatTimeInMillisAsSeconds(10000));
+  EXPECT_EQ("100.", FormatTimeInMillisAsSeconds(100000));
+  EXPECT_EQ("123.456", FormatTimeInMillisAsSeconds(123456));
+  EXPECT_EQ("1234567.89", FormatTimeInMillisAsSeconds(1234567890));
+}
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsNegativeNumber) {
+  EXPECT_EQ("-0.003", FormatTimeInMillisAsSeconds(-3));
+  EXPECT_EQ("-0.01", FormatTimeInMillisAsSeconds(-10));
+  EXPECT_EQ("-0.2", FormatTimeInMillisAsSeconds(-200));
+  EXPECT_EQ("-1.2", FormatTimeInMillisAsSeconds(-1200));
+  EXPECT_EQ("-3.", FormatTimeInMillisAsSeconds(-3000));
+  EXPECT_EQ("-10.", FormatTimeInMillisAsSeconds(-10000));
+  EXPECT_EQ("-100.", FormatTimeInMillisAsSeconds(-100000));
+  EXPECT_EQ("-123.456", FormatTimeInMillisAsSeconds(-123456));
+  EXPECT_EQ("-1234567.89", FormatTimeInMillisAsSeconds(-1234567890));
+}
+
+// TODO: b/287046337 - In emscripten, local time zone modification is not
+// supported.
+#if !defined(__EMSCRIPTEN__)
+// Tests FormatEpochTimeInMillisAsIso8601().  The correctness of conversion
+// for particular dates below was verified in Python using
+// datetime.datetime.fromutctimestamp(<timestamp>/1000).
+
+// FormatEpochTimeInMillisAsIso8601 depends on the local timezone, so we
+// have to set up a particular timezone to obtain predictable results.
+class FormatEpochTimeInMillisAsIso8601Test : public Test {
+ public:
+  // On Cygwin, GCC doesn't allow unqualified integer literals to exceed
+  // 32 bits, even when 64-bit integer types are available.  We have to
+  // force the constants to have a 64-bit type here.
+  static const TimeInMillis kMillisPerSec = 1000;
+
+ private:
+  void SetUp() override {
+    saved_tz_.reset();
+
+    GTEST_DISABLE_MSC_DEPRECATED_PUSH_(/* getenv: deprecated */)
+    if (const char* tz = getenv("TZ")) {
+      saved_tz_ = std::make_unique<std::string>(tz);
+    }
+    GTEST_DISABLE_MSC_DEPRECATED_POP_()
+
+    // Set the local time zone for FormatEpochTimeInMillisAsIso8601 to be
+    // a fixed time zone for reproducibility purposes.
+    SetTimeZone("UTC+00");
+  }
+
+  void TearDown() override {
+    SetTimeZone(saved_tz_ != nullptr ? saved_tz_->c_str() : nullptr);
+    saved_tz_.reset();
+  }
+
+  static void SetTimeZone(const char* time_zone) {
+    // tzset() distinguishes between the TZ variable being present and empty
+    // and not being present, so we have to consider the case of time_zone
+    // being NULL.
+#if defined(_MSC_VER) || defined(GTEST_OS_WINDOWS_MINGW)
+    // ...Unless it's MSVC, whose standard library's _putenv doesn't
+    // distinguish between an empty and a missing variable.
+    const std::string env_var =
+        std::string("TZ=") + (time_zone ? time_zone : "");
+    _putenv(env_var.c_str());
+    GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* deprecated function */)
+    tzset();
+    GTEST_DISABLE_MSC_WARNINGS_POP_()
+#else
+#if defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ < 21
+    // Work around KitKat bug in tzset by setting "UTC" before setting "UTC+00".
+    // See https://github.com/android/ndk/issues/1604.
+    setenv("TZ", "UTC", 1);
+    tzset();
+#endif
+    if (time_zone) {
+      setenv(("TZ"), time_zone, 1);
+    } else {
+      unsetenv("TZ");
+    }
+    tzset();
+#endif
+  }
+
+  std::unique_ptr<std::string> saved_tz_;  // Empty and null are different here
+};
+
+const TimeInMillis FormatEpochTimeInMillisAsIso8601Test::kMillisPerSec;
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsTwoDigitSegments) {
+  EXPECT_EQ("2011-10-31T18:52:42.000",
+            FormatEpochTimeInMillisAsIso8601(1320087162 * kMillisPerSec));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, IncludesMillisecondsAfterDot) {
+  EXPECT_EQ("2011-10-31T18:52:42.234",
+            FormatEpochTimeInMillisAsIso8601(1320087162 * kMillisPerSec + 234));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsLeadingZeroes) {
+  EXPECT_EQ("2011-09-03T05:07:02.000",
+            FormatEpochTimeInMillisAsIso8601(1315026422 * kMillisPerSec));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, Prints24HourTime) {
+  EXPECT_EQ("2011-09-28T17:08:22.000",
+            FormatEpochTimeInMillisAsIso8601(1317229702 * kMillisPerSec));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsEpochStart) {
+  EXPECT_EQ("1970-01-01T00:00:00.000", FormatEpochTimeInMillisAsIso8601(0));
+}
+
+#endif  // __EMSCRIPTEN__
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+#pragma option push -w-ccc -w-rch
+#endif
+
+// Tests that the LHS of EXPECT_EQ or ASSERT_EQ can be used as a null literal
+// when the RHS is a pointer type.
+TEST(NullLiteralTest, LHSAllowsNullLiterals) {
+  EXPECT_EQ(0, static_cast<void*>(nullptr));     // NOLINT
+  ASSERT_EQ(0, static_cast<void*>(nullptr));     // NOLINT
+  EXPECT_EQ(NULL, static_cast<void*>(nullptr));  // NOLINT
+  ASSERT_EQ(NULL, static_cast<void*>(nullptr));  // NOLINT
+  EXPECT_EQ(nullptr, static_cast<void*>(nullptr));
+  ASSERT_EQ(nullptr, static_cast<void*>(nullptr));
+
+  const int* const p = nullptr;
+  EXPECT_EQ(0, p);     // NOLINT
+  ASSERT_EQ(0, p);     // NOLINT
+  EXPECT_EQ(NULL, p);  // NOLINT
+  ASSERT_EQ(NULL, p);  // NOLINT
+  EXPECT_EQ(nullptr, p);
+  ASSERT_EQ(nullptr, p);
+}
+
+struct ConvertToAll {
+  template <typename T>
+  operator T() const {  // NOLINT
+    return T();
+  }
+};
+
+struct ConvertToPointer {
+  template <class T>
+  operator T*() const {  // NOLINT
+    return nullptr;
+  }
+};
+
+struct ConvertToAllButNoPointers {
+  template <typename T,
+            typename std::enable_if<!std::is_pointer<T>::value, int>::type = 0>
+  operator T() const {  // NOLINT
+    return T();
+  }
+};
+
+struct MyType {};
+inline bool operator==(MyType const&, MyType const&) { return true; }
+
+TEST(NullLiteralTest, ImplicitConversion) {
+  EXPECT_EQ(ConvertToPointer{}, static_cast<void*>(nullptr));
+#if !defined(__GNUC__) || defined(__clang__)
+  // Disabled due to GCC bug gcc.gnu.org/PR89580
+  EXPECT_EQ(ConvertToAll{}, static_cast<void*>(nullptr));
+#endif
+  EXPECT_EQ(ConvertToAll{}, MyType{});
+  EXPECT_EQ(ConvertToAllButNoPointers{}, MyType{});
+}
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#if __has_warning("-Wzero-as-null-pointer-constant")
+#pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
+#endif
+#endif
+
+TEST(NullLiteralTest, NoConversionNoWarning) {
+  // Test that gtests detection and handling of null pointer constants
+  // doesn't trigger a warning when '0' isn't actually used as null.
+  EXPECT_EQ(0, 0);
+  ASSERT_EQ(0, 0);
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them.
+#pragma option pop
+#endif
+
+//
+// Tests CodePointToUtf8().
+
+// Tests that the NUL character L'\0' is encoded correctly.
+TEST(CodePointToUtf8Test, CanEncodeNul) {
+  EXPECT_EQ("", CodePointToUtf8(L'\0'));
+}
+
+// Tests that ASCII characters are encoded correctly.
+TEST(CodePointToUtf8Test, CanEncodeAscii) {
+  EXPECT_EQ("a", CodePointToUtf8(L'a'));
+  EXPECT_EQ("Z", CodePointToUtf8(L'Z'));
+  EXPECT_EQ("&", CodePointToUtf8(L'&'));
+  EXPECT_EQ("\x7F", CodePointToUtf8(L'\x7F'));
+}
+
+// Tests that Unicode code-points that have 8 to 11 bits are encoded
+// as 110xxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode8To11Bits) {
+  // 000 1101 0011 => 110-00011 10-010011
+  EXPECT_EQ("\xC3\x93", CodePointToUtf8(L'\xD3'));
+
+  // 101 0111 0110 => 110-10101 10-110110
+  // Some compilers (e.g., GCC on MinGW) cannot handle non-ASCII codepoints
+  // in wide strings and wide chars. In order to accommodate them, we have to
+  // introduce such character constants as integers.
+  EXPECT_EQ("\xD5\xB6", CodePointToUtf8(static_cast<wchar_t>(0x576)));
+}
+
+// Tests that Unicode code-points that have 12 to 16 bits are encoded
+// as 1110xxxx 10xxxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode12To16Bits) {
+  // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
+  EXPECT_EQ("\xE0\xA3\x93", CodePointToUtf8(static_cast<wchar_t>(0x8D3)));
+
+  // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
+  EXPECT_EQ("\xEC\x9D\x8D", CodePointToUtf8(static_cast<wchar_t>(0xC74D)));
+}
+
+#if !GTEST_WIDE_STRING_USES_UTF16_
+// Tests in this group require a wchar_t to hold > 16 bits, and thus
+// are skipped on Windows, and Cygwin, where a wchar_t is
+// 16-bit wide. This code may not compile on those systems.
+
+// Tests that Unicode code-points that have 17 to 21 bits are encoded
+// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode17To21Bits) {
+  // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
+  EXPECT_EQ("\xF0\x90\xA3\x93", CodePointToUtf8(L'\x108D3'));
+
+  // 0 0001 0000 0100 0000 0000 => 11110-000 10-010000 10-010000 10-000000
+  EXPECT_EQ("\xF0\x90\x90\x80", CodePointToUtf8(L'\x10400'));
+
+  // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
+  EXPECT_EQ("\xF4\x88\x98\xB4", CodePointToUtf8(L'\x108634'));
+}
+
+// Tests that encoding an invalid code-point generates the expected result.
+TEST(CodePointToUtf8Test, CanEncodeInvalidCodePoint) {
+  EXPECT_EQ("(Invalid Unicode 0x1234ABCD)", CodePointToUtf8(L'\x1234ABCD'));
+}
+
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests WideStringToUtf8().
+
+// Tests that the NUL character L'\0' is encoded correctly.
+TEST(WideStringToUtf8Test, CanEncodeNul) {
+  EXPECT_STREQ("", WideStringToUtf8(L"", 0).c_str());
+  EXPECT_STREQ("", WideStringToUtf8(L"", -1).c_str());
+}
+
+// Tests that ASCII strings are encoded correctly.
+TEST(WideStringToUtf8Test, CanEncodeAscii) {
+  EXPECT_STREQ("a", WideStringToUtf8(L"a", 1).c_str());
+  EXPECT_STREQ("ab", WideStringToUtf8(L"ab", 2).c_str());
+  EXPECT_STREQ("a", WideStringToUtf8(L"a", -1).c_str());
+  EXPECT_STREQ("ab", WideStringToUtf8(L"ab", -1).c_str());
+}
+
+// Tests that Unicode code-points that have 8 to 11 bits are encoded
+// as 110xxxxx 10xxxxxx.
+TEST(WideStringToUtf8Test, CanEncode8To11Bits) {
+  // 000 1101 0011 => 110-00011 10-010011
+  EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", 1).c_str());
+  EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", -1).c_str());
+
+  // 101 0111 0110 => 110-10101 10-110110
+  const wchar_t s[] = {0x576, '\0'};
+  EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, 1).c_str());
+  EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, -1).c_str());
+}
+
+// Tests that Unicode code-points that have 12 to 16 bits are encoded
+// as 1110xxxx 10xxxxxx 10xxxxxx.
+TEST(WideStringToUtf8Test, CanEncode12To16Bits) {
+  // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
+  const wchar_t s1[] = {0x8D3, '\0'};
+  EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, 1).c_str());
+  EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, -1).c_str());
+
+  // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
+  const wchar_t s2[] = {0xC74D, '\0'};
+  EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, 1).c_str());
+  EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, -1).c_str());
+}
+
+// Tests that the conversion stops when the function encounters \0 character.
+TEST(WideStringToUtf8Test, StopsOnNulCharacter) {
+  EXPECT_STREQ("ABC", WideStringToUtf8(L"ABC\0XYZ", 100).c_str());
+}
+
+// Tests that the conversion stops when the function reaches the limit
+// specified by the 'length' parameter.
+TEST(WideStringToUtf8Test, StopsWhenLengthLimitReached) {
+  EXPECT_STREQ("ABC", WideStringToUtf8(L"ABCDEF", 3).c_str());
+}
+
+#if !GTEST_WIDE_STRING_USES_UTF16_
+// Tests that Unicode code-points that have 17 to 21 bits are encoded
+// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx. This code may not compile
+// on the systems using UTF-16 encoding.
+TEST(WideStringToUtf8Test, CanEncode17To21Bits) {
+  // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
+  EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", 1).c_str());
+  EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", -1).c_str());
+
+  // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
+  EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", 1).c_str());
+  EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", -1).c_str());
+}
+
+// Tests that encoding an invalid code-point generates the expected result.
+TEST(WideStringToUtf8Test, CanEncodeInvalidCodePoint) {
+  EXPECT_STREQ("(Invalid Unicode 0xABCDFF)",
+               WideStringToUtf8(L"\xABCDFF", -1).c_str());
+}
+#else   // !GTEST_WIDE_STRING_USES_UTF16_
+// Tests that surrogate pairs are encoded correctly on the systems using
+// UTF-16 encoding in the wide strings.
+TEST(WideStringToUtf8Test, CanEncodeValidUtf16SUrrogatePairs) {
+  const wchar_t s[] = {0xD801, 0xDC00, '\0'};
+  EXPECT_STREQ("\xF0\x90\x90\x80", WideStringToUtf8(s, -1).c_str());
+}
+
+// Tests that encoding an invalid UTF-16 surrogate pair
+// generates the expected result.
+TEST(WideStringToUtf8Test, CanEncodeInvalidUtf16SurrogatePair) {
+  // Leading surrogate is at the end of the string.
+  const wchar_t s1[] = {0xD800, '\0'};
+  EXPECT_STREQ("\xED\xA0\x80", WideStringToUtf8(s1, -1).c_str());
+  // Leading surrogate is not followed by the trailing surrogate.
+  const wchar_t s2[] = {0xD800, 'M', '\0'};
+  EXPECT_STREQ("\xED\xA0\x80M", WideStringToUtf8(s2, -1).c_str());
+  // Trailing surrogate appearas without a leading surrogate.
+  const wchar_t s3[] = {0xDC00, 'P', 'Q', 'R', '\0'};
+  EXPECT_STREQ("\xED\xB0\x80PQR", WideStringToUtf8(s3, -1).c_str());
+}
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests that codepoint concatenation works correctly.
+#if !GTEST_WIDE_STRING_USES_UTF16_
+TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
+  const wchar_t s[] = {0x108634, 0xC74D, '\n', 0x576, 0x8D3, 0x108634, '\0'};
+  EXPECT_STREQ(
+      "\xF4\x88\x98\xB4"
+      "\xEC\x9D\x8D"
+      "\n"
+      "\xD5\xB6"
+      "\xE0\xA3\x93"
+      "\xF4\x88\x98\xB4",
+      WideStringToUtf8(s, -1).c_str());
+}
+#else
+TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
+  const wchar_t s[] = {0xC74D, '\n', 0x576, 0x8D3, '\0'};
+  EXPECT_STREQ(
+      "\xEC\x9D\x8D"
+      "\n"
+      "\xD5\xB6"
+      "\xE0\xA3\x93",
+      WideStringToUtf8(s, -1).c_str());
+}
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests the Random class.
+
+TEST(RandomDeathTest, GeneratesCrashesOnInvalidRange) {
+  testing::internal::Random random(42);
+  EXPECT_DEATH_IF_SUPPORTED(random.Generate(0),
+                            "Cannot generate a number in the range \\[0, 0\\)");
+  EXPECT_DEATH_IF_SUPPORTED(
+      random.Generate(testing::internal::Random::kMaxRange + 1),
+      "Generation of a number in \\[0, 2147483649\\) was requested, "
+      "but this can only generate numbers in \\[0, 2147483648\\)");
+}
+
+TEST(RandomTest, GeneratesNumbersWithinRange) {
+  constexpr uint32_t kRange = 10000;
+  testing::internal::Random random(12345);
+  for (int i = 0; i < 10; i++) {
+    EXPECT_LT(random.Generate(kRange), kRange) << " for iteration " << i;
+  }
+
+  testing::internal::Random random2(testing::internal::Random::kMaxRange);
+  for (int i = 0; i < 10; i++) {
+    EXPECT_LT(random2.Generate(kRange), kRange) << " for iteration " << i;
+  }
+}
+
+TEST(RandomTest, RepeatsWhenReseeded) {
+  constexpr int kSeed = 123;
+  constexpr int kArraySize = 10;
+  constexpr uint32_t kRange = 10000;
+  uint32_t values[kArraySize];
+
+  testing::internal::Random random(kSeed);
+  for (int i = 0; i < kArraySize; i++) {
+    values[i] = random.Generate(kRange);
+  }
+
+  random.Reseed(kSeed);
+  for (int i = 0; i < kArraySize; i++) {
+    EXPECT_EQ(values[i], random.Generate(kRange)) << " for iteration " << i;
+  }
+}
+
+// Tests STL container utilities.
+
+// Tests CountIf().
+
+static bool IsPositive(int n) { return n > 0; }
+
+TEST(ContainerUtilityTest, CountIf) {
+  std::vector<int> v;
+  EXPECT_EQ(0, CountIf(v, IsPositive));  // Works for an empty container.
+
+  v.push_back(-1);
+  v.push_back(0);
+  EXPECT_EQ(0, CountIf(v, IsPositive));  // Works when no value satisfies.
+
+  v.push_back(2);
+  v.push_back(-10);
+  v.push_back(10);
+  EXPECT_EQ(2, CountIf(v, IsPositive));
+}
+
+// Tests ForEach().
+
+static int g_sum = 0;
+static void Accumulate(int n) { g_sum += n; }
+
+TEST(ContainerUtilityTest, ForEach) {
+  std::vector<int> v;
+  g_sum = 0;
+  ForEach(v, Accumulate);
+  EXPECT_EQ(0, g_sum);  // Works for an empty container;
+
+  g_sum = 0;
+  v.push_back(1);
+  ForEach(v, Accumulate);
+  EXPECT_EQ(1, g_sum);  // Works for a container with one element.
+
+  g_sum = 0;
+  v.push_back(20);
+  v.push_back(300);
+  ForEach(v, Accumulate);
+  EXPECT_EQ(321, g_sum);
+}
+
+// Tests GetElementOr().
+TEST(ContainerUtilityTest, GetElementOr) {
+  std::vector<char> a;
+  EXPECT_EQ('x', GetElementOr(a, 0, 'x'));
+
+  a.push_back('a');
+  a.push_back('b');
+  EXPECT_EQ('a', GetElementOr(a, 0, 'x'));
+  EXPECT_EQ('b', GetElementOr(a, 1, 'x'));
+  EXPECT_EQ('x', GetElementOr(a, -2, 'x'));
+  EXPECT_EQ('x', GetElementOr(a, 2, 'x'));
+}
+
+TEST(ContainerUtilityDeathTest, ShuffleRange) {
+  std::vector<int> a;
+  a.push_back(0);
+  a.push_back(1);
+  a.push_back(2);
+  testing::internal::Random random(1);
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, -1, 1, &a),
+      "Invalid shuffle range start -1: must be in range \\[0, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 4, 4, &a),
+      "Invalid shuffle range start 4: must be in range \\[0, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 3, 2, &a),
+      "Invalid shuffle range finish 2: must be in range \\[3, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 3, 4, &a),
+      "Invalid shuffle range finish 4: must be in range \\[3, 3\\]");
+}
+
+class VectorShuffleTest : public Test {
+ protected:
+  static const size_t kVectorSize = 20;
+
+  VectorShuffleTest() : random_(1) {
+    for (int i = 0; i < static_cast<int>(kVectorSize); i++) {
+      vector_.push_back(i);
+    }
+  }
+
+  static bool VectorIsCorrupt(const TestingVector& vector) {
+    if (kVectorSize != vector.size()) {
+      return true;
+    }
+
+    bool found_in_vector[kVectorSize] = {false};
+    for (size_t i = 0; i < vector.size(); i++) {
+      const int e = vector[i];
+      if (e < 0 || e >= static_cast<int>(kVectorSize) || found_in_vector[e]) {
+        return true;
+      }
+      found_in_vector[e] = true;
+    }
+
+    // Vector size is correct, elements' range is correct, no
+    // duplicate elements.  Therefore no corruption has occurred.
+    return false;
+  }
+
+  static bool VectorIsNotCorrupt(const TestingVector& vector) {
+    return !VectorIsCorrupt(vector);
+  }
+
+  static bool RangeIsShuffled(const TestingVector& vector, int begin, int end) {
+    for (int i = begin; i < end; i++) {
+      if (i != vector[static_cast<size_t>(i)]) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static bool RangeIsUnshuffled(const TestingVector& vector, int begin,
+                                int end) {
+    return !RangeIsShuffled(vector, begin, end);
+  }
+
+  static bool VectorIsShuffled(const TestingVector& vector) {
+    return RangeIsShuffled(vector, 0, static_cast<int>(vector.size()));
+  }
+
+  static bool VectorIsUnshuffled(const TestingVector& vector) {
+    return !VectorIsShuffled(vector);
+  }
+
+  testing::internal::Random random_;
+  TestingVector vector_;
+};  // class VectorShuffleTest
+
+const size_t VectorShuffleTest::kVectorSize;
+
+TEST_F(VectorShuffleTest, HandlesEmptyRange) {
+  // Tests an empty range at the beginning...
+  ShuffleRange(&random_, 0, 0, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...in the middle...
+  ShuffleRange(&random_, kVectorSize / 2, kVectorSize / 2, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...at the end...
+  ShuffleRange(&random_, kVectorSize - 1, kVectorSize - 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...and past the end.
+  ShuffleRange(&random_, kVectorSize, kVectorSize, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+TEST_F(VectorShuffleTest, HandlesRangeOfSizeOne) {
+  // Tests a size one range at the beginning...
+  ShuffleRange(&random_, 0, 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...in the middle...
+  ShuffleRange(&random_, kVectorSize / 2, kVectorSize / 2 + 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...and at the end.
+  ShuffleRange(&random_, kVectorSize - 1, kVectorSize, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+// Because we use our own random number generator and a fixed seed,
+// we can guarantee that the following "random" tests will succeed.
+
+TEST_F(VectorShuffleTest, ShufflesEntireVector) {
+  Shuffle(&random_, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_FALSE(VectorIsUnshuffled(vector_)) << vector_;
+
+  // Tests the first and last elements in particular to ensure that
+  // there are no off-by-one problems in our shuffle algorithm.
+  EXPECT_NE(0, vector_[0]);
+  EXPECT_NE(static_cast<int>(kVectorSize - 1), vector_[kVectorSize - 1]);
+}
+
+TEST_F(VectorShuffleTest, ShufflesStartOfVector) {
+  const int kRangeSize = kVectorSize / 2;
+
+  ShuffleRange(&random_, 0, kRangeSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsShuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, kRangeSize,
+               static_cast<int>(kVectorSize));
+}
+
+TEST_F(VectorShuffleTest, ShufflesEndOfVector) {
+  const int kRangeSize = kVectorSize / 2;
+  ShuffleRange(&random_, kRangeSize, kVectorSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize,
+               static_cast<int>(kVectorSize));
+}
+
+TEST_F(VectorShuffleTest, ShufflesMiddleOfVector) {
+  const int kRangeSize = static_cast<int>(kVectorSize) / 3;
+  ShuffleRange(&random_, kRangeSize, 2 * kRangeSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, 2 * kRangeSize);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 2 * kRangeSize,
+               static_cast<int>(kVectorSize));
+}
+
+TEST_F(VectorShuffleTest, ShufflesRepeatably) {
+  TestingVector vector2;
+  for (size_t i = 0; i < kVectorSize; i++) {
+    vector2.push_back(static_cast<int>(i));
+  }
+
+  random_.Reseed(1234);
+  Shuffle(&random_, &vector_);
+  random_.Reseed(1234);
+  Shuffle(&random_, &vector2);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector2);
+
+  for (size_t i = 0; i < kVectorSize; i++) {
+    EXPECT_EQ(vector_[i], vector2[i]) << " where i is " << i;
+  }
+}
+
+// Tests the size of the AssertHelper class.
+
+TEST(AssertHelperTest, AssertHelperIsSmall) {
+  // To avoid breaking clients that use lots of assertions in one
+  // function, we cannot grow the size of AssertHelper.
+  EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
+}
+
+// Tests String::EndsWithCaseInsensitive().
+TEST(StringTest, EndsWithCaseInsensitive) {
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("foobar", "BAR"));
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("foobaR", "bar"));
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("foobar", ""));
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("", ""));
+
+  EXPECT_FALSE(String::EndsWithCaseInsensitive("Foobar", "foo"));
+  EXPECT_FALSE(String::EndsWithCaseInsensitive("foobar", "Foo"));
+  EXPECT_FALSE(String::EndsWithCaseInsensitive("", "foo"));
+}
+
+// C++Builder's preprocessor is buggy; it fails to expand macros that
+// appear in macro parameters after wide char literals.  Provide an alias
+// for NULL as a workaround.
+static const wchar_t* const kNull = nullptr;
+
+// Tests String::CaseInsensitiveWideCStringEquals
+TEST(StringTest, CaseInsensitiveWideCStringEquals) {
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(nullptr, nullptr));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L""));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"", kNull));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L"foobar"));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"foobar", kNull));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"foobar"));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"FOOBAR"));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"FOOBAR", L"foobar"));
+}
+
+#ifdef GTEST_OS_WINDOWS
+
+// Tests String::ShowWideCString().
+TEST(StringTest, ShowWideCString) {
+  EXPECT_STREQ("(null)", String::ShowWideCString(NULL).c_str());
+  EXPECT_STREQ("", String::ShowWideCString(L"").c_str());
+  EXPECT_STREQ("foo", String::ShowWideCString(L"foo").c_str());
+}
+
+#ifdef GTEST_OS_WINDOWS_MOBILE
+TEST(StringTest, AnsiAndUtf16Null) {
+  EXPECT_EQ(NULL, String::AnsiToUtf16(NULL));
+  EXPECT_EQ(NULL, String::Utf16ToAnsi(NULL));
+}
+
+TEST(StringTest, AnsiAndUtf16ConvertBasic) {
+  const char* ansi = String::Utf16ToAnsi(L"str");
+  EXPECT_STREQ("str", ansi);
+  delete[] ansi;
+  const WCHAR* utf16 = String::AnsiToUtf16("str");
+  EXPECT_EQ(0, wcsncmp(L"str", utf16, 3));
+  delete[] utf16;
+}
+
+TEST(StringTest, AnsiAndUtf16ConvertPathChars) {
+  const char* ansi = String::Utf16ToAnsi(L".:\\ \"*?");
+  EXPECT_STREQ(".:\\ \"*?", ansi);
+  delete[] ansi;
+  const WCHAR* utf16 = String::AnsiToUtf16(".:\\ \"*?");
+  EXPECT_EQ(0, wcsncmp(L".:\\ \"*?", utf16, 3));
+  delete[] utf16;
+}
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#endif  // GTEST_OS_WINDOWS
+
+// Tests TestProperty construction.
+TEST(TestPropertyTest, StringValue) {
+  TestProperty property("key", "1");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("1", property.value());
+}
+
+// Tests TestProperty replacing a value.
+TEST(TestPropertyTest, ReplaceStringValue) {
+  TestProperty property("key", "1");
+  EXPECT_STREQ("1", property.value());
+  property.SetValue("2");
+  EXPECT_STREQ("2", property.value());
+}
+
+// AddFatalFailure() and AddNonfatalFailure() must be stand-alone
+// functions (i.e. their definitions cannot be inlined at the call
+// sites), or C++Builder won't compile the code.
+static void AddFatalFailure() { FAIL() << "Expected fatal failure."; }
+
+static void AddNonfatalFailure() {
+  ADD_FAILURE() << "Expected non-fatal failure.";
+}
+
+class ScopedFakeTestPartResultReporterTest : public Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  enum FailureMode { FATAL_FAILURE, NONFATAL_FAILURE };
+  static void AddFailure(FailureMode failure) {
+    if (failure == FATAL_FAILURE) {
+      AddFatalFailure();
+    } else {
+      AddNonfatalFailure();
+    }
+  }
+};
+
+// Tests that ScopedFakeTestPartResultReporter intercepts test
+// failures.
+TEST_F(ScopedFakeTestPartResultReporterTest, InterceptsTestFailures) {
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
+        &results);
+    AddFailure(NONFATAL_FAILURE);
+    AddFailure(FATAL_FAILURE);
+  }
+
+  EXPECT_EQ(2, results.size());
+  EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
+}
+
+TEST_F(ScopedFakeTestPartResultReporterTest, DeprecatedConstructor) {
+  TestPartResultArray results;
+  {
+    // Tests, that the deprecated constructor still works.
+    ScopedFakeTestPartResultReporter reporter(&results);
+    AddFailure(NONFATAL_FAILURE);
+  }
+  EXPECT_EQ(1, results.size());
+}
+
+#ifdef GTEST_IS_THREADSAFE
+
+class ScopedFakeTestPartResultReporterWithThreadsTest
+    : public ScopedFakeTestPartResultReporterTest {
+ protected:
+  static void AddFailureInOtherThread(FailureMode failure) {
+    ThreadWithParam<FailureMode> thread(&AddFailure, failure, nullptr);
+    thread.Join();
+  }
+};
+
+TEST_F(ScopedFakeTestPartResultReporterWithThreadsTest,
+       InterceptsTestFailuresInAllThreads) {
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, &results);
+    AddFailure(NONFATAL_FAILURE);
+    AddFailure(FATAL_FAILURE);
+    AddFailureInOtherThread(NONFATAL_FAILURE);
+    AddFailureInOtherThread(FATAL_FAILURE);
+  }
+
+  EXPECT_EQ(4, results.size());
+  EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(2).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(3).fatally_failed());
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests EXPECT_FATAL_FAILURE{,ON_ALL_THREADS}.  Makes sure that they
+// work even if the failure is generated in a called function rather than
+// the current context.
+
+typedef ScopedFakeTestPartResultReporterTest ExpectFatalFailureTest;
+
+TEST_F(ExpectFatalFailureTest, CatchesFatalFaliure) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(), "Expected fatal failure.");
+}
+
+TEST_F(ExpectFatalFailureTest, AcceptsStdStringObject) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(),
+                       ::std::string("Expected fatal failure."));
+}
+
+TEST_F(ExpectFatalFailureTest, CatchesFatalFailureOnAllThreads) {
+  // We have another test below to verify that the macro catches fatal
+  // failures generated on another thread.
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFatalFailure(),
+                                      "Expected fatal failure.");
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true"
+#pragma option push -w-ccc
+#endif
+
+// Tests that EXPECT_FATAL_FAILURE() can be used in a non-void
+// function even when the statement in it contains ASSERT_*.
+
+int NonVoidFunction() {
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
+  return 0;
+}
+
+TEST_F(ExpectFatalFailureTest, CanBeUsedInNonVoidFunction) {
+  NonVoidFunction();
+}
+
+// Tests that EXPECT_FATAL_FAILURE(statement, ...) doesn't abort the
+// current function even though 'statement' generates a fatal failure.
+
+void DoesNotAbortHelper(bool* aborted) {
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
+
+  *aborted = false;
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them.
+#pragma option pop
+#endif
+
+TEST_F(ExpectFatalFailureTest, DoesNotAbort) {
+  bool aborted = true;
+  DoesNotAbortHelper(&aborted);
+  EXPECT_FALSE(aborted);
+}
+
+// Tests that the EXPECT_FATAL_FAILURE{,_ON_ALL_THREADS} accepts a
+// statement that contains a macro which expands to code containing an
+// unprotected comma.
+
+static int global_var = 0;
+#define GTEST_USE_UNPROTECTED_COMMA_ global_var++, global_var++
+
+TEST_F(ExpectFatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(
+      {
+        GTEST_USE_UNPROTECTED_COMMA_;
+        AddFatalFailure();
+      },
+      "");
+#endif
+
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(
+      {
+        GTEST_USE_UNPROTECTED_COMMA_;
+        AddFatalFailure();
+      },
+      "");
+}
+
+// Tests EXPECT_NONFATAL_FAILURE{,ON_ALL_THREADS}.
+
+typedef ScopedFakeTestPartResultReporterTest ExpectNonfatalFailureTest;
+
+TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailure) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(), "Expected non-fatal failure.");
+}
+
+TEST_F(ExpectNonfatalFailureTest, AcceptsStdStringObject) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          ::std::string("Expected non-fatal failure."));
+}
+
+TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailureOnAllThreads) {
+  // We have another test below to verify that the macro catches
+  // non-fatal failures generated on another thread.
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddNonfatalFailure(),
+                                         "Expected non-fatal failure.");
+}
+
+// Tests that the EXPECT_NONFATAL_FAILURE{,_ON_ALL_THREADS} accepts a
+// statement that contains a macro which expands to code containing an
+// unprotected comma.
+TEST_F(ExpectNonfatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
+  EXPECT_NONFATAL_FAILURE(
+      {
+        GTEST_USE_UNPROTECTED_COMMA_;
+        AddNonfatalFailure();
+      },
+      "");
+
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      {
+        GTEST_USE_UNPROTECTED_COMMA_;
+        AddNonfatalFailure();
+      },
+      "");
+}
+
+#ifdef GTEST_IS_THREADSAFE
+
+typedef ScopedFakeTestPartResultReporterWithThreadsTest
+    ExpectFailureWithThreadsTest;
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailureOnAllThreads) {
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailureInOtherThread(FATAL_FAILURE),
+                                      "Expected fatal failure.");
+}
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailureOnAllThreads) {
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      AddFailureInOtherThread(NONFATAL_FAILURE), "Expected non-fatal failure.");
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests the TestProperty class.
+
+TEST(TestPropertyTest, ConstructorWorks) {
+  const TestProperty property("key", "value");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("value", property.value());
+}
+
+TEST(TestPropertyTest, SetValue) {
+  TestProperty property("key", "value_1");
+  EXPECT_STREQ("key", property.key());
+  property.SetValue("value_2");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("value_2", property.value());
+}
+
+// Tests the TestResult class
+
+// The test fixture for testing TestResult.
+class TestResultTest : public Test {
+ protected:
+  typedef std::vector<TestPartResult> TPRVector;
+
+  // We make use of 2 TestPartResult objects,
+  TestPartResult *pr1, *pr2;
+
+  // ... and 3 TestResult objects.
+  TestResult *r0, *r1, *r2;
+
+  void SetUp() override {
+    // pr1 is for success.
+    pr1 = new TestPartResult(TestPartResult::kSuccess, "foo/bar.cc", 10,
+                             "Success!");
+
+    // pr2 is for fatal failure.
+    pr2 = new TestPartResult(TestPartResult::kFatalFailure, "foo/bar.cc",
+                             -1,  // This line number means "unknown"
+                             "Failure!");
+
+    // Creates the TestResult objects.
+    r0 = new TestResult();
+    r1 = new TestResult();
+    r2 = new TestResult();
+
+    // In order to test TestResult, we need to modify its internal
+    // state, in particular the TestPartResult vector it holds.
+    // test_part_results() returns a const reference to this vector.
+    // We cast it to a non-const object s.t. it can be modified
+    TPRVector* results1 =
+        const_cast<TPRVector*>(&TestResultAccessor::test_part_results(*r1));
+    TPRVector* results2 =
+        const_cast<TPRVector*>(&TestResultAccessor::test_part_results(*r2));
+
+    // r0 is an empty TestResult.
+
+    // r1 contains a single SUCCESS TestPartResult.
+    results1->push_back(*pr1);
+
+    // r2 contains a SUCCESS, and a FAILURE.
+    results2->push_back(*pr1);
+    results2->push_back(*pr2);
+  }
+
+  void TearDown() override {
+    delete pr1;
+    delete pr2;
+
+    delete r0;
+    delete r1;
+    delete r2;
+  }
+
+  // Helper that compares two TestPartResults.
+  static void CompareTestPartResult(const TestPartResult& expected,
+                                    const TestPartResult& actual) {
+    EXPECT_EQ(expected.type(), actual.type());
+    EXPECT_STREQ(expected.file_name(), actual.file_name());
+    EXPECT_EQ(expected.line_number(), actual.line_number());
+    EXPECT_STREQ(expected.summary(), actual.summary());
+    EXPECT_STREQ(expected.message(), actual.message());
+    EXPECT_EQ(expected.passed(), actual.passed());
+    EXPECT_EQ(expected.failed(), actual.failed());
+    EXPECT_EQ(expected.nonfatally_failed(), actual.nonfatally_failed());
+    EXPECT_EQ(expected.fatally_failed(), actual.fatally_failed());
+  }
+};
+
+// Tests TestResult::total_part_count().
+TEST_F(TestResultTest, total_part_count) {
+  ASSERT_EQ(0, r0->total_part_count());
+  ASSERT_EQ(1, r1->total_part_count());
+  ASSERT_EQ(2, r2->total_part_count());
+}
+
+// Tests TestResult::Passed().
+TEST_F(TestResultTest, Passed) {
+  ASSERT_TRUE(r0->Passed());
+  ASSERT_TRUE(r1->Passed());
+  ASSERT_FALSE(r2->Passed());
+}
+
+// Tests TestResult::Failed().
+TEST_F(TestResultTest, Failed) {
+  ASSERT_FALSE(r0->Failed());
+  ASSERT_FALSE(r1->Failed());
+  ASSERT_TRUE(r2->Failed());
+}
+
+// Tests TestResult::GetTestPartResult().
+
+typedef TestResultTest TestResultDeathTest;
+
+TEST_F(TestResultDeathTest, GetTestPartResult) {
+  CompareTestPartResult(*pr1, r2->GetTestPartResult(0));
+  CompareTestPartResult(*pr2, r2->GetTestPartResult(1));
+  EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(2), "");
+  EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(-1), "");
+}
+
+// Tests TestResult has no properties when none are added.
+TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
+  TestResult test_result;
+  ASSERT_EQ(0, test_result.test_property_count());
+}
+
+// Tests TestResult has the expected property when added.
+TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) {
+  TestResult test_result;
+  TestProperty property("key_1", "1");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property);
+  ASSERT_EQ(1, test_result.test_property_count());
+  const TestProperty& actual_property = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property.key());
+  EXPECT_STREQ("1", actual_property.value());
+}
+
+// Tests TestResult has multiple properties when added.
+TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
+  TestResult test_result;
+  TestProperty property_1("key_1", "1");
+  TestProperty property_2("key_2", "2");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
+  ASSERT_EQ(2, test_result.test_property_count());
+  const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property_1.key());
+  EXPECT_STREQ("1", actual_property_1.value());
+
+  const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
+  EXPECT_STREQ("key_2", actual_property_2.key());
+  EXPECT_STREQ("2", actual_property_2.value());
+}
+
+// Tests TestResult::RecordProperty() overrides values for duplicate keys.
+TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
+  TestResult test_result;
+  TestProperty property_1_1("key_1", "1");
+  TestProperty property_2_1("key_2", "2");
+  TestProperty property_1_2("key_1", "12");
+  TestProperty property_2_2("key_2", "22");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_2);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_2);
+
+  ASSERT_EQ(2, test_result.test_property_count());
+  const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property_1.key());
+  EXPECT_STREQ("12", actual_property_1.value());
+
+  const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
+  EXPECT_STREQ("key_2", actual_property_2.key());
+  EXPECT_STREQ("22", actual_property_2.value());
+}
+
+// Tests TestResult::GetTestProperty().
+TEST(TestResultPropertyTest, GetTestProperty) {
+  TestResult test_result;
+  TestProperty property_1("key_1", "1");
+  TestProperty property_2("key_2", "2");
+  TestProperty property_3("key_3", "3");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_3);
+
+  const TestProperty& fetched_property_1 = test_result.GetTestProperty(0);
+  const TestProperty& fetched_property_2 = test_result.GetTestProperty(1);
+  const TestProperty& fetched_property_3 = test_result.GetTestProperty(2);
+
+  EXPECT_STREQ("key_1", fetched_property_1.key());
+  EXPECT_STREQ("1", fetched_property_1.value());
+
+  EXPECT_STREQ("key_2", fetched_property_2.key());
+  EXPECT_STREQ("2", fetched_property_2.value());
+
+  EXPECT_STREQ("key_3", fetched_property_3.key());
+  EXPECT_STREQ("3", fetched_property_3.value());
+
+  EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(3), "");
+  EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(-1), "");
+}
+
+// Tests the Test class.
+//
+// It's difficult to test every public method of this class (we are
+// already stretching the limit of Google Test by using it to test itself!).
+// Fortunately, we don't have to do that, as we are already testing
+// the functionalities of the Test class extensively by using Google Test
+// alone.
+//
+// Therefore, this section only contains one test.
+
+// Tests that GTestFlagSaver works on Windows and Mac.
+
+class GTestFlagSaverTest : public Test {
+ protected:
+  // Saves the Google Test flags such that we can restore them later, and
+  // then sets them to their default values.  This will be called
+  // before the first test in this test case is run.
+  static void SetUpTestSuite() {
+    saver_ = new GTestFlagSaver;
+
+    GTEST_FLAG_SET(also_run_disabled_tests, false);
+    GTEST_FLAG_SET(break_on_failure, false);
+    GTEST_FLAG_SET(catch_exceptions, false);
+    GTEST_FLAG_SET(death_test_use_fork, false);
+    GTEST_FLAG_SET(color, "auto");
+    GTEST_FLAG_SET(fail_fast, false);
+    GTEST_FLAG_SET(filter, "");
+    GTEST_FLAG_SET(list_tests, false);
+    GTEST_FLAG_SET(output, "");
+    GTEST_FLAG_SET(brief, false);
+    GTEST_FLAG_SET(print_time, true);
+    GTEST_FLAG_SET(random_seed, 0);
+    GTEST_FLAG_SET(repeat, 1);
+    GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+    GTEST_FLAG_SET(shuffle, false);
+    GTEST_FLAG_SET(stack_trace_depth, kMaxStackTraceDepth);
+    GTEST_FLAG_SET(stream_result_to, "");
+    GTEST_FLAG_SET(throw_on_failure, false);
+  }
+
+  // Restores the Google Test flags that the tests have modified.  This will
+  // be called after the last test in this test case is run.
+  static void TearDownTestSuite() {
+    delete saver_;
+    saver_ = nullptr;
+  }
+
+  // Verifies that the Google Test flags have their default values, and then
+  // modifies each of them.
+  void VerifyAndModifyFlags() {
+    EXPECT_FALSE(GTEST_FLAG_GET(also_run_disabled_tests));
+    EXPECT_FALSE(GTEST_FLAG_GET(break_on_failure));
+    EXPECT_FALSE(GTEST_FLAG_GET(catch_exceptions));
+    EXPECT_STREQ("auto", GTEST_FLAG_GET(color).c_str());
+    EXPECT_FALSE(GTEST_FLAG_GET(death_test_use_fork));
+    EXPECT_FALSE(GTEST_FLAG_GET(fail_fast));
+    EXPECT_STREQ("", GTEST_FLAG_GET(filter).c_str());
+    EXPECT_FALSE(GTEST_FLAG_GET(list_tests));
+    EXPECT_STREQ("", GTEST_FLAG_GET(output).c_str());
+    EXPECT_FALSE(GTEST_FLAG_GET(brief));
+    EXPECT_TRUE(GTEST_FLAG_GET(print_time));
+    EXPECT_EQ(0, GTEST_FLAG_GET(random_seed));
+    EXPECT_EQ(1, GTEST_FLAG_GET(repeat));
+    EXPECT_TRUE(GTEST_FLAG_GET(recreate_environments_when_repeating));
+    EXPECT_FALSE(GTEST_FLAG_GET(shuffle));
+    EXPECT_EQ(kMaxStackTraceDepth, GTEST_FLAG_GET(stack_trace_depth));
+    EXPECT_STREQ("", GTEST_FLAG_GET(stream_result_to).c_str());
+    EXPECT_FALSE(GTEST_FLAG_GET(throw_on_failure));
+
+    GTEST_FLAG_SET(also_run_disabled_tests, true);
+    GTEST_FLAG_SET(break_on_failure, true);
+    GTEST_FLAG_SET(catch_exceptions, true);
+    GTEST_FLAG_SET(color, "no");
+    GTEST_FLAG_SET(death_test_use_fork, true);
+    GTEST_FLAG_SET(fail_fast, true);
+    GTEST_FLAG_SET(filter, "abc");
+    GTEST_FLAG_SET(list_tests, true);
+    GTEST_FLAG_SET(output, "xml:foo.xml");
+    GTEST_FLAG_SET(brief, true);
+    GTEST_FLAG_SET(print_time, false);
+    GTEST_FLAG_SET(random_seed, 1);
+    GTEST_FLAG_SET(repeat, 100);
+    GTEST_FLAG_SET(recreate_environments_when_repeating, false);
+    GTEST_FLAG_SET(shuffle, true);
+    GTEST_FLAG_SET(stack_trace_depth, 1);
+    GTEST_FLAG_SET(stream_result_to, "localhost:1234");
+    GTEST_FLAG_SET(throw_on_failure, true);
+  }
+
+ private:
+  // For saving Google Test flags during this test case.
+  static GTestFlagSaver* saver_;
+};
+
+GTestFlagSaver* GTestFlagSaverTest::saver_ = nullptr;
+
+// Google Test doesn't guarantee the order of tests.  The following two
+// tests are designed to work regardless of their order.
+
+// Modifies the Google Test flags in the test body.
+TEST_F(GTestFlagSaverTest, ModifyGTestFlags) { VerifyAndModifyFlags(); }
+
+// Verifies that the Google Test flags in the body of the previous test were
+// restored to their original values.
+TEST_F(GTestFlagSaverTest, VerifyGTestFlags) { VerifyAndModifyFlags(); }
+
+// Sets an environment variable with the given name to the given
+// value.  If the value argument is "", unsets the environment
+// variable.  The caller must ensure that both arguments are not NULL.
+static void SetEnv(const char* name, const char* value) {
+#ifdef GTEST_OS_WINDOWS_MOBILE
+  // Environment variables are not supported on Windows CE.
+  return;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // C++Builder's putenv only stores a pointer to its parameter; we have to
+  // ensure that the string remains valid as long as it might be needed.
+  // We use an std::map to do so.
+  static std::map<std::string, std::string*> added_env;
+
+  // Because putenv stores a pointer to the string buffer, we can't delete the
+  // previous string (if present) until after it's replaced.
+  std::string* prev_env = NULL;
+  if (added_env.find(name) != added_env.end()) {
+    prev_env = added_env[name];
+  }
+  added_env[name] =
+      new std::string((Message() << name << "=" << value).GetString());
+
+  // The standard signature of putenv accepts a 'char*' argument. Other
+  // implementations, like C++Builder's, accept a 'const char*'.
+  // We cast away the 'const' since that would work for both variants.
+  putenv(const_cast<char*>(added_env[name]->c_str()));
+  delete prev_env;
+#elif defined(GTEST_OS_WINDOWS)  // If we are on Windows proper.
+  _putenv((Message() << name << "=" << value).GetString().c_str());
+#else
+  if (*value == '\0') {
+    unsetenv(name);
+  } else {
+    setenv(name, value, 1);
+  }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+#ifndef GTEST_OS_WINDOWS_MOBILE
+// Environment variables are not supported on Windows CE.
+
+using testing::internal::Int32FromGTestEnv;
+
+// Tests Int32FromGTestEnv().
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable is not set.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenVariableIsNotSet) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "");
+  EXPECT_EQ(10, Int32FromGTestEnv("temp", 10));
+}
+
+#if !defined(GTEST_GET_INT32_FROM_ENV_)
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable overflows as an Int32.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueOverflows) {
+  printf("(expecting 2 warnings)\n");
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12345678987654321");
+  EXPECT_EQ(20, Int32FromGTestEnv("temp", 20));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-12345678987654321");
+  EXPECT_EQ(30, Int32FromGTestEnv("temp", 30));
+}
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable does not represent a valid decimal integer.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueIsInvalid) {
+  printf("(expecting 2 warnings)\n");
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "A1");
+  EXPECT_EQ(40, Int32FromGTestEnv("temp", 40));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12X");
+  EXPECT_EQ(50, Int32FromGTestEnv("temp", 50));
+}
+
+#endif  // !defined(GTEST_GET_INT32_FROM_ENV_)
+
+// Tests that Int32FromGTestEnv() parses and returns the value of the
+// environment variable when it represents a valid decimal integer in
+// the range of an Int32.
+TEST(Int32FromGTestEnvTest, ParsesAndReturnsValidValue) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "123");
+  EXPECT_EQ(123, Int32FromGTestEnv("temp", 0));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-321");
+  EXPECT_EQ(-321, Int32FromGTestEnv("temp", 0));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests ParseFlag().
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag has wrong format
+TEST(ParseInt32FlagTest, ReturnsFalseForInvalidFlag) {
+  int32_t value = 123;
+  EXPECT_FALSE(ParseFlag("--a=100", "b", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseFlag("a=100", "a", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseFlag() returns false and doesn't change the
+// output value when the flag overflows as an Int32.
+TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueOverflows) {
+  printf("(expecting 2 warnings)\n");
+
+  int32_t value = 123;
+  EXPECT_FALSE(ParseFlag("--abc=12345678987654321", "abc", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseFlag("--abc=-12345678987654321", "abc", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag does not represent a valid decimal
+// integer.
+TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueIsInvalid) {
+  printf("(expecting 2 warnings)\n");
+
+  int32_t value = 123;
+  EXPECT_FALSE(ParseFlag("--abc=A1", "abc", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseFlag("--abc=12X", "abc", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() parses the value of the flag and
+// returns true when the flag represents a valid decimal integer in
+// the range of an Int32.
+TEST(ParseInt32FlagTest, ParsesAndReturnsValidValue) {
+  int32_t value = 123;
+  EXPECT_TRUE(ParseFlag("--" GTEST_FLAG_PREFIX_ "abc=456", "abc", &value));
+  EXPECT_EQ(456, value);
+
+  EXPECT_TRUE(ParseFlag("--" GTEST_FLAG_PREFIX_ "abc=-789", "abc", &value));
+  EXPECT_EQ(-789, value);
+}
+
+// Tests that Int32FromEnvOrDie() parses the value of the var or
+// returns the correct default.
+// Environment variables are not supported on Windows CE.
+#ifndef GTEST_OS_WINDOWS_MOBILE
+TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
+  EXPECT_EQ(333, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "123");
+  EXPECT_EQ(123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123");
+  EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that Int32FromEnvOrDie() aborts with an error message
+// if the variable is not an int32_t.
+TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "xxx");
+  EXPECT_DEATH_IF_SUPPORTED(
+      Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123), ".*");
+}
+
+// Tests that Int32FromEnvOrDie() aborts with an error message
+// if the variable cannot be represented by an int32_t.
+TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234");
+  EXPECT_DEATH_IF_SUPPORTED(
+      Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123), ".*");
+}
+
+// Tests that ShouldRunTestOnShard() selects all tests
+// where there is 1 shard.
+TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) {
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 0));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 1));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 2));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 3));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 4));
+}
+
+class ShouldShardTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    index_var_ = GTEST_FLAG_PREFIX_UPPER_ "INDEX";
+    total_var_ = GTEST_FLAG_PREFIX_UPPER_ "TOTAL";
+  }
+
+  void TearDown() override {
+    SetEnv(index_var_, "");
+    SetEnv(total_var_, "");
+  }
+
+  const char* index_var_;
+  const char* total_var_;
+};
+
+// Tests that sharding is disabled if neither of the environment variables
+// are set.
+TEST_F(ShouldShardTest, ReturnsFalseWhenNeitherEnvVarIsSet) {
+  SetEnv(index_var_, "");
+  SetEnv(total_var_, "");
+
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+
+// Tests that sharding is not enabled if total_shards  == 1.
+TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
+  SetEnv(index_var_, "0");
+  SetEnv(total_var_, "1");
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+
+// Tests that sharding is enabled if total_shards > 1 and
+// we are not in a death test subprocess.
+// Environment variables are not supported on Windows CE.
+#ifndef GTEST_OS_WINDOWS_MOBILE
+TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "22");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+
+  SetEnv(index_var_, "8");
+  SetEnv(total_var_, "9");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+
+  SetEnv(index_var_, "0");
+  SetEnv(total_var_, "9");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that we exit in error if the sharding values are not valid.
+
+typedef ShouldShardTest ShouldShardDeathTest;
+
+TEST_F(ShouldShardDeathTest, AbortsWhenShardingEnvVarsAreInvalid) {
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "4");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "-2");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "5");
+  SetEnv(total_var_, "");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "");
+  SetEnv(total_var_, "5");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+}
+
+// Tests that ShouldRunTestOnShard is a partition when 5
+// shards are used.
+TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) {
+  // Choose an arbitrary number of tests and shards.
+  const int num_tests = 17;
+  const int num_shards = 5;
+
+  // Check partitioning: each test should be on exactly 1 shard.
+  for (int test_id = 0; test_id < num_tests; test_id++) {
+    int prev_selected_shard_index = -1;
+    for (int shard_index = 0; shard_index < num_shards; shard_index++) {
+      if (ShouldRunTestOnShard(num_shards, shard_index, test_id)) {
+        if (prev_selected_shard_index < 0) {
+          prev_selected_shard_index = shard_index;
+        } else {
+          ADD_FAILURE() << "Shard " << prev_selected_shard_index << " and "
+                        << shard_index << " are both selected to run test "
+                        << test_id;
+        }
+      }
+    }
+  }
+
+  // Check balance: This is not required by the sharding protocol, but is a
+  // desirable property for performance.
+  for (int shard_index = 0; shard_index < num_shards; shard_index++) {
+    int num_tests_on_shard = 0;
+    for (int test_id = 0; test_id < num_tests; test_id++) {
+      num_tests_on_shard +=
+          ShouldRunTestOnShard(num_shards, shard_index, test_id);
+    }
+    EXPECT_GE(num_tests_on_shard, num_tests / num_shards);
+  }
+}
+
+// For the same reason we are not explicitly testing everything in the
+// Test class, there are no separate tests for the following classes
+// (except for some trivial cases):
+//
+//   TestSuite, UnitTest, UnitTestResultPrinter.
+//
+// Similarly, there are no separate tests for the following macros:
+//
+//   TEST, TEST_F, RUN_ALL_TESTS
+
+TEST(UnitTestTest, CanGetOriginalWorkingDir) {
+  ASSERT_TRUE(UnitTest::GetInstance()->original_working_dir() != nullptr);
+  EXPECT_STRNE(UnitTest::GetInstance()->original_working_dir(), "");
+}
+
+TEST(UnitTestTest, ReturnsPlausibleTimestamp) {
+  EXPECT_LT(0, UnitTest::GetInstance()->start_timestamp());
+  EXPECT_LE(UnitTest::GetInstance()->start_timestamp(), GetTimeInMillis());
+}
+
+// When a property using a reserved key is supplied to this function, it
+// tests that a non-fatal failure is added, a fatal failure is not added,
+// and that the property is not recorded.
+void ExpectNonFatalFailureRecordingPropertyWithReservedKey(
+    const TestResult& test_result, const char* key) {
+  EXPECT_NONFATAL_FAILURE(Test::RecordProperty(key, "1"), "Reserved key");
+  ASSERT_EQ(0, test_result.test_property_count())
+      << "Property for key '" << key << "' recorded unexpectedly.";
+}
+
+void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+    const char* key) {
+  const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(test_info != nullptr);
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey(*test_info->result(),
+                                                        key);
+}
+
+void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+    const char* key) {
+  const testing::TestSuite* test_suite =
+      UnitTest::GetInstance()->current_test_suite();
+  ASSERT_TRUE(test_suite != nullptr);
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey(
+      test_suite->ad_hoc_test_result(), key);
+}
+
+void ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+    const char* key) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey(
+      UnitTest::GetInstance()->ad_hoc_test_result(), key);
+}
+
+// Tests that property recording functions in UnitTest outside of tests
+// functions correctly.  Creating a separate instance of UnitTest ensures it
+// is in a state similar to the UnitTest's singleton's between tests.
+class UnitTestRecordPropertyTest
+    : public testing::internal::UnitTestRecordPropertyTestHelper {
+ public:
+  static void SetUpTestSuite() {
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+        "disabled");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+        "errors");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+        "failures");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+        "name");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+        "tests");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
+        "time");
+
+    Test::RecordProperty("test_case_key_1", "1");
+
+    const testing::TestSuite* test_suite =
+        UnitTest::GetInstance()->current_test_suite();
+
+    ASSERT_TRUE(test_suite != nullptr);
+
+    ASSERT_EQ(1, test_suite->ad_hoc_test_result().test_property_count());
+    EXPECT_STREQ("test_case_key_1",
+                 test_suite->ad_hoc_test_result().GetTestProperty(0).key());
+    EXPECT_STREQ("1",
+                 test_suite->ad_hoc_test_result().GetTestProperty(0).value());
+  }
+};
+
+// Tests TestResult has the expected property when added.
+TEST_F(UnitTestRecordPropertyTest, OnePropertyFoundWhenAdded) {
+  UnitTestRecordProperty("key_1", "1");
+
+  ASSERT_EQ(1, unit_test_.ad_hoc_test_result().test_property_count());
+
+  EXPECT_STREQ("key_1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
+  EXPECT_STREQ("1", unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
+}
+
+// Tests TestResult has multiple properties when added.
+TEST_F(UnitTestRecordPropertyTest, MultiplePropertiesFoundWhenAdded) {
+  UnitTestRecordProperty("key_1", "1");
+  UnitTestRecordProperty("key_2", "2");
+
+  ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
+
+  EXPECT_STREQ("key_1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
+  EXPECT_STREQ("1", unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
+
+  EXPECT_STREQ("key_2",
+               unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
+  EXPECT_STREQ("2", unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
+}
+
+// Tests TestResult::RecordProperty() overrides values for duplicate keys.
+TEST_F(UnitTestRecordPropertyTest, OverridesValuesForDuplicateKeys) {
+  UnitTestRecordProperty("key_1", "1");
+  UnitTestRecordProperty("key_2", "2");
+  UnitTestRecordProperty("key_1", "12");
+  UnitTestRecordProperty("key_2", "22");
+
+  ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
+
+  EXPECT_STREQ("key_1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
+  EXPECT_STREQ("12",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
+
+  EXPECT_STREQ("key_2",
+               unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
+  EXPECT_STREQ("22",
+               unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
+}
+
+TEST_F(UnitTestRecordPropertyTest,
+       AddFailureInsideTestsWhenUsingTestSuiteReservedKeys) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest("name");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "value_param");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "type_param");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest("status");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest("time");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "classname");
+}
+
+TEST_F(UnitTestRecordPropertyTest,
+       AddRecordWithReservedKeysGeneratesCorrectPropertyList) {
+  EXPECT_NONFATAL_FAILURE(
+      Test::RecordProperty("name", "1"),
+      "'classname', 'name', 'status', 'time', 'type_param', 'value_param',"
+      " 'file', and 'line' are reserved");
+}
+
+class UnitTestRecordPropertyTestEnvironment : public Environment {
+ public:
+  void TearDown() override {
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "tests");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "failures");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "disabled");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "errors");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "name");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "timestamp");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "time");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
+        "random_seed");
+  }
+};
+
+// This will test property recording outside of any test or test case.
+GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static Environment* record_property_env =
+    AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
+
+// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
+// of various arities.  They do not attempt to be exhaustive.  Rather,
+// view them as smoke tests that can be easily reviewed and verified.
+// A more complete set of tests for predicate assertions can be found
+// in gtest_pred_impl_unittest.cc.
+
+// First, some predicates and predicate-formatters needed by the tests.
+
+// Returns true if and only if the argument is an even number.
+bool IsEven(int n) { return (n % 2) == 0; }
+
+// A functor that returns true if and only if the argument is an even number.
+struct IsEvenFunctor {
+  bool operator()(int n) { return IsEven(n); }
+};
+
+// A predicate-formatter function that asserts the argument is an even
+// number.
+AssertionResult AssertIsEven(const char* expr, int n) {
+  if (IsEven(n)) {
+    return AssertionSuccess();
+  }
+
+  Message msg;
+  msg << expr << " evaluates to " << n << ", which is not even.";
+  return AssertionFailure(msg);
+}
+
+// A predicate function that returns AssertionResult for use in
+// EXPECT/ASSERT_TRUE/FALSE.
+AssertionResult ResultIsEven(int n) {
+  if (IsEven(n))
+    return AssertionSuccess() << n << " is even";
+  else
+    return AssertionFailure() << n << " is odd";
+}
+
+// A predicate function that returns AssertionResult but gives no
+// explanation why it succeeds. Needed for testing that
+// EXPECT/ASSERT_FALSE handles such functions correctly.
+AssertionResult ResultIsEvenNoExplanation(int n) {
+  if (IsEven(n))
+    return AssertionSuccess();
+  else
+    return AssertionFailure() << n << " is odd";
+}
+
+// A predicate-formatter functor that asserts the argument is an even
+// number.
+struct AssertIsEvenFunctor {
+  AssertionResult operator()(const char* expr, int n) {
+    return AssertIsEven(expr, n);
+  }
+};
+
+// Returns true if and only if the sum of the arguments is an even number.
+bool SumIsEven2(int n1, int n2) { return IsEven(n1 + n2); }
+
+// A functor that returns true if and only if the sum of the arguments is an
+// even number.
+struct SumIsEven3Functor {
+  bool operator()(int n1, int n2, int n3) { return IsEven(n1 + n2 + n3); }
+};
+
+// A predicate-formatter function that asserts the sum of the
+// arguments is an even number.
+AssertionResult AssertSumIsEven4(const char* e1, const char* e2, const char* e3,
+                                 const char* e4, int n1, int n2, int n3,
+                                 int n4) {
+  const int sum = n1 + n2 + n3 + n4;
+  if (IsEven(sum)) {
+    return AssertionSuccess();
+  }
+
+  Message msg;
+  msg << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " (" << n1 << " + "
+      << n2 << " + " << n3 << " + " << n4 << ") evaluates to " << sum
+      << ", which is not even.";
+  return AssertionFailure(msg);
+}
+
+// A predicate-formatter functor that asserts the sum of the arguments
+// is an even number.
+struct AssertSumIsEven5Functor {
+  AssertionResult operator()(const char* e1, const char* e2, const char* e3,
+                             const char* e4, const char* e5, int n1, int n2,
+                             int n3, int n4, int n5) {
+    const int sum = n1 + n2 + n3 + n4 + n5;
+    if (IsEven(sum)) {
+      return AssertionSuccess();
+    }
+
+    Message msg;
+    msg << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
+        << " (" << n1 << " + " << n2 << " + " << n3 << " + " << n4 << " + "
+        << n5 << ") evaluates to " << sum << ", which is not even.";
+    return AssertionFailure(msg);
+  }
+};
+
+// Tests unary predicate assertions.
+
+// Tests unary predicate assertions that don't use a custom formatter.
+TEST(Pred1Test, WithoutFormat) {
+  // Success cases.
+  EXPECT_PRED1(IsEvenFunctor(), 2) << "This failure is UNEXPECTED!";
+  ASSERT_PRED1(IsEven, 4);
+
+  // Failure cases.
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED1(IsEven, 5) << "This failure is expected.";
+      },
+      "This failure is expected.");
+  EXPECT_FATAL_FAILURE(ASSERT_PRED1(IsEvenFunctor(), 5), "evaluates to false");
+}
+
+// Tests unary predicate assertions that use a custom formatter.
+TEST(Pred1Test, WithFormat) {
+  // Success cases.
+  EXPECT_PRED_FORMAT1(AssertIsEven, 2);
+  ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), 4)
+      << "This failure is UNEXPECTED!";
+
+  // Failure cases.
+  const int n = 5;
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT1(AssertIsEvenFunctor(), n),
+                          "n evaluates to 5, which is not even.");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT1(AssertIsEven, 5) << "This failure is expected.";
+      },
+      "This failure is expected.");
+}
+
+// Tests that unary predicate assertions evaluates their arguments
+// exactly once.
+TEST(Pred1Test, SingleEvaluationOnFailure) {
+  // A success case.
+  static int n = 0;
+  EXPECT_PRED1(IsEven, n++);
+  EXPECT_EQ(1, n) << "The argument is not evaluated exactly once.";
+
+  // A failure case.
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), n++)
+            << "This failure is expected.";
+      },
+      "This failure is expected.");
+  EXPECT_EQ(2, n) << "The argument is not evaluated exactly once.";
+}
+
+// Tests predicate assertions whose arity is >= 2.
+
+// Tests predicate assertions that don't use a custom formatter.
+TEST(PredTest, WithoutFormat) {
+  // Success cases.
+  ASSERT_PRED2(SumIsEven2, 2, 4) << "This failure is UNEXPECTED!";
+  EXPECT_PRED3(SumIsEven3Functor(), 4, 6, 8);
+
+  // Failure cases.
+  const int n1 = 1;
+  const int n2 = 2;
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED2(SumIsEven2, n1, n2) << "This failure is expected.";
+      },
+      "This failure is expected.");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED3(SumIsEven3Functor(), 1, 2, 4);
+      },
+      "evaluates to false");
+}
+
+// Tests predicate assertions that use a custom formatter.
+TEST(PredTest, WithFormat) {
+  // Success cases.
+  ASSERT_PRED_FORMAT4(AssertSumIsEven4, 4, 6, 8, 10)
+      << "This failure is UNEXPECTED!";
+  EXPECT_PRED_FORMAT5(AssertSumIsEven5Functor(), 2, 4, 6, 8, 10);
+
+  // Failure cases.
+  const int n1 = 1;
+  const int n2 = 2;
+  const int n3 = 4;
+  const int n4 = 6;
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT4(AssertSumIsEven4, n1, n2, n3, n4);
+      },
+      "evaluates to 13, which is not even.");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(), 1, 2, 4, 6, 8)
+            << "This failure is expected.";
+      },
+      "This failure is expected.");
+}
+
+// Tests that predicate assertions evaluates their arguments
+// exactly once.
+TEST(PredTest, SingleEvaluationOnFailure) {
+  // A success case.
+  int n1 = 0;
+  int n2 = 0;
+  EXPECT_PRED2(SumIsEven2, n1++, n2++);
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+
+  // Another success case.
+  n1 = n2 = 0;
+  int n3 = 0;
+  int n4 = 0;
+  int n5 = 0;
+  ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(), n1++, n2++, n3++, n4++, n5++)
+      << "This failure is UNEXPECTED!";
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+  EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
+  EXPECT_EQ(1, n5) << "Argument 5 is not evaluated exactly once.";
+
+  // A failure case.
+  n1 = n2 = n3 = 0;
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED3(SumIsEven3Functor(), ++n1, n2++, n3++)
+            << "This failure is expected.";
+      },
+      "This failure is expected.");
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+
+  // Another failure case.
+  n1 = n2 = n3 = n4 = 0;
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT4(AssertSumIsEven4, ++n1, n2++, n3++, n4++);
+      },
+      "evaluates to 1, which is not even.");
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+  EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
+}
+
+// Test predicate assertions for sets
+TEST(PredTest, ExpectPredEvalFailure) {
+  std::set<int> set_a = {2, 1, 3, 4, 5};
+  std::set<int> set_b = {0, 4, 8};
+  const auto compare_sets = [](std::set<int>, std::set<int>) { return false; };
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_PRED2(compare_sets, set_a, set_b),
+      "compare_sets(set_a, set_b) evaluates to false, where\nset_a evaluates "
+      "to { 1, 2, 3, 4, 5 }\nset_b evaluates to { 0, 4, 8 }");
+}
+
+// Some helper functions for testing using overloaded/template
+// functions with ASSERT_PREDn and EXPECT_PREDn.
+
+bool IsPositive(double x) { return x > 0; }
+
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+
+template <typename T1, typename T2>
+bool GreaterThan(T1 x1, T2 x2) {
+  return x1 > x2;
+}
+
+// Tests that overloaded functions can be used in *_PRED* as long as
+// their types are explicitly specified.
+TEST(PredicateAssertionTest, AcceptsOverloadedFunction) {
+  // C++Builder requires C-style casts rather than static_cast.
+  EXPECT_PRED1((bool (*)(int))(IsPositive), 5);       // NOLINT
+  ASSERT_PRED1((bool (*)(double))(IsPositive), 6.0);  // NOLINT
+}
+
+// Tests that template functions can be used in *_PRED* as long as
+// their types are explicitly specified.
+TEST(PredicateAssertionTest, AcceptsTemplateFunction) {
+  EXPECT_PRED1(IsNegative<int>, -5);
+  // Makes sure that we can handle templates with more than one
+  // parameter.
+  ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
+}
+
+// Some helper functions for testing using overloaded/template
+// functions with ASSERT_PRED_FORMATn and EXPECT_PRED_FORMATn.
+
+AssertionResult IsPositiveFormat(const char* /* expr */, int n) {
+  return n > 0 ? AssertionSuccess() : AssertionFailure(Message() << "Failure");
+}
+
+AssertionResult IsPositiveFormat(const char* /* expr */, double x) {
+  return x > 0 ? AssertionSuccess() : AssertionFailure(Message() << "Failure");
+}
+
+template <typename T>
+AssertionResult IsNegativeFormat(const char* /* expr */, T x) {
+  return x < 0 ? AssertionSuccess() : AssertionFailure(Message() << "Failure");
+}
+
+template <typename T1, typename T2>
+AssertionResult EqualsFormat(const char* /* expr1 */, const char* /* expr2 */,
+                             const T1& x1, const T2& x2) {
+  return x1 == x2 ? AssertionSuccess()
+                  : AssertionFailure(Message() << "Failure");
+}
+
+// Tests that overloaded functions can be used in *_PRED_FORMAT*
+// without explicitly specifying their types.
+TEST(PredicateFormatAssertionTest, AcceptsOverloadedFunction) {
+  EXPECT_PRED_FORMAT1(IsPositiveFormat, 5);
+  ASSERT_PRED_FORMAT1(IsPositiveFormat, 6.0);
+}
+
+// Tests that template functions can be used in *_PRED_FORMAT* without
+// explicitly specifying their types.
+TEST(PredicateFormatAssertionTest, AcceptsTemplateFunction) {
+  EXPECT_PRED_FORMAT1(IsNegativeFormat, -5);
+  ASSERT_PRED_FORMAT2(EqualsFormat, 3, 3);
+}
+
+// Tests string assertions.
+
+// Tests ASSERT_STREQ with non-NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ) {
+  const char* const p1 = "good";
+  ASSERT_STREQ(p1, p1);
+
+  // Let p2 have the same content as p1, but be at a different address.
+  const char p2[] = "good";
+  ASSERT_STREQ(p1, p2);
+
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("bad", "good"), "  \"bad\"\n  \"good\"");
+}
+
+// Tests ASSERT_STREQ with NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ_Null) {
+  ASSERT_STREQ(static_cast<const char*>(nullptr), nullptr);
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ(nullptr, "non-null"), "non-null");
+}
+
+// Tests ASSERT_STREQ with NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ_Null2) {
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("non-null", nullptr), "non-null");
+}
+
+// Tests ASSERT_STRNE.
+TEST(StringAssertionTest, ASSERT_STRNE) {
+  ASSERT_STRNE("hi", "Hi");
+  ASSERT_STRNE("Hi", nullptr);
+  ASSERT_STRNE(nullptr, "Hi");
+  ASSERT_STRNE("", nullptr);
+  ASSERT_STRNE(nullptr, "");
+  ASSERT_STRNE("", "Hi");
+  ASSERT_STRNE("Hi", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRNE("Hi", "Hi"), "\"Hi\" vs \"Hi\"");
+}
+
+// Tests ASSERT_STRCASEEQ.
+TEST(StringAssertionTest, ASSERT_STRCASEEQ) {
+  ASSERT_STRCASEEQ("hi", "Hi");
+  ASSERT_STRCASEEQ(static_cast<const char*>(nullptr), nullptr);
+
+  ASSERT_STRCASEEQ("", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("Hi", "hi2"), "Ignoring case");
+}
+
+// Tests ASSERT_STRCASENE.
+TEST(StringAssertionTest, ASSERT_STRCASENE) {
+  ASSERT_STRCASENE("hi1", "Hi2");
+  ASSERT_STRCASENE("Hi", nullptr);
+  ASSERT_STRCASENE(nullptr, "Hi");
+  ASSERT_STRCASENE("", nullptr);
+  ASSERT_STRCASENE(nullptr, "");
+  ASSERT_STRCASENE("", "Hi");
+  ASSERT_STRCASENE("Hi", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("Hi", "hi"), "(ignoring case)");
+}
+
+// Tests *_STREQ on wide strings.
+TEST(StringAssertionTest, STREQ_Wide) {
+  // NULL strings.
+  ASSERT_STREQ(static_cast<const wchar_t*>(nullptr), nullptr);
+
+  // Empty strings.
+  ASSERT_STREQ(L"", L"");
+
+  // Non-null vs NULL.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"non-null", nullptr), "non-null");
+
+  // Equal strings.
+  EXPECT_STREQ(L"Hi", L"Hi");
+
+  // Unequal strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc", L"Abc"), "Abc");
+
+  // Strings containing wide characters.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc\x8119", L"abc\x8120"), "abc");
+
+  // The streaming variation.
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_STREQ(L"abc\x8119", L"abc\x8121") << "Expected failure";
+      },
+      "Expected failure");
+}
+
+// Tests *_STRNE on wide strings.
+TEST(StringAssertionTest, STRNE_Wide) {
+  // NULL strings.
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_STRNE(static_cast<const wchar_t*>(nullptr), nullptr);
+      },
+      "");
+
+  // Empty strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"", L""), "L\"\"");
+
+  // Non-null vs NULL.
+  ASSERT_STRNE(L"non-null", nullptr);
+
+  // Equal strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"Hi", L"Hi"), "L\"Hi\"");
+
+  // Unequal strings.
+  EXPECT_STRNE(L"abc", L"Abc");
+
+  // Strings containing wide characters.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"abc\x8119", L"abc\x8119"), "abc");
+
+  // The streaming variation.
+  ASSERT_STRNE(L"abc\x8119", L"abc\x8120") << "This shouldn't happen";
+}
+
+// Tests for ::testing::IsSubstring().
+
+// Tests that IsSubstring() returns the correct result when the input
+// argument type is const char*.
+TEST(IsSubstringTest, ReturnsCorrectResultForCString) {
+  EXPECT_FALSE(IsSubstring("", "", nullptr, "a"));
+  EXPECT_FALSE(IsSubstring("", "", "b", nullptr));
+  EXPECT_FALSE(IsSubstring("", "", "needle", "haystack"));
+
+  EXPECT_TRUE(IsSubstring("", "", static_cast<const char*>(nullptr), nullptr));
+  EXPECT_TRUE(IsSubstring("", "", "needle", "two needles"));
+}
+
+// Tests that IsSubstring() returns the correct result when the input
+// argument type is const wchar_t*.
+TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
+  EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
+  EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
+  EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
+
+  EXPECT_TRUE(
+      IsSubstring("", "", static_cast<const wchar_t*>(nullptr), nullptr));
+  EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
+}
+
+// Tests that IsSubstring() generates the correct message when the input
+// argument type is const char*.
+TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
+  EXPECT_STREQ(
+      "Value of: needle_expr\n"
+      "  Actual: \"needle\"\n"
+      "Expected: a substring of haystack_expr\n"
+      "Which is: \"haystack\"",
+      IsSubstring("needle_expr", "haystack_expr", "needle", "haystack")
+          .failure_message());
+}
+
+// Tests that IsSubstring returns the correct result when the input
+// argument type is ::std::string.
+TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
+  EXPECT_TRUE(IsSubstring("", "", std::string("hello"), "ahellob"));
+  EXPECT_FALSE(IsSubstring("", "", "hello", std::string("world")));
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Tests that IsSubstring returns the correct result when the input
+// argument type is ::std::wstring.
+TEST(IsSubstringTest, ReturnsCorrectResultForStdWstring) {
+  EXPECT_TRUE(IsSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
+  EXPECT_FALSE(IsSubstring("", "", L"needle", ::std::wstring(L"haystack")));
+}
+
+// Tests that IsSubstring() generates the correct message when the input
+// argument type is ::std::wstring.
+TEST(IsSubstringTest, GeneratesCorrectMessageForWstring) {
+  EXPECT_STREQ(
+      "Value of: needle_expr\n"
+      "  Actual: L\"needle\"\n"
+      "Expected: a substring of haystack_expr\n"
+      "Which is: L\"haystack\"",
+      IsSubstring("needle_expr", "haystack_expr", ::std::wstring(L"needle"),
+                  L"haystack")
+          .failure_message());
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests for ::testing::IsNotSubstring().
+
+// Tests that IsNotSubstring() returns the correct result when the input
+// argument type is const char*.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForCString) {
+  EXPECT_TRUE(IsNotSubstring("", "", "needle", "haystack"));
+  EXPECT_FALSE(IsNotSubstring("", "", "needle", "two needles"));
+}
+
+// Tests that IsNotSubstring() returns the correct result when the input
+// argument type is const wchar_t*.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
+  EXPECT_TRUE(IsNotSubstring("", "", L"needle", L"haystack"));
+  EXPECT_FALSE(IsNotSubstring("", "", L"needle", L"two needles"));
+}
+
+// Tests that IsNotSubstring() generates the correct message when the input
+// argument type is const wchar_t*.
+TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
+  EXPECT_STREQ(
+      "Value of: needle_expr\n"
+      "  Actual: L\"needle\"\n"
+      "Expected: not a substring of haystack_expr\n"
+      "Which is: L\"two needles\"",
+      IsNotSubstring("needle_expr", "haystack_expr", L"needle", L"two needles")
+          .failure_message());
+}
+
+// Tests that IsNotSubstring returns the correct result when the input
+// argument type is ::std::string.
+TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
+  EXPECT_FALSE(IsNotSubstring("", "", std::string("hello"), "ahellob"));
+  EXPECT_TRUE(IsNotSubstring("", "", "hello", std::string("world")));
+}
+
+// Tests that IsNotSubstring() generates the correct message when the input
+// argument type is ::std::string.
+TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
+  EXPECT_STREQ(
+      "Value of: needle_expr\n"
+      "  Actual: \"needle\"\n"
+      "Expected: not a substring of haystack_expr\n"
+      "Which is: \"two needles\"",
+      IsNotSubstring("needle_expr", "haystack_expr", ::std::string("needle"),
+                     "two needles")
+          .failure_message());
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Tests that IsNotSubstring returns the correct result when the input
+// argument type is ::std::wstring.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForStdWstring) {
+  EXPECT_FALSE(
+      IsNotSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
+  EXPECT_TRUE(IsNotSubstring("", "", L"needle", ::std::wstring(L"haystack")));
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests floating-point assertions.
+
+template <typename RawType>
+class FloatingPointTest : public Test {
+ protected:
+  // Pre-calculated numbers to be used by the tests.
+  struct TestValues {
+    RawType close_to_positive_zero;
+    RawType close_to_negative_zero;
+    RawType further_from_negative_zero;
+
+    RawType close_to_one;
+    RawType further_from_one;
+
+    RawType infinity;
+    RawType close_to_infinity;
+    RawType further_from_infinity;
+
+    RawType nan1;
+    RawType nan2;
+  };
+
+  typedef typename testing::internal::FloatingPoint<RawType> Floating;
+  typedef typename Floating::Bits Bits;
+
+  void SetUp() override {
+    const uint32_t max_ulps = Floating::kMaxUlps;
+
+    // The bits that represent 0.0.
+    const Bits zero_bits = Floating(0).bits();
+
+    // Makes some numbers close to 0.0.
+    values_.close_to_positive_zero =
+        Floating::ReinterpretBits(zero_bits + max_ulps / 2);
+    values_.close_to_negative_zero =
+        -Floating::ReinterpretBits(zero_bits + max_ulps - max_ulps / 2);
+    values_.further_from_negative_zero =
+        -Floating::ReinterpretBits(zero_bits + max_ulps + 1 - max_ulps / 2);
+
+    // The bits that represent 1.0.
+    const Bits one_bits = Floating(1).bits();
+
+    // Makes some numbers close to 1.0.
+    values_.close_to_one = Floating::ReinterpretBits(one_bits + max_ulps);
+    values_.further_from_one =
+        Floating::ReinterpretBits(one_bits + max_ulps + 1);
+
+    // +infinity.
+    values_.infinity = Floating::Infinity();
+
+    // The bits that represent +infinity.
+    const Bits infinity_bits = Floating(values_.infinity).bits();
+
+    // Makes some numbers close to infinity.
+    values_.close_to_infinity =
+        Floating::ReinterpretBits(infinity_bits - max_ulps);
+    values_.further_from_infinity =
+        Floating::ReinterpretBits(infinity_bits - max_ulps - 1);
+
+    // Makes some NAN's.  Sets the most significant bit of the fraction so that
+    // our NaN's are quiet; trying to process a signaling NaN would raise an
+    // exception if our environment enables floating point exceptions.
+    values_.nan1 = Floating::ReinterpretBits(
+        Floating::kExponentBitMask |
+        (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 1);
+    values_.nan2 = Floating::ReinterpretBits(
+        Floating::kExponentBitMask |
+        (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 200);
+  }
+
+  void TestSize() { EXPECT_EQ(sizeof(RawType), sizeof(Bits)); }
+
+  static TestValues values_;
+};
+
+template <typename RawType>
+typename FloatingPointTest<RawType>::TestValues
+    FloatingPointTest<RawType>::values_;
+
+// Instantiates FloatingPointTest for testing *_FLOAT_EQ.
+typedef FloatingPointTest<float> FloatTest;
+
+// Tests that the size of Float::Bits matches the size of float.
+TEST_F(FloatTest, Size) { TestSize(); }
+
+// Tests comparing with +0 and -0.
+TEST_F(FloatTest, Zeros) {
+  EXPECT_FLOAT_EQ(0.0, -0.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(-0.0, 1.0), "1.0");
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.5), "1.5");
+}
+
+// Tests comparing numbers close to 0.
+//
+// This ensures that *_FLOAT_EQ handles the sign correctly and no
+// overflow occurs when comparing numbers whose absolute value is very
+// small.
+TEST_F(FloatTest, AlmostZeros) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
+
+  EXPECT_FLOAT_EQ(0.0, v.close_to_positive_zero);
+  EXPECT_FLOAT_EQ(-0.0, v.close_to_negative_zero);
+  EXPECT_FLOAT_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
+
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_FLOAT_EQ(v.close_to_positive_zero, v.further_from_negative_zero);
+      },
+      "v.further_from_negative_zero");
+}
+
+// Tests comparing numbers close to each other.
+TEST_F(FloatTest, SmallDiff) {
+  EXPECT_FLOAT_EQ(1.0, values_.close_to_one);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, values_.further_from_one),
+                          "values_.further_from_one");
+}
+
+// Tests comparing numbers far apart.
+TEST_F(FloatTest, LargeDiff) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(2.5, 3.0), "3.0");
+}
+
+// Tests comparing with infinity.
+//
+// This ensures that no overflow occurs when comparing numbers whose
+// absolute value is very large.
+TEST_F(FloatTest, Infinity) {
+  EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
+  EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
+                          "-values_.infinity");
+
+  // This is interesting as the representations of infinity and nan1
+  // are only 1 DLP apart.
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, values_.nan1),
+                          "values_.nan1");
+}
+
+// Tests that comparing with NAN always returns false.
+TEST_F(FloatTest, NaN) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2), "v.nan2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1), "v.nan1");
+
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity), "v.infinity");
+}
+
+// Tests that *_FLOAT_EQ are reflexive.
+TEST_F(FloatTest, Reflexive) {
+  EXPECT_FLOAT_EQ(0.0, 0.0);
+  EXPECT_FLOAT_EQ(1.0, 1.0);
+  ASSERT_FLOAT_EQ(values_.infinity, values_.infinity);
+}
+
+// Tests that *_FLOAT_EQ are commutative.
+TEST_F(FloatTest, Commutative) {
+  // We already tested EXPECT_FLOAT_EQ(1.0, values_.close_to_one).
+  EXPECT_FLOAT_EQ(values_.close_to_one, 1.0);
+
+  // We already tested EXPECT_FLOAT_EQ(1.0, values_.further_from_one).
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.further_from_one, 1.0),
+                          "1.0");
+}
+
+// Tests EXPECT_NEAR.
+TEST_F(FloatTest, EXPECT_NEAR) {
+  EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
+  EXPECT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, 1.5f, 0.25f),  // NOLINT
+                          "The difference between 1.0f and 1.5f is 0.5, "
+                          "which exceeds 0.25f");
+}
+
+// Tests ASSERT_NEAR.
+TEST_F(FloatTest, ASSERT_NEAR) {
+  ASSERT_NEAR(-1.0f, -1.1f, 0.2f);
+  ASSERT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0f, 1.5f, 0.25f),  // NOLINT
+                       "The difference between 1.0f and 1.5f is 0.5, "
+                       "which exceeds 0.25f");
+}
+
+// Tests the cases where FloatLE() should succeed.
+TEST_F(FloatTest, FloatLESucceeds) {
+  EXPECT_PRED_FORMAT2(FloatLE, 1.0f, 2.0f);  // When val1 < val2,
+  ASSERT_PRED_FORMAT2(FloatLE, 1.0f, 1.0f);  // val1 == val2,
+
+  // or when val1 is greater than, but almost equals to, val2.
+  EXPECT_PRED_FORMAT2(FloatLE, values_.close_to_positive_zero, 0.0f);
+}
+
+// Tests the cases where FloatLE() should fail.
+TEST_F(FloatTest, FloatLEFails) {
+  // When val1 is greater than val2 by a large margin,
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(FloatLE, 2.0f, 1.0f),
+                          "(2.0f) <= (1.0f)");
+
+  // or by a small yet non-negligible margin,
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(FloatLE, values_.further_from_one, 1.0f);
+      },
+      "(values_.further_from_one) <= (1.0f)");
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(FloatLE, values_.nan1, values_.infinity);
+      },
+      "(values_.nan1) <= (values_.infinity)");
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(FloatLE, -values_.infinity, values_.nan1);
+      },
+      "(-values_.infinity) <= (values_.nan1)");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT2(FloatLE, values_.nan1, values_.nan1);
+      },
+      "(values_.nan1) <= (values_.nan1)");
+}
+
+// Instantiates FloatingPointTest for testing *_DOUBLE_EQ.
+typedef FloatingPointTest<double> DoubleTest;
+
+// Tests that the size of Double::Bits matches the size of double.
+TEST_F(DoubleTest, Size) { TestSize(); }
+
+// Tests comparing with +0 and -0.
+TEST_F(DoubleTest, Zeros) {
+  EXPECT_DOUBLE_EQ(0.0, -0.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(-0.0, 1.0), "1.0");
+  EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(0.0, 1.0), "1.0");
+}
+
+// Tests comparing numbers close to 0.
+//
+// This ensures that *_DOUBLE_EQ handles the sign correctly and no
+// overflow occurs when comparing numbers whose absolute value is very
+// small.
+TEST_F(DoubleTest, AlmostZeros) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
+
+  EXPECT_DOUBLE_EQ(0.0, v.close_to_positive_zero);
+  EXPECT_DOUBLE_EQ(-0.0, v.close_to_negative_zero);
+  EXPECT_DOUBLE_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
+
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_DOUBLE_EQ(v.close_to_positive_zero,
+                         v.further_from_negative_zero);
+      },
+      "v.further_from_negative_zero");
+}
+
+// Tests comparing numbers close to each other.
+TEST_F(DoubleTest, SmallDiff) {
+  EXPECT_DOUBLE_EQ(1.0, values_.close_to_one);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, values_.further_from_one),
+                          "values_.further_from_one");
+}
+
+// Tests comparing numbers far apart.
+TEST_F(DoubleTest, LargeDiff) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(2.0, 3.0), "3.0");
+}
+
+// Tests comparing with infinity.
+//
+// This ensures that no overflow occurs when comparing numbers whose
+// absolute value is very large.
+TEST_F(DoubleTest, Infinity) {
+  EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
+  EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
+                          "-values_.infinity");
+
+  // This is interesting as the representations of infinity_ and nan1_
+  // are only 1 DLP apart.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, values_.nan1),
+                          "values_.nan1");
+}
+
+// Tests that comparing with NAN always returns false.
+TEST_F(DoubleTest, NaN) {
+  static const DoubleTest::TestValues& v = this->values_;
+
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
+  EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity), "v.infinity");
+}
+
+// Tests that *_DOUBLE_EQ are reflexive.
+TEST_F(DoubleTest, Reflexive) {
+  EXPECT_DOUBLE_EQ(0.0, 0.0);
+  EXPECT_DOUBLE_EQ(1.0, 1.0);
+  ASSERT_DOUBLE_EQ(values_.infinity, values_.infinity);
+}
+
+// Tests that *_DOUBLE_EQ are commutative.
+TEST_F(DoubleTest, Commutative) {
+  // We already tested EXPECT_DOUBLE_EQ(1.0, values_.close_to_one).
+  EXPECT_DOUBLE_EQ(values_.close_to_one, 1.0);
+
+  // We already tested EXPECT_DOUBLE_EQ(1.0, values_.further_from_one).
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.further_from_one, 1.0),
+                          "1.0");
+}
+
+// Tests EXPECT_NEAR.
+TEST_F(DoubleTest, EXPECT_NEAR) {
+  EXPECT_NEAR(-1.0, -1.1, 0.2);
+  EXPECT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25),  // NOLINT
+                          "The difference between 1.0 and 1.5 is 0.5, "
+                          "which exceeds 0.25");
+  // At this magnitude adjacent doubles are 512.0 apart, so this triggers a
+  // slightly different failure reporting path.
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_NEAR(4.2934311416234112e+18, 4.2934311416234107e+18, 1.0),
+      "The abs_error parameter 1.0 evaluates to 1 which is smaller than the "
+      "minimum distance between doubles for numbers of this magnitude which is "
+      "512");
+}
+
+// Tests ASSERT_NEAR.
+TEST_F(DoubleTest, ASSERT_NEAR) {
+  ASSERT_NEAR(-1.0, -1.1, 0.2);
+  ASSERT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0, 1.5, 0.25),  // NOLINT
+                       "The difference between 1.0 and 1.5 is 0.5, "
+                       "which exceeds 0.25");
+}
+
+// Tests the cases where DoubleLE() should succeed.
+TEST_F(DoubleTest, DoubleLESucceeds) {
+  EXPECT_PRED_FORMAT2(DoubleLE, 1.0, 2.0);  // When val1 < val2,
+  ASSERT_PRED_FORMAT2(DoubleLE, 1.0, 1.0);  // val1 == val2,
+
+  // or when val1 is greater than, but almost equals to, val2.
+  EXPECT_PRED_FORMAT2(DoubleLE, values_.close_to_positive_zero, 0.0);
+}
+
+// Tests the cases where DoubleLE() should fail.
+TEST_F(DoubleTest, DoubleLEFails) {
+  // When val1 is greater than val2 by a large margin,
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(DoubleLE, 2.0, 1.0),
+                          "(2.0) <= (1.0)");
+
+  // or by a small yet non-negligible margin,
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(DoubleLE, values_.further_from_one, 1.0);
+      },
+      "(values_.further_from_one) <= (1.0)");
+
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.infinity);
+      },
+      "(values_.nan1) <= (values_.infinity)");
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_PRED_FORMAT2(DoubleLE, -values_.infinity, values_.nan1);
+      },
+      " (-values_.infinity) <= (values_.nan1)");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.nan1);
+      },
+      "(values_.nan1) <= (values_.nan1)");
+}
+
+// Verifies that a test or test case whose name starts with DISABLED_ is
+// not run.
+
+// A test whose name starts with DISABLED_.
+// Should not run.
+TEST(DisabledTest, DISABLED_TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+// A test whose name does not start with DISABLED_.
+// Should run.
+TEST(DisabledTest, NotDISABLED_TestShouldRun) { EXPECT_EQ(1, 1); }
+
+// A test case whose name starts with DISABLED_.
+// Should not run.
+TEST(DISABLED_TestSuite, TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
+}
+
+// A test case and test whose names start with DISABLED_.
+// Should not run.
+TEST(DISABLED_TestSuite, DISABLED_TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
+}
+
+// Check that when all tests in a test case are disabled, SetUpTestSuite() and
+// TearDownTestSuite() are not called.
+class DisabledTestsTest : public Test {
+ protected:
+  static void SetUpTestSuite() {
+    FAIL() << "Unexpected failure: All tests disabled in test case. "
+              "SetUpTestSuite() should not be called.";
+  }
+
+  static void TearDownTestSuite() {
+    FAIL() << "Unexpected failure: All tests disabled in test case. "
+              "TearDownTestSuite() should not be called.";
+  }
+};
+
+TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_1) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_2) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+// Tests that disabled typed tests aren't run.
+
+template <typename T>
+class TypedTest : public Test {};
+
+typedef testing::Types<int, double> NumericTypes;
+TYPED_TEST_SUITE(TypedTest, NumericTypes);
+
+TYPED_TEST(TypedTest, DISABLED_ShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled typed test should not run.";
+}
+
+template <typename T>
+class DISABLED_TypedTest : public Test {};
+
+TYPED_TEST_SUITE(DISABLED_TypedTest, NumericTypes);
+
+TYPED_TEST(DISABLED_TypedTest, ShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled typed test should not run.";
+}
+
+// Tests that disabled type-parameterized tests aren't run.
+
+template <typename T>
+class TypedTestP : public Test {};
+
+TYPED_TEST_SUITE_P(TypedTestP);
+
+TYPED_TEST_P(TypedTestP, DISABLED_ShouldNotRun) {
+  FAIL() << "Unexpected failure: "
+         << "Disabled type-parameterized test should not run.";
+}
+
+REGISTER_TYPED_TEST_SUITE_P(TypedTestP, DISABLED_ShouldNotRun);
+
+INSTANTIATE_TYPED_TEST_SUITE_P(My, TypedTestP, NumericTypes);
+
+template <typename T>
+class DISABLED_TypedTestP : public Test {};
+
+TYPED_TEST_SUITE_P(DISABLED_TypedTestP);
+
+TYPED_TEST_P(DISABLED_TypedTestP, ShouldNotRun) {
+  FAIL() << "Unexpected failure: "
+         << "Disabled type-parameterized test should not run.";
+}
+
+REGISTER_TYPED_TEST_SUITE_P(DISABLED_TypedTestP, ShouldNotRun);
+
+INSTANTIATE_TYPED_TEST_SUITE_P(My, DISABLED_TypedTestP, NumericTypes);
+
+// Tests that assertion macros evaluate their arguments exactly once.
+
+class SingleEvaluationTest : public Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  // This helper function is needed by the FailedASSERT_STREQ test
+  // below.  It's public to work around C++Builder's bug with scoping local
+  // classes.
+  static void CompareAndIncrementCharPtrs() { ASSERT_STREQ(p1_++, p2_++); }
+
+  // This helper function is needed by the FailedASSERT_NE test below.  It's
+  // public to work around C++Builder's bug with scoping local classes.
+  static void CompareAndIncrementInts() { ASSERT_NE(a_++, b_++); }
+
+ protected:
+  SingleEvaluationTest() {
+    p1_ = s1_;
+    p2_ = s2_;
+    a_ = 0;
+    b_ = 0;
+  }
+
+  static const char* const s1_;
+  static const char* const s2_;
+  static const char* p1_;
+  static const char* p2_;
+
+  static int a_;
+  static int b_;
+};
+
+const char* const SingleEvaluationTest::s1_ = "01234";
+const char* const SingleEvaluationTest::s2_ = "abcde";
+const char* SingleEvaluationTest::p1_;
+const char* SingleEvaluationTest::p2_;
+int SingleEvaluationTest::a_;
+int SingleEvaluationTest::b_;
+
+// Tests that when ASSERT_STREQ fails, it evaluates its arguments
+// exactly once.
+TEST_F(SingleEvaluationTest, FailedASSERT_STREQ) {
+  EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementCharPtrs(),
+                       "p2_++");
+  EXPECT_EQ(s1_ + 1, p1_);
+  EXPECT_EQ(s2_ + 1, p2_);
+}
+
+// Tests that string assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, ASSERT_STR) {
+  // successful EXPECT_STRNE
+  EXPECT_STRNE(p1_++, p2_++);
+  EXPECT_EQ(s1_ + 1, p1_);
+  EXPECT_EQ(s2_ + 1, p2_);
+
+  // failed EXPECT_STRCASEEQ
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ(p1_++, p2_++), "Ignoring case");
+  EXPECT_EQ(s1_ + 2, p1_);
+  EXPECT_EQ(s2_ + 2, p2_);
+}
+
+// Tests that when ASSERT_NE fails, it evaluates its arguments exactly
+// once.
+TEST_F(SingleEvaluationTest, FailedASSERT_NE) {
+  EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementInts(),
+                       "(a_++) != (b_++)");
+  EXPECT_EQ(1, a_);
+  EXPECT_EQ(1, b_);
+}
+
+// Tests that assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, OtherCases) {
+  // successful EXPECT_TRUE
+  EXPECT_TRUE(0 == a_++);  // NOLINT
+  EXPECT_EQ(1, a_);
+
+  // failed EXPECT_TRUE
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(-1 == a_++), "-1 == a_++");
+  EXPECT_EQ(2, a_);
+
+  // successful EXPECT_GT
+  EXPECT_GT(a_++, b_++);
+  EXPECT_EQ(3, a_);
+  EXPECT_EQ(1, b_);
+
+  // failed EXPECT_LT
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(a_++, b_++), "(a_++) < (b_++)");
+  EXPECT_EQ(4, a_);
+  EXPECT_EQ(2, b_);
+
+  // successful ASSERT_TRUE
+  ASSERT_TRUE(0 < a_++);  // NOLINT
+  EXPECT_EQ(5, a_);
+
+  // successful ASSERT_GT
+  ASSERT_GT(a_++, b_++);
+  EXPECT_EQ(6, a_);
+  EXPECT_EQ(3, b_);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+#if GTEST_HAS_RTTI
+
+#define ERROR_DESC "std::runtime_error"
+
+#else  // GTEST_HAS_RTTI
+
+#define ERROR_DESC "an std::exception-derived error"
+
+#endif  // GTEST_HAS_RTTI
+
+void ThrowAnInteger() { throw 1; }
+void ThrowRuntimeError(const char* what) { throw std::runtime_error(what); }
+
+// Tests that assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, ExceptionTests) {
+  // successful EXPECT_THROW
+  EXPECT_THROW(
+      {  // NOLINT
+        a_++;
+        ThrowAnInteger();
+      },
+      int);
+  EXPECT_EQ(1, a_);
+
+  // failed EXPECT_THROW, throws different
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(
+                              {  // NOLINT
+                                a_++;
+                                ThrowAnInteger();
+                              },
+                              bool),
+                          "throws a different type");
+  EXPECT_EQ(2, a_);
+
+  // failed EXPECT_THROW, throws runtime error
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(
+                              {  // NOLINT
+                                a_++;
+                                ThrowRuntimeError("A description");
+                              },
+                              bool),
+                          "throws " ERROR_DESC
+                          " with description \"A description\"");
+  EXPECT_EQ(3, a_);
+
+  // failed EXPECT_THROW, throws nothing
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(a_++, bool), "throws nothing");
+  EXPECT_EQ(4, a_);
+
+  // successful EXPECT_NO_THROW
+  EXPECT_NO_THROW(a_++);
+  EXPECT_EQ(5, a_);
+
+  // failed EXPECT_NO_THROW
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW({  // NOLINT
+                            a_++;
+                            ThrowAnInteger();
+                          }),
+                          "it throws");
+  EXPECT_EQ(6, a_);
+
+  // successful EXPECT_ANY_THROW
+  EXPECT_ANY_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  });
+  EXPECT_EQ(7, a_);
+
+  // failed EXPECT_ANY_THROW
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(a_++), "it doesn't");
+  EXPECT_EQ(8, a_);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests {ASSERT|EXPECT}_NO_FATAL_FAILURE.
+class NoFatalFailureTest : public Test {
+ protected:
+  void Succeeds() {}
+  void FailsNonFatal() { ADD_FAILURE() << "some non-fatal failure"; }
+  void Fails() { FAIL() << "some fatal failure"; }
+
+  void DoAssertNoFatalFailureOnFails() {
+    ASSERT_NO_FATAL_FAILURE(Fails());
+    ADD_FAILURE() << "should not reach here.";
+  }
+
+  void DoExpectNoFatalFailureOnFails() {
+    EXPECT_NO_FATAL_FAILURE(Fails());
+    ADD_FAILURE() << "other failure";
+  }
+};
+
+TEST_F(NoFatalFailureTest, NoFailure) {
+  EXPECT_NO_FATAL_FAILURE(Succeeds());
+  ASSERT_NO_FATAL_FAILURE(Succeeds());
+}
+
+TEST_F(NoFatalFailureTest, NonFatalIsNoFailure) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_FATAL_FAILURE(FailsNonFatal()),
+                          "some non-fatal failure");
+  EXPECT_NONFATAL_FAILURE(ASSERT_NO_FATAL_FAILURE(FailsNonFatal()),
+                          "some non-fatal failure");
+}
+
+TEST_F(NoFatalFailureTest, AssertNoFatalFailureOnFatalFailure) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    DoAssertNoFatalFailureOnFails();
+  }
+  ASSERT_EQ(2, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
+                      gtest_failures.GetTestPartResult(1).message());
+}
+
+TEST_F(NoFatalFailureTest, ExpectNoFatalFailureOnFatalFailure) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    DoExpectNoFatalFailureOnFails();
+  }
+  ASSERT_EQ(3, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(2).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
+                      gtest_failures.GetTestPartResult(1).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "other failure",
+                      gtest_failures.GetTestPartResult(2).message());
+}
+
+TEST_F(NoFatalFailureTest, MessageIsStreamable) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    EXPECT_NO_FATAL_FAILURE([] { FAIL() << "foo"; }()) << "my message";
+  }
+  ASSERT_EQ(2, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "foo",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "my message",
+                      gtest_failures.GetTestPartResult(1).message());
+}
+
+// Tests non-string assertions.
+
+std::string EditsToString(const std::vector<EditType>& edits) {
+  std::string out;
+  for (size_t i = 0; i < edits.size(); ++i) {
+    static const char kEdits[] = " +-/";
+    out.append(1, kEdits[edits[i]]);
+  }
+  return out;
+}
+
+std::vector<size_t> CharsToIndices(const std::string& str) {
+  std::vector<size_t> out;
+  for (size_t i = 0; i < str.size(); ++i) {
+    out.push_back(static_cast<size_t>(str[i]));
+  }
+  return out;
+}
+
+std::vector<std::string> CharsToLines(const std::string& str) {
+  std::vector<std::string> out;
+  for (size_t i = 0; i < str.size(); ++i) {
+    out.push_back(str.substr(i, 1));
+  }
+  return out;
+}
+
+TEST(EditDistance, TestSuites) {
+  struct Case {
+    int line;
+    const char* left;
+    const char* right;
+    const char* expected_edits;
+    const char* expected_diff;
+  };
+  static const Case kCases[] = {
+      // No change.
+      {__LINE__, "A", "A", " ", ""},
+      {__LINE__, "ABCDE", "ABCDE", "     ", ""},
+      // Simple adds.
+      {__LINE__, "X", "XA", " +", "@@ +1,2 @@\n X\n+A\n"},
+      {__LINE__, "X", "XABCD", " ++++", "@@ +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
+      // Simple removes.
+      {__LINE__, "XA", "X", " -", "@@ -1,2 @@\n X\n-A\n"},
+      {__LINE__, "XABCD", "X", " ----", "@@ -1,5 @@\n X\n-A\n-B\n-C\n-D\n"},
+      // Simple replaces.
+      {__LINE__, "A", "a", "/", "@@ -1,1 +1,1 @@\n-A\n+a\n"},
+      {__LINE__, "ABCD", "abcd", "////",
+       "@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
+      // Path finding.
+      {__LINE__, "ABCDEFGH", "ABXEGH1", "  -/ -  +",
+       "@@ -1,8 +1,7 @@\n A\n B\n-C\n-D\n+X\n E\n-F\n G\n H\n+1\n"},
+      {__LINE__, "AAAABCCCC", "ABABCDCDC", "- /   + / ",
+       "@@ -1,9 +1,9 @@\n-A\n A\n-A\n+B\n A\n B\n C\n+D\n C\n-C\n+D\n C\n"},
+      {__LINE__, "ABCDE", "BCDCD", "-   +/",
+       "@@ -1,5 +1,5 @@\n-A\n B\n C\n D\n-E\n+C\n+D\n"},
+      {__LINE__, "ABCDEFGHIJKL", "BCDCDEFGJKLJK", "- ++     --   ++",
+       "@@ -1,4 +1,5 @@\n-A\n B\n+C\n+D\n C\n D\n"
+       "@@ -6,7 +7,7 @@\n F\n G\n-H\n-I\n J\n K\n L\n+J\n+K\n"},
+      {}};
+  for (const Case* c = kCases; c->left; ++c) {
+    EXPECT_TRUE(c->expected_edits ==
+                EditsToString(CalculateOptimalEdits(CharsToIndices(c->left),
+                                                    CharsToIndices(c->right))))
+        << "Left <" << c->left << "> Right <" << c->right << "> Edits <"
+        << EditsToString(CalculateOptimalEdits(CharsToIndices(c->left),
+                                               CharsToIndices(c->right)))
+        << ">";
+    EXPECT_TRUE(c->expected_diff == CreateUnifiedDiff(CharsToLines(c->left),
+                                                      CharsToLines(c->right)))
+        << "Left <" << c->left << "> Right <" << c->right << "> Diff <"
+        << CreateUnifiedDiff(CharsToLines(c->left), CharsToLines(c->right))
+        << ">";
+  }
+}
+
+// Tests EqFailure(), used for implementing *EQ* assertions.
+TEST(AssertionTest, EqFailure) {
+  const std::string foo_val("5"), bar_val("6");
+  const std::string msg1(
+      EqFailure("foo", "bar", foo_val, bar_val, false).failure_message());
+  EXPECT_STREQ(
+      "Expected equality of these values:\n"
+      "  foo\n"
+      "    Which is: 5\n"
+      "  bar\n"
+      "    Which is: 6",
+      msg1.c_str());
+
+  const std::string msg2(
+      EqFailure("foo", "6", foo_val, bar_val, false).failure_message());
+  EXPECT_STREQ(
+      "Expected equality of these values:\n"
+      "  foo\n"
+      "    Which is: 5\n"
+      "  6",
+      msg2.c_str());
+
+  const std::string msg3(
+      EqFailure("5", "bar", foo_val, bar_val, false).failure_message());
+  EXPECT_STREQ(
+      "Expected equality of these values:\n"
+      "  5\n"
+      "  bar\n"
+      "    Which is: 6",
+      msg3.c_str());
+
+  const std::string msg4(
+      EqFailure("5", "6", foo_val, bar_val, false).failure_message());
+  EXPECT_STREQ(
+      "Expected equality of these values:\n"
+      "  5\n"
+      "  6",
+      msg4.c_str());
+
+  const std::string msg5(
+      EqFailure("foo", "bar", std::string("\"x\""), std::string("\"y\""), true)
+          .failure_message());
+  EXPECT_STREQ(
+      "Expected equality of these values:\n"
+      "  foo\n"
+      "    Which is: \"x\"\n"
+      "  bar\n"
+      "    Which is: \"y\"\n"
+      "Ignoring case",
+      msg5.c_str());
+}
+
+TEST(AssertionTest, EqFailureWithDiff) {
+  const std::string left(
+      "1\\n2XXX\\n3\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12XXX\\n13\\n14\\n15");
+  const std::string right(
+      "1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n11\\n12\\n13\\n14");
+  const std::string msg1(
+      EqFailure("left", "right", left, right, false).failure_message());
+  EXPECT_STREQ(
+      "Expected equality of these values:\n"
+      "  left\n"
+      "    Which is: "
+      "1\\n2XXX\\n3\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12XXX\\n13\\n14\\n15\n"
+      "  right\n"
+      "    Which is: 1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n11\\n12\\n13\\n14\n"
+      "With diff:\n@@ -1,5 +1,6 @@\n 1\n-2XXX\n+2\n 3\n+4\n 5\n 6\n"
+      "@@ -7,8 +8,6 @@\n 8\n 9\n-10\n 11\n-12XXX\n+12\n 13\n 14\n-15\n",
+      msg1.c_str());
+}
+
+// Tests AppendUserMessage(), used for implementing the *EQ* macros.
+TEST(AssertionTest, AppendUserMessage) {
+  const std::string foo("foo");
+
+  Message msg;
+  EXPECT_STREQ("foo", AppendUserMessage(foo, msg).c_str());
+
+  msg << "bar";
+  EXPECT_STREQ("foo\nbar", AppendUserMessage(foo, msg).c_str());
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+#pragma option push -w-ccc -w-rch
+#endif
+
+// Tests ASSERT_TRUE.
+TEST(AssertionTest, ASSERT_TRUE) {
+  ASSERT_TRUE(2 > 1);  // NOLINT
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(2 < 1), "2 < 1");
+}
+
+// Tests ASSERT_TRUE(predicate) for predicates returning AssertionResult.
+TEST(AssertionTest, AssertTrueWithAssertionResult) {
+  ASSERT_TRUE(ResultIsEven(2));
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEven(3)),
+                       "Value of: ResultIsEven(3)\n"
+                       "  Actual: false (3 is odd)\n"
+                       "Expected: true");
+#endif
+  ASSERT_TRUE(ResultIsEvenNoExplanation(2));
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEvenNoExplanation(3)),
+                       "Value of: ResultIsEvenNoExplanation(3)\n"
+                       "  Actual: false (3 is odd)\n"
+                       "Expected: true");
+}
+
+// Tests ASSERT_FALSE.
+TEST(AssertionTest, ASSERT_FALSE) {
+  ASSERT_FALSE(2 < 1);  // NOLINT
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(2 > 1),
+                       "Value of: 2 > 1\n"
+                       "  Actual: true\n"
+                       "Expected: false");
+}
+
+// Tests ASSERT_FALSE(predicate) for predicates returning AssertionResult.
+TEST(AssertionTest, AssertFalseWithAssertionResult) {
+  ASSERT_FALSE(ResultIsEven(3));
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEven(2)),
+                       "Value of: ResultIsEven(2)\n"
+                       "  Actual: true (2 is even)\n"
+                       "Expected: false");
+#endif
+  ASSERT_FALSE(ResultIsEvenNoExplanation(3));
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEvenNoExplanation(2)),
+                       "Value of: ResultIsEvenNoExplanation(2)\n"
+                       "  Actual: true\n"
+                       "Expected: false");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them
+#pragma option pop
+#endif
+
+// Tests using ASSERT_EQ on double values.  The purpose is to make
+// sure that the specialization we did for integer and anonymous enums
+// isn't used for double arguments.
+TEST(ExpectTest, ASSERT_EQ_Double) {
+  // A success.
+  ASSERT_EQ(5.6, 5.6);
+
+  // A failure.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(5.1, 5.2), "5.1");
+}
+
+// Tests ASSERT_EQ.
+TEST(AssertionTest, ASSERT_EQ) {
+  ASSERT_EQ(5, 2 + 3);
+  // clang-format off
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(5, 2*3),
+                       "Expected equality of these values:\n"
+                       "  5\n"
+                       "  2*3\n"
+                       "    Which is: 6");
+  // clang-format on
+}
+
+// Tests ASSERT_EQ(NULL, pointer).
+TEST(AssertionTest, ASSERT_EQ_NULL) {
+  // A success.
+  const char* p = nullptr;
+  ASSERT_EQ(nullptr, p);
+
+  // A failure.
+  static int n = 0;
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(nullptr, &n), "  &n\n    Which is:");
+}
+
+// Tests ASSERT_EQ(0, non_pointer).  Since the literal 0 can be
+// treated as a null pointer by the compiler, we need to make sure
+// that ASSERT_EQ(0, non_pointer) isn't interpreted by Google Test as
+// ASSERT_EQ(static_cast<void*>(NULL), non_pointer).
+TEST(ExpectTest, ASSERT_EQ_0) {
+  int n = 0;
+
+  // A success.
+  ASSERT_EQ(0, n);
+
+  // A failure.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(0, 5.6), "  0\n  5.6");
+}
+
+// Tests ASSERT_NE.
+TEST(AssertionTest, ASSERT_NE) {
+  ASSERT_NE(6, 7);
+  EXPECT_FATAL_FAILURE(ASSERT_NE('a', 'a'),
+                       "Expected: ('a') != ('a'), "
+                       "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
+}
+
+// Tests ASSERT_LE.
+TEST(AssertionTest, ASSERT_LE) {
+  ASSERT_LE(2, 3);
+  ASSERT_LE(2, 2);
+  EXPECT_FATAL_FAILURE(ASSERT_LE(2, 0), "Expected: (2) <= (0), actual: 2 vs 0");
+}
+
+// Tests ASSERT_LT.
+TEST(AssertionTest, ASSERT_LT) {
+  ASSERT_LT(2, 3);
+  EXPECT_FATAL_FAILURE(ASSERT_LT(2, 2), "Expected: (2) < (2), actual: 2 vs 2");
+}
+
+// Tests ASSERT_GE.
+TEST(AssertionTest, ASSERT_GE) {
+  ASSERT_GE(2, 1);
+  ASSERT_GE(2, 2);
+  EXPECT_FATAL_FAILURE(ASSERT_GE(2, 3), "Expected: (2) >= (3), actual: 2 vs 3");
+}
+
+// Tests ASSERT_GT.
+TEST(AssertionTest, ASSERT_GT) {
+  ASSERT_GT(2, 1);
+  EXPECT_FATAL_FAILURE(ASSERT_GT(2, 2), "Expected: (2) > (2), actual: 2 vs 2");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowNothing() {}
+
+// Tests ASSERT_THROW.
+TEST(AssertionTest, ASSERT_THROW) {
+  ASSERT_THROW(ThrowAnInteger(), int);
+
+#ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowAnInteger(), bool),
+      "Expected: ThrowAnInteger() throws an exception of type bool.\n"
+      "  Actual: it throws a different type.");
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowRuntimeError("A description"), std::logic_error),
+      "Expected: ThrowRuntimeError(\"A description\") "
+      "throws an exception of type std::logic_error.\n  "
+      "Actual: it throws " ERROR_DESC
+      " "
+      "with description \"A description\".");
+#endif
+
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowNothing(), bool),
+      "Expected: ThrowNothing() throws an exception of type bool.\n"
+      "  Actual: it throws nothing.");
+}
+
+// Tests ASSERT_NO_THROW.
+TEST(AssertionTest, ASSERT_NO_THROW) {
+  ASSERT_NO_THROW(ThrowNothing());
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()),
+                       "Expected: ThrowAnInteger() doesn't throw an exception."
+                       "\n  Actual: it throws.");
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowRuntimeError("A description")),
+                       "Expected: ThrowRuntimeError(\"A description\") "
+                       "doesn't throw an exception.\n  "
+                       "Actual: it throws " ERROR_DESC
+                       " "
+                       "with description \"A description\".");
+}
+
+// Tests ASSERT_ANY_THROW.
+TEST(AssertionTest, ASSERT_ANY_THROW) {
+  ASSERT_ANY_THROW(ThrowAnInteger());
+  EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(ThrowNothing()),
+                       "Expected: ThrowNothing() throws an exception.\n"
+                       "  Actual: it doesn't.");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Makes sure we deal with the precedence of <<.  This test should
+// compile.
+TEST(AssertionTest, AssertPrecedence) {
+  ASSERT_EQ(1 < 2, true);
+  bool false_value = false;
+  ASSERT_EQ(true && false_value, false);
+}
+
+// A subroutine used by the following test.
+void TestEq1(int x) { ASSERT_EQ(1, x); }
+
+// Tests calling a test subroutine that's not part of a fixture.
+TEST(AssertionTest, NonFixtureSubroutine) {
+  EXPECT_FATAL_FAILURE(TestEq1(2), "  x\n    Which is: 2");
+}
+
+// An uncopyable class.
+class Uncopyable {
+ public:
+  explicit Uncopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+  bool operator==(const Uncopyable& rhs) const {
+    return value() == rhs.value();
+  }
+
+ private:
+  // This constructor deliberately has no implementation, as we don't
+  // want this class to be copyable.
+  Uncopyable(const Uncopyable&);  // NOLINT
+
+  int value_;
+};
+
+::std::ostream& operator<<(::std::ostream& os, const Uncopyable& value) {
+  return os << value.value();
+}
+
+bool IsPositiveUncopyable(const Uncopyable& x) { return x.value() > 0; }
+
+// A subroutine used by the following test.
+void TestAssertNonPositive() {
+  Uncopyable y(-1);
+  ASSERT_PRED1(IsPositiveUncopyable, y);
+}
+// A subroutine used by the following test.
+void TestAssertEqualsUncopyable() {
+  Uncopyable x(5);
+  Uncopyable y(-1);
+  ASSERT_EQ(x, y);
+}
+
+// Tests that uncopyable objects can be used in assertions.
+TEST(AssertionTest, AssertWorksWithUncopyableObject) {
+  Uncopyable x(5);
+  ASSERT_PRED1(IsPositiveUncopyable, x);
+  ASSERT_EQ(x, x);
+  EXPECT_FATAL_FAILURE(
+      TestAssertNonPositive(),
+      "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
+  EXPECT_FATAL_FAILURE(TestAssertEqualsUncopyable(),
+                       "Expected equality of these values:\n"
+                       "  x\n    Which is: 5\n  y\n    Which is: -1");
+}
+
+// Tests that uncopyable objects can be used in expects.
+TEST(AssertionTest, ExpectWorksWithUncopyableObject) {
+  Uncopyable x(5);
+  EXPECT_PRED1(IsPositiveUncopyable, x);
+  Uncopyable y(-1);
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_PRED1(IsPositiveUncopyable, y),
+      "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
+  EXPECT_EQ(x, x);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y),
+                          "Expected equality of these values:\n"
+                          "  x\n    Which is: 5\n  y\n    Which is: -1");
+}
+
+enum NamedEnum { kE1 = 0, kE2 = 1 };
+
+TEST(AssertionTest, NamedEnum) {
+  EXPECT_EQ(kE1, kE1);
+  EXPECT_LT(kE1, kE2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 1");
+}
+
+// Sun Studio and HP aCC2reject this code.
+#if !defined(__SUNPRO_CC) && !defined(__HP_aCC)
+
+// Tests using assertions with anonymous enums.
+enum {
+  kCaseA = -1,
+
+#ifdef GTEST_OS_LINUX
+
+  // We want to test the case where the size of the anonymous enum is
+  // larger than sizeof(int), to make sure our implementation of the
+  // assertions doesn't truncate the enums.  However, MSVC
+  // (incorrectly) doesn't allow an enum value to exceed the range of
+  // an int, so this has to be conditionally compiled.
+  //
+  // On Linux, kCaseB and kCaseA have the same value when truncated to
+  // int size.  We want to test whether this will confuse the
+  // assertions.
+  kCaseB = testing::internal::kMaxBiggestInt,
+
+#else
+
+  kCaseB = INT_MAX,
+
+#endif  // GTEST_OS_LINUX
+
+  kCaseC = 42
+};
+
+TEST(AssertionTest, AnonymousEnum) {
+#ifdef GTEST_OS_LINUX
+
+  EXPECT_EQ(static_cast<int>(kCaseA), static_cast<int>(kCaseB));
+
+#endif  // GTEST_OS_LINUX
+
+  EXPECT_EQ(kCaseA, kCaseA);
+  EXPECT_NE(kCaseA, kCaseB);
+  EXPECT_LT(kCaseA, kCaseB);
+  EXPECT_LE(kCaseA, kCaseB);
+  EXPECT_GT(kCaseB, kCaseA);
+  EXPECT_GE(kCaseA, kCaseA);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseB), "(kCaseA) >= (kCaseB)");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseC), "-1 vs 42");
+
+  ASSERT_EQ(kCaseA, kCaseA);
+  ASSERT_NE(kCaseA, kCaseB);
+  ASSERT_LT(kCaseA, kCaseB);
+  ASSERT_LE(kCaseA, kCaseB);
+  ASSERT_GT(kCaseB, kCaseA);
+  ASSERT_GE(kCaseA, kCaseA);
+
+#ifndef __BORLANDC__
+
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB), "  kCaseB\n    Which is: ");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC), "\n    Which is: 42");
+#endif
+
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC), "\n    Which is: -1");
+}
+
+#endif  // !GTEST_OS_MAC && !defined(__SUNPRO_CC)
+
+#ifdef GTEST_OS_WINDOWS
+
+static HRESULT UnexpectedHRESULTFailure() { return E_UNEXPECTED; }
+
+static HRESULT OkHRESULTSuccess() { return S_OK; }
+
+static HRESULT FalseHRESULTSuccess() { return S_FALSE; }
+
+// HRESULT assertion tests test both zero and non-zero
+// success codes as well as failure message for each.
+//
+// Windows CE doesn't support message texts.
+TEST(HRESULTAssertionTest, EXPECT_HRESULT_SUCCEEDED) {
+  EXPECT_HRESULT_SUCCEEDED(S_OK);
+  EXPECT_HRESULT_SUCCEEDED(S_FALSE);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
+                          "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
+                          "  Actual: 0x8000FFFF");
+}
+
+TEST(HRESULTAssertionTest, ASSERT_HRESULT_SUCCEEDED) {
+  ASSERT_HRESULT_SUCCEEDED(S_OK);
+  ASSERT_HRESULT_SUCCEEDED(S_FALSE);
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
+                       "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
+                       "  Actual: 0x8000FFFF");
+}
+
+TEST(HRESULTAssertionTest, EXPECT_HRESULT_FAILED) {
+  EXPECT_HRESULT_FAILED(E_UNEXPECTED);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(OkHRESULTSuccess()),
+                          "Expected: (OkHRESULTSuccess()) fails.\n"
+                          "  Actual: 0x0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(FalseHRESULTSuccess()),
+                          "Expected: (FalseHRESULTSuccess()) fails.\n"
+                          "  Actual: 0x1");
+}
+
+TEST(HRESULTAssertionTest, ASSERT_HRESULT_FAILED) {
+  ASSERT_HRESULT_FAILED(E_UNEXPECTED);
+
+#ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(OkHRESULTSuccess()),
+                       "Expected: (OkHRESULTSuccess()) fails.\n"
+                       "  Actual: 0x0");
+#endif
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(FalseHRESULTSuccess()),
+                       "Expected: (FalseHRESULTSuccess()) fails.\n"
+                       "  Actual: 0x1");
+}
+
+// Tests that streaming to the HRESULT macros works.
+TEST(HRESULTAssertionTest, Streaming) {
+  EXPECT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
+  ASSERT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
+  EXPECT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
+  ASSERT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_SUCCEEDED(E_UNEXPECTED)
+                              << "expected failure",
+                          "expected failure");
+
+#ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_SUCCEEDED(E_UNEXPECTED)
+                           << "expected failure",
+                       "expected failure");
+#endif
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(S_OK) << "expected failure",
+                          "expected failure");
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(S_OK) << "expected failure",
+                       "expected failure");
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// The following code intentionally tests a suboptimal syntax.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-else"
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+// Tests that the assertion macros behave like single statements.
+TEST(AssertionSyntaxTest, BasicAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    ASSERT_TRUE(false) << "This should never be executed; "
+                          "It's a compilation test only.";
+
+  if (AlwaysTrue())
+    EXPECT_FALSE(false);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse()) ASSERT_LT(1, 3);
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    EXPECT_GT(3, 2) << "";
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+// Tests that the compiler will not complain about unreachable code in the
+// EXPECT_THROW/EXPECT_ANY_THROW/EXPECT_NO_THROW macros.
+TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
+  int n = 0;
+
+  EXPECT_THROW(throw 1, int);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(n++, int), "");
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(throw n, const char*), "");
+  EXPECT_NO_THROW(n++);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(throw 1), "");
+  EXPECT_ANY_THROW(throw 1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(n++), "");
+}
+
+TEST(ExpectThrowTest, DoesNotGenerateDuplicateCatchClauseWarning) {
+  EXPECT_THROW(throw std::exception(), std::exception);
+}
+
+// The following code intentionally tests a suboptimal syntax.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-else"
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+TEST(AssertionSyntaxTest, ExceptionAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse()) EXPECT_THROW(ThrowNothing(), bool);
+
+  if (AlwaysTrue())
+    EXPECT_THROW(ThrowAnInteger(), int);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse()) EXPECT_NO_THROW(ThrowAnInteger());
+
+  if (AlwaysTrue())
+    EXPECT_NO_THROW(ThrowNothing());
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse()) EXPECT_ANY_THROW(ThrowNothing());
+
+  if (AlwaysTrue())
+    EXPECT_ANY_THROW(ThrowAnInteger());
+  else
+    ;  // NOLINT
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// The following code intentionally tests a suboptimal syntax.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-else"
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+TEST(AssertionSyntaxTest, NoFatalFailureAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    EXPECT_NO_FATAL_FAILURE(FAIL())
+        << "This should never be executed. " << "It's a compilation test only.";
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_NO_FATAL_FAILURE(FAIL()) << "";
+  else
+    ;  // NOLINT
+
+  if (AlwaysTrue())
+    EXPECT_NO_FATAL_FAILURE(SUCCEED());
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    ASSERT_NO_FATAL_FAILURE(SUCCEED());
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+// Tests that the assertion macros work well with switch statements.
+TEST(AssertionSyntaxTest, WorksWithSwitch) {
+  switch (0) {
+    case 1:
+      break;
+    default:
+      ASSERT_TRUE(true);
+  }
+
+  switch (0)
+  case 0:
+    EXPECT_FALSE(false) << "EXPECT_FALSE failed in switch case";
+
+  // Binary assertions are implemented using a different code path
+  // than the Boolean assertions.  Hence we test them separately.
+  switch (0) {
+    case 1:
+    default:
+      ASSERT_EQ(1, 1) << "ASSERT_EQ failed in default switch handler";
+  }
+
+  switch (0)
+  case 0:
+    EXPECT_NE(1, 2);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowAString() { throw "std::string"; }
+
+// Test that the exception assertion macros compile and work with const
+// type qualifier.
+TEST(AssertionSyntaxTest, WorksWithConst) {
+  ASSERT_THROW(ThrowAString(), const char*);
+
+  EXPECT_THROW(ThrowAString(), const char*);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+}  // namespace
+
+namespace testing {
+
+// Tests that Google Test tracks SUCCEED*.
+TEST(SuccessfulAssertionTest, SUCCEED) {
+  SUCCEED();
+  SUCCEED() << "OK";
+  EXPECT_EQ(2, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful EXPECT_*.
+TEST(SuccessfulAssertionTest, EXPECT) {
+  EXPECT_TRUE(true);
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful EXPECT_STR*.
+TEST(SuccessfulAssertionTest, EXPECT_STR) {
+  EXPECT_STREQ("", "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful ASSERT_*.
+TEST(SuccessfulAssertionTest, ASSERT) {
+  ASSERT_TRUE(true);
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful ASSERT_STR*.
+TEST(SuccessfulAssertionTest, ASSERT_STR) {
+  ASSERT_STREQ("", "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+}  // namespace testing
+
+namespace {
+
+// Tests the message streaming variation of assertions.
+
+TEST(AssertionWithMessageTest, EXPECT) {
+  EXPECT_EQ(1, 1) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(1, 1) << "Expected failure #1.",
+                          "Expected failure #1");
+  EXPECT_LE(1, 2) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(1, 0) << "Expected failure #2.",
+                          "Expected failure #2.");
+  EXPECT_GE(1, 0) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(1, 2) << "Expected failure #3.",
+                          "Expected failure #3.");
+
+  EXPECT_STREQ("1", "1") << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("1", "1") << "Expected failure #4.",
+                          "Expected failure #4.");
+  EXPECT_STRCASEEQ("a", "A") << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("a", "A") << "Expected failure #5.",
+                          "Expected failure #5.");
+
+  EXPECT_FLOAT_EQ(1, 1) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1, 1.2) << "Expected failure #6.",
+                          "Expected failure #6.");
+  EXPECT_NEAR(1, 1.1, 0.2) << "This should succeed.";
+}
+
+TEST(AssertionWithMessageTest, ASSERT) {
+  ASSERT_EQ(1, 1) << "This should succeed.";
+  ASSERT_NE(1, 2) << "This should succeed.";
+  ASSERT_LE(1, 2) << "This should succeed.";
+  ASSERT_LT(1, 2) << "This should succeed.";
+  ASSERT_GE(1, 0) << "This should succeed.";
+  EXPECT_FATAL_FAILURE(ASSERT_GT(1, 2) << "Expected failure.",
+                       "Expected failure.");
+}
+
+TEST(AssertionWithMessageTest, ASSERT_STR) {
+  ASSERT_STREQ("1", "1") << "This should succeed.";
+  ASSERT_STRNE("1", "2") << "This should succeed.";
+  ASSERT_STRCASEEQ("a", "A") << "This should succeed.";
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("a", "A") << "Expected failure.",
+                       "Expected failure.");
+}
+
+TEST(AssertionWithMessageTest, ASSERT_FLOATING) {
+  ASSERT_FLOAT_EQ(1, 1) << "This should succeed.";
+  ASSERT_DOUBLE_EQ(1, 1) << "This should succeed.";
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1, 1.2, 0.1) << "Expect failure.",  // NOLINT
+                       "Expect failure.");
+}
+
+// Tests using ASSERT_FALSE with a streamed message.
+TEST(AssertionWithMessageTest, ASSERT_FALSE) {
+  ASSERT_FALSE(false) << "This shouldn't fail.";
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_FALSE(true) << "Expected failure: " << 2 << " > " << 1
+                           << " evaluates to " << true;
+      },
+      "Expected failure");
+}
+
+// Tests using FAIL with a streamed message.
+TEST(AssertionWithMessageTest, FAIL) { EXPECT_FATAL_FAILURE(FAIL() << 0, "0"); }
+
+// Tests using SUCCEED with a streamed message.
+TEST(AssertionWithMessageTest, SUCCEED) { SUCCEED() << "Success == " << 1; }
+
+// Tests using ASSERT_TRUE with a streamed message.
+TEST(AssertionWithMessageTest, ASSERT_TRUE) {
+  ASSERT_TRUE(true) << "This should succeed.";
+  ASSERT_TRUE(true) << true;
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_TRUE(false) << static_cast<const char*>(nullptr)
+                           << static_cast<char*>(nullptr);
+      },
+      "(null)(null)");
+}
+
+#ifdef GTEST_OS_WINDOWS
+// Tests using wide strings in assertion messages.
+TEST(AssertionWithMessageTest, WideStringMessage) {
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_TRUE(false) << L"This failure is expected.\x8119";
+      },
+      "This failure is expected.");
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_EQ(1, 2) << "This failure is " << L"expected too.\x8120";
+      },
+      "This failure is expected too.");
+}
+#endif  // GTEST_OS_WINDOWS
+
+// Tests EXPECT_TRUE.
+TEST(ExpectTest, EXPECT_TRUE) {
+  EXPECT_TRUE(true) << "Intentional success";
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "Intentional failure #1.",
+                          "Intentional failure #1.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "Intentional failure #2.",
+                          "Intentional failure #2.");
+  EXPECT_TRUE(2 > 1);  // NOLINT
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 < 1),
+                          "Value of: 2 < 1\n"
+                          "  Actual: false\n"
+                          "Expected: true");
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 > 3), "2 > 3");
+}
+
+// Tests EXPECT_TRUE(predicate) for predicates returning AssertionResult.
+TEST(ExpectTest, ExpectTrueWithAssertionResult) {
+  EXPECT_TRUE(ResultIsEven(2));
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEven(3)),
+                          "Value of: ResultIsEven(3)\n"
+                          "  Actual: false (3 is odd)\n"
+                          "Expected: true");
+  EXPECT_TRUE(ResultIsEvenNoExplanation(2));
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEvenNoExplanation(3)),
+                          "Value of: ResultIsEvenNoExplanation(3)\n"
+                          "  Actual: false (3 is odd)\n"
+                          "Expected: true");
+}
+
+// Tests EXPECT_FALSE with a streamed message.
+TEST(ExpectTest, EXPECT_FALSE) {
+  EXPECT_FALSE(2 < 1);  // NOLINT
+  EXPECT_FALSE(false) << "Intentional success";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "Intentional failure #1.",
+                          "Intentional failure #1.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "Intentional failure #2.",
+                          "Intentional failure #2.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 > 1),
+                          "Value of: 2 > 1\n"
+                          "  Actual: true\n"
+                          "Expected: false");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 < 3), "2 < 3");
+}
+
+// Tests EXPECT_FALSE(predicate) for predicates returning AssertionResult.
+TEST(ExpectTest, ExpectFalseWithAssertionResult) {
+  EXPECT_FALSE(ResultIsEven(3));
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEven(2)),
+                          "Value of: ResultIsEven(2)\n"
+                          "  Actual: true (2 is even)\n"
+                          "Expected: false");
+  EXPECT_FALSE(ResultIsEvenNoExplanation(3));
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEvenNoExplanation(2)),
+                          "Value of: ResultIsEvenNoExplanation(2)\n"
+                          "  Actual: true\n"
+                          "Expected: false");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them
+#pragma option pop
+#endif
+
+// Tests EXPECT_EQ.
+TEST(ExpectTest, EXPECT_EQ) {
+  EXPECT_EQ(5, 2 + 3);
+  // clang-format off
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2*3),
+                          "Expected equality of these values:\n"
+                          "  5\n"
+                          "  2*3\n"
+                          "    Which is: 6");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2 - 3), "2 - 3");
+  // clang-format on
+}
+
+// Tests using EXPECT_EQ on double values.  The purpose is to make
+// sure that the specialization we did for integer and anonymous enums
+// isn't used for double arguments.
+TEST(ExpectTest, EXPECT_EQ_Double) {
+  // A success.
+  EXPECT_EQ(5.6, 5.6);
+
+  // A failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5.1, 5.2), "5.1");
+}
+
+// Tests EXPECT_EQ(NULL, pointer).
+TEST(ExpectTest, EXPECT_EQ_NULL) {
+  // A success.
+  const char* p = nullptr;
+  EXPECT_EQ(nullptr, p);
+
+  // A failure.
+  int n = 0;
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(nullptr, &n), "  &n\n    Which is:");
+}
+
+// Tests EXPECT_EQ(0, non_pointer).  Since the literal 0 can be
+// treated as a null pointer by the compiler, we need to make sure
+// that EXPECT_EQ(0, non_pointer) isn't interpreted by Google Test as
+// EXPECT_EQ(static_cast<void*>(NULL), non_pointer).
+TEST(ExpectTest, EXPECT_EQ_0) {
+  int n = 0;
+
+  // A success.
+  EXPECT_EQ(0, n);
+
+  // A failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(0, 5.6), "  0\n  5.6");
+}
+
+// Tests EXPECT_NE.
+TEST(ExpectTest, EXPECT_NE) {
+  EXPECT_NE(6, 7);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE('a', 'a'),
+                          "Expected: ('a') != ('a'), "
+                          "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(2, 2), "2");
+  char* const p0 = nullptr;
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(p0, p0), "p0");
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  char* const p1 = reinterpret_cast<char*>(pv1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(p1, p1), "p1");
+}
+
+// Tests EXPECT_LE.
+TEST(ExpectTest, EXPECT_LE) {
+  EXPECT_LE(2, 3);
+  EXPECT_LE(2, 2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_LE(2, 0),
+                          "Expected: (2) <= (0), actual: 2 vs 0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LE(1.1, 0.9), "(1.1) <= (0.9)");
+}
+
+// Tests EXPECT_LT.
+TEST(ExpectTest, EXPECT_LT) {
+  EXPECT_LT(2, 3);
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 2),
+                          "Expected: (2) < (2), actual: 2 vs 2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1), "(2) < (1)");
+}
+
+// Tests EXPECT_GE.
+TEST(ExpectTest, EXPECT_GE) {
+  EXPECT_GE(2, 1);
+  EXPECT_GE(2, 2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(2, 3),
+                          "Expected: (2) >= (3), actual: 2 vs 3");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(0.9, 1.1), "(0.9) >= (1.1)");
+}
+
+// Tests EXPECT_GT.
+TEST(ExpectTest, EXPECT_GT) {
+  EXPECT_GT(2, 1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 2),
+                          "Expected: (2) > (2), actual: 2 vs 2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 3), "(2) > (3)");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests EXPECT_THROW.
+TEST(ExpectTest, EXPECT_THROW) {
+  EXPECT_THROW(ThrowAnInteger(), int);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool),
+                          "Expected: ThrowAnInteger() throws an exception of "
+                          "type bool.\n  Actual: it throws a different type.");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THROW(ThrowRuntimeError("A description"), std::logic_error),
+      "Expected: ThrowRuntimeError(\"A description\") "
+      "throws an exception of type std::logic_error.\n  "
+      "Actual: it throws " ERROR_DESC
+      " "
+      "with description \"A description\".");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THROW(ThrowNothing(), bool),
+      "Expected: ThrowNothing() throws an exception of type bool.\n"
+      "  Actual: it throws nothing.");
+}
+
+// Tests EXPECT_NO_THROW.
+TEST(ExpectTest, EXPECT_NO_THROW) {
+  EXPECT_NO_THROW(ThrowNothing());
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()),
+                          "Expected: ThrowAnInteger() doesn't throw an "
+                          "exception.\n  Actual: it throws.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowRuntimeError("A description")),
+                          "Expected: ThrowRuntimeError(\"A description\") "
+                          "doesn't throw an exception.\n  "
+                          "Actual: it throws " ERROR_DESC
+                          " "
+                          "with description \"A description\".");
+}
+
+// Tests EXPECT_ANY_THROW.
+TEST(ExpectTest, EXPECT_ANY_THROW) {
+  EXPECT_ANY_THROW(ThrowAnInteger());
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(ThrowNothing()),
+                          "Expected: ThrowNothing() throws an exception.\n"
+                          "  Actual: it doesn't.");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Make sure we deal with the precedence of <<.
+TEST(ExpectTest, ExpectPrecedence) {
+  EXPECT_EQ(1 < 2, true);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(true, true && false),
+                          "  true && false\n    Which is: false");
+}
+
+// Tests the StreamableToString() function.
+
+// Tests using StreamableToString() on a scalar.
+TEST(StreamableToStringTest, Scalar) {
+  EXPECT_STREQ("5", StreamableToString(5).c_str());
+}
+
+// Tests using StreamableToString() on a non-char pointer.
+TEST(StreamableToStringTest, Pointer) {
+  int n = 0;
+  int* p = &n;
+  EXPECT_STRNE("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using StreamableToString() on a NULL non-char pointer.
+TEST(StreamableToStringTest, NullPointer) {
+  int* p = nullptr;
+  EXPECT_STREQ("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using StreamableToString() on a C string.
+TEST(StreamableToStringTest, CString) {
+  EXPECT_STREQ("Foo", StreamableToString("Foo").c_str());
+}
+
+// Tests using StreamableToString() on a NULL C string.
+TEST(StreamableToStringTest, NullCString) {
+  char* p = nullptr;
+  EXPECT_STREQ("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using streamable values as assertion messages.
+
+// Tests using std::string as an assertion message.
+TEST(StreamableTest, string) {
+  static const std::string str(
+      "This failure message is a std::string, and is expected.");
+  EXPECT_FATAL_FAILURE(FAIL() << str, str.c_str());
+}
+
+// Tests that we can output strings containing embedded NULs.
+// Limited to Linux because we can only do this with std::string's.
+TEST(StreamableTest, stringWithEmbeddedNUL) {
+  static const char char_array_with_nul[] =
+      "Here's a NUL\0 and some more string";
+  static const std::string string_with_nul(
+      char_array_with_nul,
+      sizeof(char_array_with_nul) - 1);  // drops the trailing NUL
+  EXPECT_FATAL_FAILURE(FAIL() << string_with_nul,
+                       "Here's a NUL\\0 and some more string");
+}
+
+// Tests that we can output a NUL char.
+TEST(StreamableTest, NULChar) {
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        FAIL() << "A NUL" << '\0' << " and some more string";
+      },
+      "A NUL\\0 and some more string");
+}
+
+// Tests using int as an assertion message.
+TEST(StreamableTest, int) { EXPECT_FATAL_FAILURE(FAIL() << 900913, "900913"); }
+
+// Tests using NULL char pointer as an assertion message.
+//
+// In MSVC, streaming a NULL char * causes access violation.  Google Test
+// implemented a workaround (substituting "(null)" for NULL).  This
+// tests whether the workaround works.
+TEST(StreamableTest, NullCharPtr) {
+  EXPECT_FATAL_FAILURE(FAIL() << static_cast<const char*>(nullptr), "(null)");
+}
+
+// Tests that basic IO manipulators (endl, ends, and flush) can be
+// streamed to testing::Message.
+TEST(StreamableTest, BasicIoManip) {
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        FAIL() << "Line 1." << std::endl
+               << "A NUL char " << std::ends << std::flush << " in line 2.";
+      },
+      "Line 1.\nA NUL char \\0 in line 2.");
+}
+
+// Tests the macros that haven't been covered so far.
+
+void AddFailureHelper(bool* aborted) {
+  *aborted = true;
+  ADD_FAILURE() << "Intentional failure.";
+  *aborted = false;
+}
+
+// Tests ADD_FAILURE.
+TEST(MacroTest, ADD_FAILURE) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(AddFailureHelper(&aborted), "Intentional failure.");
+  EXPECT_FALSE(aborted);
+}
+
+// Tests ADD_FAILURE_AT.
+TEST(MacroTest, ADD_FAILURE_AT) {
+  // Verifies that ADD_FAILURE_AT does generate a nonfatal failure and
+  // the failure message contains the user-streamed part.
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42) << "Wrong!", "Wrong!");
+
+  // Verifies that the user-streamed part is optional.
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42), "Failed");
+
+  // Unfortunately, we cannot verify that the failure message contains
+  // the right file path and line number the same way, as
+  // EXPECT_NONFATAL_FAILURE() doesn't get to see the file path and
+  // line number.  Instead, we do that in googletest-output-test_.cc.
+}
+
+// Tests FAIL.
+TEST(MacroTest, FAIL) {
+  EXPECT_FATAL_FAILURE(FAIL(), "Failed");
+  EXPECT_FATAL_FAILURE(FAIL() << "Intentional failure.",
+                       "Intentional failure.");
+}
+
+// Tests GTEST_FAIL_AT.
+TEST(MacroTest, GTEST_FAIL_AT) {
+  // Verifies that GTEST_FAIL_AT does generate a fatal failure and
+  // the failure message contains the user-streamed part.
+  EXPECT_FATAL_FAILURE(GTEST_FAIL_AT("foo.cc", 42) << "Wrong!", "Wrong!");
+
+  // Verifies that the user-streamed part is optional.
+  EXPECT_FATAL_FAILURE(GTEST_FAIL_AT("foo.cc", 42), "Failed");
+
+  // See the ADD_FAIL_AT test above to see how we test that the failure message
+  // contains the right filename and line number -- the same applies here.
+}
+
+// Tests SUCCEED
+TEST(MacroTest, SUCCEED) {
+  SUCCEED();
+  SUCCEED() << "Explicit success.";
+}
+
+// Tests for EXPECT_EQ() and ASSERT_EQ().
+//
+// These tests fail *intentionally*, s.t. the failure messages can be
+// generated and tested.
+//
+// We have different tests for different argument types.
+
+// Tests using bool values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Bool) {
+  EXPECT_EQ(true, true);
+  EXPECT_FATAL_FAILURE(
+      {
+        bool false_value = false;
+        ASSERT_EQ(false_value, true);
+      },
+      "  false_value\n    Which is: false\n  true");
+}
+
+// Tests using int values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Int) {
+  ASSERT_EQ(32, 32);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(32, 33), "  32\n  33");
+}
+
+// Tests using time_t values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Time_T) {
+  EXPECT_EQ(static_cast<time_t>(0), static_cast<time_t>(0));
+  EXPECT_FATAL_FAILURE(
+      ASSERT_EQ(static_cast<time_t>(0), static_cast<time_t>(1234)), "1234");
+}
+
+// Tests using char values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Char) {
+  ASSERT_EQ('z', 'z');
+  const char ch = 'b';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ('\0', ch), "  ch\n    Which is: 'b'");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ('a', ch), "  ch\n    Which is: 'b'");
+}
+
+// Tests using wchar_t values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, WideChar) {
+  EXPECT_EQ(L'b', L'b');
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'\0', L'x'),
+                          "Expected equality of these values:\n"
+                          "  L'\0'\n"
+                          "    Which is: L'\0' (0, 0x0)\n"
+                          "  L'x'\n"
+                          "    Which is: L'x' (120, 0x78)");
+
+  static wchar_t wchar;
+  wchar = L'b';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'a', wchar), "wchar");
+  wchar = 0x8119;
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<wchar_t>(0x8120), wchar),
+                       "  wchar\n    Which is: L'");
+}
+
+// Tests using ::std::string values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, StdString) {
+  // Compares a const char* to an std::string that has identical
+  // content.
+  ASSERT_EQ("Test", ::std::string("Test"));
+
+  // Compares two identical std::strings.
+  static const ::std::string str1("A * in the middle");
+  static const ::std::string str2(str1);
+  EXPECT_EQ(str1, str2);
+
+  // Compares a const char* to an std::string that has different
+  // content
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ("Test", ::std::string("test")), "\"test\"");
+
+  // Compares an std::string to a char* that has different content.
+  char* const p1 = const_cast<char*>("foo");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(::std::string("bar"), p1), "p1");
+
+  // Compares two std::strings that have different contents, one of
+  // which having a NUL character in the middle.  This should fail.
+  static ::std::string str3(str1);
+  str3.at(2) = '\0';
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(str1, str3),
+                       "  str3\n    Which is: \"A \\0 in the middle\"");
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Tests using ::std::wstring values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, StdWideString) {
+  // Compares two identical std::wstrings.
+  const ::std::wstring wstr1(L"A * in the middle");
+  const ::std::wstring wstr2(wstr1);
+  ASSERT_EQ(wstr1, wstr2);
+
+  // Compares an std::wstring to a const wchar_t* that has identical
+  // content.
+  const wchar_t kTestX8119[] = {'T', 'e', 's', 't', 0x8119, '\0'};
+  EXPECT_EQ(::std::wstring(kTestX8119), kTestX8119);
+
+  // Compares an std::wstring to a const wchar_t* that has different
+  // content.
+  const wchar_t kTestX8120[] = {'T', 'e', 's', 't', 0x8120, '\0'};
+  EXPECT_NONFATAL_FAILURE(
+      {  // NOLINT
+        EXPECT_EQ(::std::wstring(kTestX8119), kTestX8120);
+      },
+      "kTestX8120");
+
+  // Compares two std::wstrings that have different contents, one of
+  // which having a NUL character in the middle.
+  ::std::wstring wstr3(wstr1);
+  wstr3.at(2) = L'\0';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(wstr1, wstr3), "wstr3");
+
+  // Compares a wchar_t* to an std::wstring that has different
+  // content.
+  EXPECT_FATAL_FAILURE(
+      {  // NOLINT
+        ASSERT_EQ(const_cast<wchar_t*>(L"foo"), ::std::wstring(L"bar"));
+      },
+      "");
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests using char pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, CharPointer) {
+  char* const p0 = nullptr;
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  void* pv2 = (void*)0xABC0;  // NOLINT
+  char* const p1 = reinterpret_cast<char*>(pv1);
+  char* const p2 = reinterpret_cast<char*>(pv2);
+  ASSERT_EQ(p1, p1);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2), "  p2\n    Which is:");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2), "  p2\n    Which is:");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(reinterpret_cast<char*>(0x1234),
+                                 reinterpret_cast<char*>(0xABC0)),
+                       "ABC0");
+}
+
+// Tests using wchar_t pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, WideCharPointer) {
+  wchar_t* const p0 = nullptr;
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  void* pv2 = (void*)0xABC0;  // NOLINT
+  wchar_t* const p1 = reinterpret_cast<wchar_t*>(pv1);
+  wchar_t* const p2 = reinterpret_cast<wchar_t*>(pv2);
+  EXPECT_EQ(p0, p0);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2), "  p2\n    Which is:");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2), "  p2\n    Which is:");
+  void* pv3 = (void*)0x1234;  // NOLINT
+  void* pv4 = (void*)0xABC0;  // NOLINT
+  const wchar_t* p3 = reinterpret_cast<const wchar_t*>(pv3);
+  const wchar_t* p4 = reinterpret_cast<const wchar_t*>(pv4);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p3, p4), "p4");
+}
+
+// Tests using other types of pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, OtherPointer) {
+  ASSERT_EQ(static_cast<const int*>(nullptr), static_cast<const int*>(nullptr));
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<const int*>(nullptr),
+                                 reinterpret_cast<const int*>(0x1234)),
+                       "0x1234");
+}
+
+// A class that supports binary comparison operators but not streaming.
+class UnprintableChar {
+ public:
+  explicit UnprintableChar(char ch) : char_(ch) {}
+
+  bool operator==(const UnprintableChar& rhs) const {
+    return char_ == rhs.char_;
+  }
+  bool operator!=(const UnprintableChar& rhs) const {
+    return char_ != rhs.char_;
+  }
+  bool operator<(const UnprintableChar& rhs) const { return char_ < rhs.char_; }
+  bool operator<=(const UnprintableChar& rhs) const {
+    return char_ <= rhs.char_;
+  }
+  bool operator>(const UnprintableChar& rhs) const { return char_ > rhs.char_; }
+  bool operator>=(const UnprintableChar& rhs) const {
+    return char_ >= rhs.char_;
+  }
+
+ private:
+  char char_;
+};
+
+// Tests that ASSERT_EQ() and friends don't require the arguments to
+// be printable.
+TEST(ComparisonAssertionTest, AcceptsUnprintableArgs) {
+  const UnprintableChar x('x'), y('y');
+  ASSERT_EQ(x, x);
+  EXPECT_NE(x, y);
+  ASSERT_LT(x, y);
+  EXPECT_LE(x, y);
+  ASSERT_GT(y, x);
+  EXPECT_GE(x, x);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <78>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <79>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(y, y), "1-byte object <79>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <78>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <79>");
+
+  // Code tested by EXPECT_FATAL_FAILURE cannot reference local
+  // variables, so we have to write UnprintableChar('x') instead of x.
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_NE(UnprintableChar('x'), UnprintableChar('x')),
+                       "1-byte object <78>");
+  EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
+                       "1-byte object <78>");
+#endif
+  EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
+                       "1-byte object <79>");
+  EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
+                       "1-byte object <78>");
+  EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
+                       "1-byte object <79>");
+}
+
+// Tests the FRIEND_TEST macro.
+
+// This class has a private member we want to test.  We will test it
+// both in a TEST and in a TEST_F.
+class Foo {
+ public:
+  Foo() = default;
+
+ private:
+  int Bar() const { return 1; }
+
+  // Declares the friend tests that can access the private member
+  // Bar().
+  FRIEND_TEST(FRIEND_TEST_Test, TEST);
+  FRIEND_TEST(FRIEND_TEST_Test2, TEST_F);
+};
+
+// Tests that the FRIEND_TEST declaration allows a TEST to access a
+// class's private members.  This should compile.
+TEST(FRIEND_TEST_Test, TEST) { ASSERT_EQ(1, Foo().Bar()); }
+
+// The fixture needed to test using FRIEND_TEST with TEST_F.
+class FRIEND_TEST_Test2 : public Test {
+ protected:
+  Foo foo;
+};
+
+// Tests that the FRIEND_TEST declaration allows a TEST_F to access a
+// class's private members.  This should compile.
+TEST_F(FRIEND_TEST_Test2, TEST_F) { ASSERT_EQ(1, foo.Bar()); }
+
+// Tests the life cycle of Test objects.
+
+// The test fixture for testing the life cycle of Test objects.
+//
+// This class counts the number of live test objects that uses this
+// fixture.
+class TestLifeCycleTest : public Test {
+ protected:
+  // Constructor.  Increments the number of test objects that uses
+  // this fixture.
+  TestLifeCycleTest() { count_++; }
+
+  // Destructor.  Decrements the number of test objects that uses this
+  // fixture.
+  ~TestLifeCycleTest() override { count_--; }
+
+  // Returns the number of live test objects that uses this fixture.
+  int count() const { return count_; }
+
+ private:
+  static int count_;
+};
+
+int TestLifeCycleTest::count_ = 0;
+
+// Tests the life cycle of test objects.
+TEST_F(TestLifeCycleTest, Test1) {
+  // There should be only one test object in this test case that's
+  // currently alive.
+  ASSERT_EQ(1, count());
+}
+
+// Tests the life cycle of test objects.
+TEST_F(TestLifeCycleTest, Test2) {
+  // After Test1 is done and Test2 is started, there should still be
+  // only one live test object, as the object for Test1 should've been
+  // deleted.
+  ASSERT_EQ(1, count());
+}
+
+}  // namespace
+
+// Tests that the copy constructor works when it is NOT optimized away by
+// the compiler.
+TEST(AssertionResultTest, CopyConstructorWorksWhenNotOptimied) {
+  // Checks that the copy constructor doesn't try to dereference NULL pointers
+  // in the source object.
+  AssertionResult r1 = AssertionSuccess();
+  AssertionResult r2 = r1;
+  // The following line is added to prevent the compiler from optimizing
+  // away the constructor call.
+  r1 << "abc";
+
+  AssertionResult r3 = r1;
+  EXPECT_EQ(static_cast<bool>(r3), static_cast<bool>(r1));
+  EXPECT_STREQ("abc", r1.message());
+}
+
+// Tests that AssertionSuccess and AssertionFailure construct
+// AssertionResult objects as expected.
+TEST(AssertionResultTest, ConstructionWorks) {
+  AssertionResult r1 = AssertionSuccess();
+  EXPECT_TRUE(r1);
+  EXPECT_STREQ("", r1.message());
+
+  AssertionResult r2 = AssertionSuccess() << "abc";
+  EXPECT_TRUE(r2);
+  EXPECT_STREQ("abc", r2.message());
+
+  AssertionResult r3 = AssertionFailure();
+  EXPECT_FALSE(r3);
+  EXPECT_STREQ("", r3.message());
+
+  AssertionResult r4 = AssertionFailure() << "def";
+  EXPECT_FALSE(r4);
+  EXPECT_STREQ("def", r4.message());
+
+  AssertionResult r5 = AssertionFailure(Message() << "ghi");
+  EXPECT_FALSE(r5);
+  EXPECT_STREQ("ghi", r5.message());
+}
+
+// Tests that the negation flips the predicate result but keeps the message.
+TEST(AssertionResultTest, NegationWorks) {
+  AssertionResult r1 = AssertionSuccess() << "abc";
+  EXPECT_FALSE(!r1);
+  EXPECT_STREQ("abc", (!r1).message());
+
+  AssertionResult r2 = AssertionFailure() << "def";
+  EXPECT_TRUE(!r2);
+  EXPECT_STREQ("def", (!r2).message());
+}
+
+TEST(AssertionResultTest, StreamingWorks) {
+  AssertionResult r = AssertionSuccess();
+  r << "abc" << 'd' << 0 << true;
+  EXPECT_STREQ("abcd0true", r.message());
+}
+
+TEST(AssertionResultTest, CanStreamOstreamManipulators) {
+  AssertionResult r = AssertionSuccess();
+  r << "Data" << std::endl << std::flush << std::ends << "Will be visible";
+  EXPECT_STREQ("Data\n\\0Will be visible", r.message());
+}
+
+// The next test uses explicit conversion operators
+
+TEST(AssertionResultTest, ConstructibleFromContextuallyConvertibleToBool) {
+  struct ExplicitlyConvertibleToBool {
+    explicit operator bool() const { return value; }
+    bool value;
+  };
+  ExplicitlyConvertibleToBool v1 = {false};
+  ExplicitlyConvertibleToBool v2 = {true};
+  EXPECT_FALSE(v1);
+  EXPECT_TRUE(v2);
+}
+
+struct ConvertibleToAssertionResult {
+  operator AssertionResult() const { return AssertionResult(true); }
+};
+
+TEST(AssertionResultTest, ConstructibleFromImplicitlyConvertible) {
+  ConvertibleToAssertionResult obj;
+  EXPECT_TRUE(obj);
+}
+
+// Tests streaming a user type whose definition and operator << are
+// both in the global namespace.
+class Base {
+ public:
+  explicit Base(int an_x) : x_(an_x) {}
+  int x() const { return x_; }
+
+ private:
+  int x_;
+};
+std::ostream& operator<<(std::ostream& os, const Base& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os, const Base* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+
+TEST(MessageTest, CanStreamUserTypeInGlobalNameSpace) {
+  Message msg;
+  Base a(1);
+
+  msg << a << &a;  // Uses ::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition and operator<< are
+// both in an unnamed namespace.
+namespace {
+class MyTypeInUnnamedNameSpace : public Base {
+ public:
+  explicit MyTypeInUnnamedNameSpace(int an_x) : Base(an_x) {}
+};
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInUnnamedNameSpace& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInUnnamedNameSpace* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+}  // namespace
+
+TEST(MessageTest, CanStreamUserTypeInUnnamedNameSpace) {
+  Message msg;
+  MyTypeInUnnamedNameSpace a(1);
+
+  msg << a << &a;  // Uses <unnamed_namespace>::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition and operator<< are
+// both in a user namespace.
+namespace namespace1 {
+class MyTypeInNameSpace1 : public Base {
+ public:
+  explicit MyTypeInNameSpace1(int an_x) : Base(an_x) {}
+};
+std::ostream& operator<<(std::ostream& os, const MyTypeInNameSpace1& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os, const MyTypeInNameSpace1* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+}  // namespace namespace1
+
+TEST(MessageTest, CanStreamUserTypeInUserNameSpace) {
+  Message msg;
+  namespace1::MyTypeInNameSpace1 a(1);
+
+  msg << a << &a;  // Uses namespace1::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition is in a user namespace
+// but whose operator<< is in the global namespace.
+namespace namespace2 {
+class MyTypeInNameSpace2 : public ::Base {
+ public:
+  explicit MyTypeInNameSpace2(int an_x) : Base(an_x) {}
+};
+}  // namespace namespace2
+std::ostream& operator<<(std::ostream& os,
+                         const namespace2::MyTypeInNameSpace2& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const namespace2::MyTypeInNameSpace2* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+
+TEST(MessageTest, CanStreamUserTypeInUserNameSpaceWithStreamOperatorInGlobal) {
+  Message msg;
+  namespace2::MyTypeInNameSpace2 a(1);
+
+  msg << a << &a;  // Uses ::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming NULL pointers to testing::Message.
+TEST(MessageTest, NullPointers) {
+  Message msg;
+  char* const p1 = nullptr;
+  unsigned char* const p2 = nullptr;
+  int* p3 = nullptr;
+  double* p4 = nullptr;
+  bool* p5 = nullptr;
+  Message* p6 = nullptr;
+
+  msg << p1 << p2 << p3 << p4 << p5 << p6;
+  ASSERT_STREQ("(null)(null)(null)(null)(null)(null)", msg.GetString().c_str());
+}
+
+// Tests streaming wide strings to testing::Message.
+TEST(MessageTest, WideStrings) {
+  // Streams a NULL of type const wchar_t*.
+  const wchar_t* const_wstr = nullptr;
+  EXPECT_STREQ("(null)", (Message() << const_wstr).GetString().c_str());
+
+  // Streams a NULL of type wchar_t*.
+  wchar_t* wstr = nullptr;
+  EXPECT_STREQ("(null)", (Message() << wstr).GetString().c_str());
+
+  // Streams a non-NULL of type const wchar_t*.
+  const_wstr = L"abc\x8119";
+  EXPECT_STREQ("abc\xe8\x84\x99",
+               (Message() << const_wstr).GetString().c_str());
+
+  // Streams a non-NULL of type wchar_t*.
+  wstr = const_cast<wchar_t*>(const_wstr);
+  EXPECT_STREQ("abc\xe8\x84\x99", (Message() << wstr).GetString().c_str());
+}
+
+// This line tests that we can define tests in the testing namespace.
+namespace testing {
+
+// Tests the TestInfo class.
+
+class TestInfoTest : public Test {
+ protected:
+  static const TestInfo* GetTestInfo(const char* test_name) {
+    const TestSuite* const test_suite =
+        GetUnitTestImpl()->GetTestSuite("TestInfoTest", "", nullptr, nullptr);
+
+    for (int i = 0; i < test_suite->total_test_count(); ++i) {
+      const TestInfo* const test_info = test_suite->GetTestInfo(i);
+      if (strcmp(test_name, test_info->name()) == 0) return test_info;
+    }
+    return nullptr;
+  }
+
+  static const TestResult* GetTestResult(const TestInfo* test_info) {
+    return test_info->result();
+  }
+};
+
+// Tests TestInfo::test_case_name() and TestInfo::name().
+TEST_F(TestInfoTest, Names) {
+  const TestInfo* const test_info = GetTestInfo("Names");
+
+  ASSERT_STREQ("TestInfoTest", test_info->test_suite_name());
+  ASSERT_STREQ("Names", test_info->name());
+}
+
+// Tests TestInfo::result().
+TEST_F(TestInfoTest, result) {
+  const TestInfo* const test_info = GetTestInfo("result");
+
+  // Initially, there is no TestPartResult for this test.
+  ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
+
+  // After the previous assertion, there is still none.
+  ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
+}
+
+#define VERIFY_CODE_LOCATION                                                \
+  const int expected_line = __LINE__ - 1;                                   \
+  const TestInfo* const test_info = GetUnitTestImpl()->current_test_info(); \
+  ASSERT_TRUE(test_info);                                                   \
+  EXPECT_STREQ(__FILE__, test_info->file());                                \
+  EXPECT_EQ(expected_line, test_info->line())
+
+// clang-format off
+TEST(CodeLocationForTEST, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+class CodeLocationForTESTF : public Test {};
+
+TEST_F(CodeLocationForTESTF, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+class CodeLocationForTESTP : public TestWithParam<int> {};
+
+TEST_P(CodeLocationForTESTP, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+INSTANTIATE_TEST_SUITE_P(, CodeLocationForTESTP, Values(0));
+
+template <typename T>
+class CodeLocationForTYPEDTEST : public Test {};
+
+TYPED_TEST_SUITE(CodeLocationForTYPEDTEST, int);
+
+TYPED_TEST(CodeLocationForTYPEDTEST, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+template <typename T>
+class CodeLocationForTYPEDTESTP : public Test {};
+
+TYPED_TEST_SUITE_P(CodeLocationForTYPEDTESTP);
+
+TYPED_TEST_P(CodeLocationForTYPEDTESTP, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+REGISTER_TYPED_TEST_SUITE_P(CodeLocationForTYPEDTESTP, Verify);
+
+INSTANTIATE_TYPED_TEST_SUITE_P(My, CodeLocationForTYPEDTESTP, int);
+
+#undef VERIFY_CODE_LOCATION
+// clang-format on
+
+// Tests setting up and tearing down a test case.
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+class SetUpTestCaseTest : public Test {
+ protected:
+  // This will be called once before the first test in this test case
+  // is run.
+  static void SetUpTestCase() {
+    printf("Setting up the test case . . .\n");
+
+    // Initializes some shared resource.  In this simple example, we
+    // just create a C string.  More complex stuff can be done if
+    // desired.
+    shared_resource_ = "123";
+
+    // Increments the number of test cases that have been set up.
+    counter_++;
+
+    // SetUpTestCase() should be called only once.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // This will be called once after the last test in this test case is
+  // run.
+  static void TearDownTestCase() {
+    printf("Tearing down the test case . . .\n");
+
+    // Decrements the number of test cases that have been set up.
+    counter_--;
+
+    // TearDownTestCase() should be called only once.
+    EXPECT_EQ(0, counter_);
+
+    // Cleans up the shared resource.
+    shared_resource_ = nullptr;
+  }
+
+  // This will be called before each test in this test case.
+  void SetUp() override {
+    // SetUpTestCase() should be called only once, so counter_ should
+    // always be 1.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // Number of test cases that have been set up.
+  static int counter_;
+
+  // Some resource to be shared by all tests in this test case.
+  static const char* shared_resource_;
+};
+
+int SetUpTestCaseTest::counter_ = 0;
+const char* SetUpTestCaseTest::shared_resource_ = nullptr;
+
+// A test that uses the shared resource.
+TEST_F(SetUpTestCaseTest, Test1) { EXPECT_STRNE(nullptr, shared_resource_); }
+
+// Another test that uses the shared resource.
+TEST_F(SetUpTestCaseTest, Test2) { EXPECT_STREQ("123", shared_resource_); }
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Tests SetupTestSuite/TearDown TestSuite
+class SetUpTestSuiteTest : public Test {
+ protected:
+  // This will be called once before the first test in this test case
+  // is run.
+  static void SetUpTestSuite() {
+    printf("Setting up the test suite . . .\n");
+
+    // Initializes some shared resource.  In this simple example, we
+    // just create a C string.  More complex stuff can be done if
+    // desired.
+    shared_resource_ = "123";
+
+    // Increments the number of test cases that have been set up.
+    counter_++;
+
+    // SetUpTestSuite() should be called only once.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // This will be called once after the last test in this test case is
+  // run.
+  static void TearDownTestSuite() {
+    printf("Tearing down the test suite . . .\n");
+
+    // Decrements the number of test suites that have been set up.
+    counter_--;
+
+    // TearDownTestSuite() should be called only once.
+    EXPECT_EQ(0, counter_);
+
+    // Cleans up the shared resource.
+    shared_resource_ = nullptr;
+  }
+
+  // This will be called before each test in this test case.
+  void SetUp() override {
+    // SetUpTestSuite() should be called only once, so counter_ should
+    // always be 1.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // Number of test suites that have been set up.
+  static int counter_;
+
+  // Some resource to be shared by all tests in this test case.
+  static const char* shared_resource_;
+};
+
+int SetUpTestSuiteTest::counter_ = 0;
+const char* SetUpTestSuiteTest::shared_resource_ = nullptr;
+
+// A test that uses the shared resource.
+TEST_F(SetUpTestSuiteTest, TestSetupTestSuite1) {
+  EXPECT_STRNE(nullptr, shared_resource_);
+}
+
+// Another test that uses the shared resource.
+TEST_F(SetUpTestSuiteTest, TestSetupTestSuite2) {
+  EXPECT_STREQ("123", shared_resource_);
+}
+
+// The ParseFlagsTest test case tests ParseGoogleTestFlagsOnly.
+
+// The Flags struct stores a copy of all Google Test flags.
+struct Flags {
+  // Constructs a Flags struct where each flag has its default value.
+  Flags()
+      : also_run_disabled_tests(false),
+        break_on_failure(false),
+        catch_exceptions(false),
+        death_test_use_fork(false),
+        fail_fast(false),
+        filter(""),
+        list_tests(false),
+        output(""),
+        brief(false),
+        print_time(true),
+        random_seed(0),
+        repeat(1),
+        recreate_environments_when_repeating(true),
+        shuffle(false),
+        stack_trace_depth(kMaxStackTraceDepth),
+        stream_result_to(""),
+        throw_on_failure(false) {}
+
+  // Factory methods.
+
+  // Creates a Flags struct where the gtest_also_run_disabled_tests flag has
+  // the given value.
+  static Flags AlsoRunDisabledTests(bool also_run_disabled_tests) {
+    Flags flags;
+    flags.also_run_disabled_tests = also_run_disabled_tests;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_break_on_failure flag has
+  // the given value.
+  static Flags BreakOnFailure(bool break_on_failure) {
+    Flags flags;
+    flags.break_on_failure = break_on_failure;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_catch_exceptions flag has
+  // the given value.
+  static Flags CatchExceptions(bool catch_exceptions) {
+    Flags flags;
+    flags.catch_exceptions = catch_exceptions;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_death_test_use_fork flag has
+  // the given value.
+  static Flags DeathTestUseFork(bool death_test_use_fork) {
+    Flags flags;
+    flags.death_test_use_fork = death_test_use_fork;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_fail_fast flag has
+  // the given value.
+  static Flags FailFast(bool fail_fast) {
+    Flags flags;
+    flags.fail_fast = fail_fast;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_filter flag has the given
+  // value.
+  static Flags Filter(const char* filter) {
+    Flags flags;
+    flags.filter = filter;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_list_tests flag has the
+  // given value.
+  static Flags ListTests(bool list_tests) {
+    Flags flags;
+    flags.list_tests = list_tests;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_output flag has the given
+  // value.
+  static Flags Output(const char* output) {
+    Flags flags;
+    flags.output = output;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_brief flag has the given
+  // value.
+  static Flags Brief(bool brief) {
+    Flags flags;
+    flags.brief = brief;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_print_time flag has the given
+  // value.
+  static Flags PrintTime(bool print_time) {
+    Flags flags;
+    flags.print_time = print_time;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_random_seed flag has the given
+  // value.
+  static Flags RandomSeed(int32_t random_seed) {
+    Flags flags;
+    flags.random_seed = random_seed;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_repeat flag has the given
+  // value.
+  static Flags Repeat(int32_t repeat) {
+    Flags flags;
+    flags.repeat = repeat;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_recreate_environments_when_repeating
+  // flag has the given value.
+  static Flags RecreateEnvironmentsWhenRepeating(
+      bool recreate_environments_when_repeating) {
+    Flags flags;
+    flags.recreate_environments_when_repeating =
+        recreate_environments_when_repeating;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_shuffle flag has the given
+  // value.
+  static Flags Shuffle(bool shuffle) {
+    Flags flags;
+    flags.shuffle = shuffle;
+    return flags;
+  }
+
+  // Creates a Flags struct where the GTEST_FLAG(stack_trace_depth) flag has
+  // the given value.
+  static Flags StackTraceDepth(int32_t stack_trace_depth) {
+    Flags flags;
+    flags.stack_trace_depth = stack_trace_depth;
+    return flags;
+  }
+
+  // Creates a Flags struct where the GTEST_FLAG(stream_result_to) flag has
+  // the given value.
+  static Flags StreamResultTo(const char* stream_result_to) {
+    Flags flags;
+    flags.stream_result_to = stream_result_to;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_throw_on_failure flag has
+  // the given value.
+  static Flags ThrowOnFailure(bool throw_on_failure) {
+    Flags flags;
+    flags.throw_on_failure = throw_on_failure;
+    return flags;
+  }
+
+  // These fields store the flag values.
+  bool also_run_disabled_tests;
+  bool break_on_failure;
+  bool catch_exceptions;
+  bool death_test_use_fork;
+  bool fail_fast;
+  const char* filter;
+  bool list_tests;
+  const char* output;
+  bool brief;
+  bool print_time;
+  int32_t random_seed;
+  int32_t repeat;
+  bool recreate_environments_when_repeating;
+  bool shuffle;
+  int32_t stack_trace_depth;
+  const char* stream_result_to;
+  bool throw_on_failure;
+};
+
+// Fixture for testing ParseGoogleTestFlagsOnly().
+class ParseFlagsTest : public Test {
+ protected:
+  // Clears the flags before each test.
+  void SetUp() override {
+    GTEST_FLAG_SET(also_run_disabled_tests, false);
+    GTEST_FLAG_SET(break_on_failure, false);
+    GTEST_FLAG_SET(catch_exceptions, false);
+    GTEST_FLAG_SET(death_test_use_fork, false);
+    GTEST_FLAG_SET(fail_fast, false);
+    GTEST_FLAG_SET(filter, "");
+    GTEST_FLAG_SET(list_tests, false);
+    GTEST_FLAG_SET(output, "");
+    GTEST_FLAG_SET(brief, false);
+    GTEST_FLAG_SET(print_time, true);
+    GTEST_FLAG_SET(random_seed, 0);
+    GTEST_FLAG_SET(repeat, 1);
+    GTEST_FLAG_SET(recreate_environments_when_repeating, true);
+    GTEST_FLAG_SET(shuffle, false);
+    GTEST_FLAG_SET(stack_trace_depth, kMaxStackTraceDepth);
+    GTEST_FLAG_SET(stream_result_to, "");
+    GTEST_FLAG_SET(throw_on_failure, false);
+  }
+
+  // Asserts that two narrow or wide string arrays are equal.
+  template <typename CharType>
+  static void AssertStringArrayEq(int size1, CharType** array1, int size2,
+                                  CharType** array2) {
+    ASSERT_EQ(size1, size2) << " Array sizes different.";
+
+    for (int i = 0; i != size1; i++) {
+      ASSERT_STREQ(array1[i], array2[i]) << " where i == " << i;
+    }
+  }
+
+  // Verifies that the flag values match the expected values.
+  static void CheckFlags(const Flags& expected) {
+    EXPECT_EQ(expected.also_run_disabled_tests,
+              GTEST_FLAG_GET(also_run_disabled_tests));
+    EXPECT_EQ(expected.break_on_failure, GTEST_FLAG_GET(break_on_failure));
+    EXPECT_EQ(expected.catch_exceptions, GTEST_FLAG_GET(catch_exceptions));
+    EXPECT_EQ(expected.death_test_use_fork,
+              GTEST_FLAG_GET(death_test_use_fork));
+    EXPECT_EQ(expected.fail_fast, GTEST_FLAG_GET(fail_fast));
+    EXPECT_STREQ(expected.filter, GTEST_FLAG_GET(filter).c_str());
+    EXPECT_EQ(expected.list_tests, GTEST_FLAG_GET(list_tests));
+    EXPECT_STREQ(expected.output, GTEST_FLAG_GET(output).c_str());
+    EXPECT_EQ(expected.brief, GTEST_FLAG_GET(brief));
+    EXPECT_EQ(expected.print_time, GTEST_FLAG_GET(print_time));
+    EXPECT_EQ(expected.random_seed, GTEST_FLAG_GET(random_seed));
+    EXPECT_EQ(expected.repeat, GTEST_FLAG_GET(repeat));
+    EXPECT_EQ(expected.recreate_environments_when_repeating,
+              GTEST_FLAG_GET(recreate_environments_when_repeating));
+    EXPECT_EQ(expected.shuffle, GTEST_FLAG_GET(shuffle));
+    EXPECT_EQ(expected.stack_trace_depth, GTEST_FLAG_GET(stack_trace_depth));
+    EXPECT_STREQ(expected.stream_result_to,
+                 GTEST_FLAG_GET(stream_result_to).c_str());
+    EXPECT_EQ(expected.throw_on_failure, GTEST_FLAG_GET(throw_on_failure));
+  }
+
+  // Parses a command line (specified by argc1 and argv1), then
+  // verifies that the flag values are expected and that the
+  // recognized flags are removed from the command line.
+  template <typename CharType>
+  static void TestParsingFlags(int argc1, const CharType** argv1, int argc2,
+                               const CharType** argv2, const Flags& expected,
+                               bool should_print_help) {
+    const bool saved_help_flag = ::testing::internal::g_help_flag;
+    ::testing::internal::g_help_flag = false;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    CaptureStdout();
+#endif
+
+    // Parses the command line.
+    internal::ParseGoogleTestFlagsOnly(&argc1, const_cast<CharType**>(argv1));
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    const std::string captured_stdout = GetCapturedStdout();
+#endif
+
+    // Verifies the flag values.
+    CheckFlags(expected);
+
+    // Verifies that the recognized flags are removed from the command
+    // line.
+    AssertStringArrayEq(argc1 + 1, argv1, argc2 + 1, argv2);
+
+    // ParseGoogleTestFlagsOnly should neither set g_help_flag nor print the
+    // help message for the flags it recognizes.
+    EXPECT_EQ(should_print_help, ::testing::internal::g_help_flag);
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    const char* const expected_help_fragment =
+        "This program contains tests written using";
+    if (should_print_help) {
+      EXPECT_PRED_FORMAT2(IsSubstring, expected_help_fragment, captured_stdout);
+    } else {
+      EXPECT_PRED_FORMAT2(IsNotSubstring, expected_help_fragment,
+                          captured_stdout);
+    }
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+    ::testing::internal::g_help_flag = saved_help_flag;
+  }
+
+  // This macro wraps TestParsingFlags s.t. the user doesn't need
+  // to specify the array sizes.
+
+#define GTEST_TEST_PARSING_FLAGS_(argv1, argv2, expected, should_print_help) \
+  TestParsingFlags(sizeof(argv1) / sizeof(*argv1) - 1, argv1,                \
+                   sizeof(argv2) / sizeof(*argv2) - 1, argv2, expected,      \
+                   should_print_help)
+};
+
+// Tests parsing an empty command line.
+TEST_F(ParseFlagsTest, Empty) {
+  const char* argv[] = {nullptr};
+
+  const char* argv2[] = {nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests parsing a command line that has no flag.
+TEST_F(ParseFlagsTest, NoFlag) {
+  const char* argv[] = {"foo.exe", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests parsing --gtest_fail_fast.
+TEST_F(ParseFlagsTest, FailFast) {
+  const char* argv[] = {"foo.exe", "--gtest_fail_fast", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::FailFast(true), false);
+}
+
+// Tests parsing an empty --gtest_filter flag.
+TEST_F(ParseFlagsTest, FilterEmpty) {
+  const char* argv[] = {"foo.exe", "--gtest_filter=", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), false);
+}
+
+// Tests parsing a non-empty --gtest_filter flag.
+TEST_F(ParseFlagsTest, FilterNonEmpty) {
+  const char* argv[] = {"foo.exe", "--gtest_filter=abc", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
+}
+
+// Tests parsing --gtest_break_on_failure.
+TEST_F(ParseFlagsTest, BreakOnFailureWithoutValue) {
+  const char* argv[] = {"foo.exe", "--gtest_break_on_failure", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
+}
+
+// Tests parsing --gtest_break_on_failure=0.
+TEST_F(ParseFlagsTest, BreakOnFailureFalse_0) {
+  const char* argv[] = {"foo.exe", "--gtest_break_on_failure=0", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing --gtest_break_on_failure=f.
+TEST_F(ParseFlagsTest, BreakOnFailureFalse_f) {
+  const char* argv[] = {"foo.exe", "--gtest_break_on_failure=f", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing --gtest_break_on_failure=F.
+TEST_F(ParseFlagsTest, BreakOnFailureFalse_F) {
+  const char* argv[] = {"foo.exe", "--gtest_break_on_failure=F", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing a --gtest_break_on_failure flag that has a "true"
+// definition.
+TEST_F(ParseFlagsTest, BreakOnFailureTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_break_on_failure=1", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
+}
+
+// Tests parsing --gtest_catch_exceptions.
+TEST_F(ParseFlagsTest, CatchExceptions) {
+  const char* argv[] = {"foo.exe", "--gtest_catch_exceptions", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::CatchExceptions(true), false);
+}
+
+// Tests parsing --gtest_death_test_use_fork.
+TEST_F(ParseFlagsTest, DeathTestUseFork) {
+  const char* argv[] = {"foo.exe", "--gtest_death_test_use_fork", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::DeathTestUseFork(true), false);
+}
+
+// Tests having the same flag twice with different values.  The
+// expected behavior is that the one coming last takes precedence.
+TEST_F(ParseFlagsTest, DuplicatedFlags) {
+  const char* argv[] = {"foo.exe", "--gtest_filter=a", "--gtest_filter=b",
+                        nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("b"), false);
+}
+
+// Tests having an unrecognized flag on the command line.
+TEST_F(ParseFlagsTest, UnrecognizedFlag) {
+  const char* argv[] = {"foo.exe", "--gtest_break_on_failure",
+                        "bar",  // Unrecognized by Google Test.
+                        "--gtest_filter=b", nullptr};
+
+  const char* argv2[] = {"foo.exe", "bar", nullptr};
+
+  Flags flags;
+  flags.break_on_failure = true;
+  flags.filter = "b";
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, flags, false);
+}
+
+// Tests having a --gtest_list_tests flag
+TEST_F(ParseFlagsTest, ListTestsFlag) {
+  const char* argv[] = {"foo.exe", "--gtest_list_tests", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
+}
+
+// Tests having a --gtest_list_tests flag with a "true" value
+TEST_F(ParseFlagsTest, ListTestsTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_list_tests=1", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
+}
+
+// Tests having a --gtest_list_tests flag with a "false" value
+TEST_F(ParseFlagsTest, ListTestsFalse) {
+  const char* argv[] = {"foo.exe", "--gtest_list_tests=0", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_list_tests=f.
+TEST_F(ParseFlagsTest, ListTestsFalse_f) {
+  const char* argv[] = {"foo.exe", "--gtest_list_tests=f", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_list_tests=F.
+TEST_F(ParseFlagsTest, ListTestsFalse_F) {
+  const char* argv[] = {"foo.exe", "--gtest_list_tests=F", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_output=xml
+TEST_F(ParseFlagsTest, OutputXml) {
+  const char* argv[] = {"foo.exe", "--gtest_output=xml", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml"), false);
+}
+
+// Tests parsing --gtest_output=xml:file
+TEST_F(ParseFlagsTest, OutputXmlFile) {
+  const char* argv[] = {"foo.exe", "--gtest_output=xml:file", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml:file"), false);
+}
+
+// Tests parsing --gtest_output=xml:directory/path/
+TEST_F(ParseFlagsTest, OutputXmlDirectory) {
+  const char* argv[] = {"foo.exe", "--gtest_output=xml:directory/path/",
+                        nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml:directory/path/"),
+                            false);
+}
+
+// Tests having a --gtest_brief flag
+TEST_F(ParseFlagsTest, BriefFlag) {
+  const char* argv[] = {"foo.exe", "--gtest_brief", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Brief(true), false);
+}
+
+// Tests having a --gtest_brief flag with a "true" value
+TEST_F(ParseFlagsTest, BriefFlagTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_brief=1", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Brief(true), false);
+}
+
+// Tests having a --gtest_brief flag with a "false" value
+TEST_F(ParseFlagsTest, BriefFlagFalse) {
+  const char* argv[] = {"foo.exe", "--gtest_brief=0", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Brief(false), false);
+}
+
+// Tests having a --gtest_print_time flag
+TEST_F(ParseFlagsTest, PrintTimeFlag) {
+  const char* argv[] = {"foo.exe", "--gtest_print_time", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
+}
+
+// Tests having a --gtest_print_time flag with a "true" value
+TEST_F(ParseFlagsTest, PrintTimeTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_print_time=1", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
+}
+
+// Tests having a --gtest_print_time flag with a "false" value
+TEST_F(ParseFlagsTest, PrintTimeFalse) {
+  const char* argv[] = {"foo.exe", "--gtest_print_time=0", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_print_time=f.
+TEST_F(ParseFlagsTest, PrintTimeFalse_f) {
+  const char* argv[] = {"foo.exe", "--gtest_print_time=f", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_print_time=F.
+TEST_F(ParseFlagsTest, PrintTimeFalse_F) {
+  const char* argv[] = {"foo.exe", "--gtest_print_time=F", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_random_seed=number
+TEST_F(ParseFlagsTest, RandomSeed) {
+  const char* argv[] = {"foo.exe", "--gtest_random_seed=1000", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::RandomSeed(1000), false);
+}
+
+// Tests parsing --gtest_repeat=number
+TEST_F(ParseFlagsTest, Repeat) {
+  const char* argv[] = {"foo.exe", "--gtest_repeat=1000", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Repeat(1000), false);
+}
+
+// Tests parsing --gtest_recreate_environments_when_repeating
+TEST_F(ParseFlagsTest, RecreateEnvironmentsWhenRepeating) {
+  const char* argv[] = {
+      "foo.exe",
+      "--gtest_recreate_environments_when_repeating=0",
+      nullptr,
+  };
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(
+      argv, argv2, Flags::RecreateEnvironmentsWhenRepeating(false), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag
+TEST_F(ParseFlagsTest, AlsoRunDisabledTestsFlag) {
+  const char* argv[] = {"foo.exe", "--gtest_also_run_disabled_tests", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(true),
+                            false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag with a "true" value
+TEST_F(ParseFlagsTest, AlsoRunDisabledTestsTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_also_run_disabled_tests=1",
+                        nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(true),
+                            false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag with a "false" value
+TEST_F(ParseFlagsTest, AlsoRunDisabledTestsFalse) {
+  const char* argv[] = {"foo.exe", "--gtest_also_run_disabled_tests=0",
+                        nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(false),
+                            false);
+}
+
+// Tests parsing --gtest_shuffle.
+TEST_F(ParseFlagsTest, ShuffleWithoutValue) {
+  const char* argv[] = {"foo.exe", "--gtest_shuffle", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
+}
+
+// Tests parsing --gtest_shuffle=0.
+TEST_F(ParseFlagsTest, ShuffleFalse_0) {
+  const char* argv[] = {"foo.exe", "--gtest_shuffle=0", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(false), false);
+}
+
+// Tests parsing a --gtest_shuffle flag that has a "true" definition.
+TEST_F(ParseFlagsTest, ShuffleTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_shuffle=1", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
+}
+
+// Tests parsing --gtest_stack_trace_depth=number.
+TEST_F(ParseFlagsTest, StackTraceDepth) {
+  const char* argv[] = {"foo.exe", "--gtest_stack_trace_depth=5", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::StackTraceDepth(5), false);
+}
+
+TEST_F(ParseFlagsTest, StreamResultTo) {
+  const char* argv[] = {"foo.exe", "--gtest_stream_result_to=localhost:1234",
+                        nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                            Flags::StreamResultTo("localhost:1234"), false);
+}
+
+// Tests parsing --gtest_throw_on_failure.
+TEST_F(ParseFlagsTest, ThrowOnFailureWithoutValue) {
+  const char* argv[] = {"foo.exe", "--gtest_throw_on_failure", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+
+// Tests parsing --gtest_throw_on_failure=0.
+TEST_F(ParseFlagsTest, ThrowOnFailureFalse_0) {
+  const char* argv[] = {"foo.exe", "--gtest_throw_on_failure=0", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(false), false);
+}
+
+// Tests parsing a --gtest_throw_on_failure flag that has a "true"
+// definition.
+TEST_F(ParseFlagsTest, ThrowOnFailureTrue) {
+  const char* argv[] = {"foo.exe", "--gtest_throw_on_failure=1", nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+
+// Tests parsing a bad --gtest_filter flag.
+TEST_F(ParseFlagsTest, FilterBad) {
+  const char* argv[] = {"foo.exe", "--gtest_filter", nullptr};
+
+  const char* argv2[] = {"foo.exe", "--gtest_filter", nullptr};
+
+#if defined(GTEST_HAS_ABSL) && defined(GTEST_HAS_DEATH_TEST)
+  // Invalid flag arguments are a fatal error when using the Abseil Flags.
+  EXPECT_EXIT(GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true),
+              testing::ExitedWithCode(1),
+              "ERROR: Missing the value for the flag 'gtest_filter'");
+#elif !defined(GTEST_HAS_ABSL)
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true);
+#else
+  static_cast<void>(argv);
+  static_cast<void>(argv2);
+#endif
+}
+
+// Tests parsing --gtest_output (invalid).
+TEST_F(ParseFlagsTest, OutputEmpty) {
+  const char* argv[] = {"foo.exe", "--gtest_output", nullptr};
+
+  const char* argv2[] = {"foo.exe", "--gtest_output", nullptr};
+
+#if defined(GTEST_HAS_ABSL) && defined(GTEST_HAS_DEATH_TEST)
+  // Invalid flag arguments are a fatal error when using the Abseil Flags.
+  EXPECT_EXIT(GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true),
+              testing::ExitedWithCode(1),
+              "ERROR: Missing the value for the flag 'gtest_output'");
+#elif !defined(GTEST_HAS_ABSL)
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true);
+#else
+  static_cast<void>(argv);
+  static_cast<void>(argv2);
+#endif
+}
+
+#ifdef GTEST_HAS_ABSL
+TEST_F(ParseFlagsTest, AbseilPositionalFlags) {
+  const char* argv[] = {"foo.exe", "--gtest_throw_on_failure=1", "--",
+                        "--other_flag", nullptr};
+
+  // When using Abseil flags, it should be possible to pass flags not recognized
+  // using "--" to delimit positional arguments. These flags should be returned
+  // though argv.
+  const char* argv2[] = {"foo.exe", "--other_flag", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+#endif
+
+TEST_F(ParseFlagsTest, UnrecognizedFlags) {
+  const char* argv[] = {"foo.exe", "--gtest_filter=abcd", "--other_flag",
+                        nullptr};
+
+  const char* argv2[] = {"foo.exe", "--other_flag", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abcd"), false);
+}
+
+#ifdef GTEST_OS_WINDOWS
+// Tests parsing wide strings.
+TEST_F(ParseFlagsTest, WideStrings) {
+  const wchar_t* argv[] = {L"foo.exe",
+                           L"--gtest_filter=Foo*",
+                           L"--gtest_list_tests=1",
+                           L"--gtest_break_on_failure",
+                           L"--non_gtest_flag",
+                           NULL};
+
+  const wchar_t* argv2[] = {L"foo.exe", L"--non_gtest_flag", NULL};
+
+  Flags expected_flags;
+  expected_flags.break_on_failure = true;
+  expected_flags.filter = "Foo*";
+  expected_flags.list_tests = true;
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
+}
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+class FlagfileTest : public ParseFlagsTest {
+ public:
+  void SetUp() override {
+    ParseFlagsTest::SetUp();
+
+    testdata_path_.Set(internal::FilePath(
+        testing::TempDir() + internal::GetCurrentExecutableName().string() +
+        "_flagfile_test"));
+    testing::internal::posix::RmDir(testdata_path_.c_str());
+    EXPECT_TRUE(testdata_path_.CreateFolder());
+  }
+
+  void TearDown() override {
+    testing::internal::posix::RmDir(testdata_path_.c_str());
+    ParseFlagsTest::TearDown();
+  }
+
+  internal::FilePath CreateFlagfile(const char* contents) {
+    internal::FilePath file_path(internal::FilePath::GenerateUniqueFileName(
+        testdata_path_, internal::FilePath("unique"), "txt"));
+    FILE* f = testing::internal::posix::FOpen(file_path.c_str(), "w");
+    fprintf(f, "%s", contents);
+    fclose(f);
+    return file_path;
+  }
+
+ private:
+  internal::FilePath testdata_path_;
+};
+
+// Tests an empty flagfile.
+TEST_F(FlagfileTest, Empty) {
+  internal::FilePath flagfile_path(CreateFlagfile(""));
+  std::string flagfile_flag =
+      std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
+
+  const char* argv[] = {"foo.exe", flagfile_flag.c_str(), nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests passing a non-empty --gtest_filter flag via --gtest_flagfile.
+TEST_F(FlagfileTest, FilterNonEmpty) {
+  internal::FilePath flagfile_path(
+      CreateFlagfile("--" GTEST_FLAG_PREFIX_ "filter=abc"));
+  std::string flagfile_flag =
+      std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
+
+  const char* argv[] = {"foo.exe", flagfile_flag.c_str(), nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
+}
+
+// Tests passing several flags via --gtest_flagfile.
+TEST_F(FlagfileTest, SeveralFlags) {
+  internal::FilePath flagfile_path(
+      CreateFlagfile("--" GTEST_FLAG_PREFIX_ "filter=abc\n"
+                     "--" GTEST_FLAG_PREFIX_ "break_on_failure\n"
+                     "--" GTEST_FLAG_PREFIX_ "list_tests"));
+  std::string flagfile_flag =
+      std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
+
+  const char* argv[] = {"foo.exe", flagfile_flag.c_str(), nullptr};
+
+  const char* argv2[] = {"foo.exe", nullptr};
+
+  Flags expected_flags;
+  expected_flags.break_on_failure = true;
+  expected_flags.filter = "abc";
+  expected_flags.list_tests = true;
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
+}
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+// Tests current_test_info() in UnitTest.
+class CurrentTestInfoTest : public Test {
+ protected:
+  // Tests that current_test_info() returns NULL before the first test in
+  // the test case is run.
+  static void SetUpTestSuite() {
+    // There should be no tests running at this point.
+    const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
+    EXPECT_TRUE(test_info == nullptr)
+        << "There should be no tests running at this point.";
+  }
+
+  // Tests that current_test_info() returns NULL after the last test in
+  // the test case has run.
+  static void TearDownTestSuite() {
+    const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
+    EXPECT_TRUE(test_info == nullptr)
+        << "There should be no tests running at this point.";
+  }
+};
+
+// Tests that current_test_info() returns TestInfo for currently running
+// test by checking the expected test name against the actual one.
+TEST_F(CurrentTestInfoTest, WorksForFirstTestInATestSuite) {
+  const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(nullptr != test_info)
+      << "There is a test running so we should have a valid TestInfo.";
+  EXPECT_STREQ("CurrentTestInfoTest", test_info->test_suite_name())
+      << "Expected the name of the currently running test suite.";
+  EXPECT_STREQ("WorksForFirstTestInATestSuite", test_info->name())
+      << "Expected the name of the currently running test.";
+}
+
+// Tests that current_test_info() returns TestInfo for currently running
+// test by checking the expected test name against the actual one.  We
+// use this test to see that the TestInfo object actually changed from
+// the previous invocation.
+TEST_F(CurrentTestInfoTest, WorksForSecondTestInATestSuite) {
+  const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(nullptr != test_info)
+      << "There is a test running so we should have a valid TestInfo.";
+  EXPECT_STREQ("CurrentTestInfoTest", test_info->test_suite_name())
+      << "Expected the name of the currently running test suite.";
+  EXPECT_STREQ("WorksForSecondTestInATestSuite", test_info->name())
+      << "Expected the name of the currently running test.";
+}
+
+}  // namespace testing
+
+// These two lines test that we can define tests in a namespace that
+// has the name "testing" and is nested in another namespace.
+namespace my_namespace {
+namespace testing {
+
+// Makes sure that TEST knows to use ::testing::Test instead of
+// ::my_namespace::testing::Test.
+class Test {};
+
+// Makes sure that an assertion knows to use ::testing::Message instead of
+// ::my_namespace::testing::Message.
+class Message {};
+
+// Makes sure that an assertion knows to use
+// ::testing::AssertionResult instead of
+// ::my_namespace::testing::AssertionResult.
+class AssertionResult {};
+
+// Tests that an assertion that should succeed works as expected.
+TEST(NestedTestingNamespaceTest, Success) {
+  EXPECT_EQ(1, 1) << "This shouldn't fail.";
+}
+
+// Tests that an assertion that should fail works as expected.
+TEST(NestedTestingNamespaceTest, Failure) {
+  EXPECT_FATAL_FAILURE(FAIL() << "This failure is expected.",
+                       "This failure is expected.");
+}
+
+}  // namespace testing
+}  // namespace my_namespace
+
+// Tests that one can call superclass SetUp and TearDown methods--
+// that is, that they are not private.
+// No tests are based on this fixture; the test "passes" if it compiles
+// successfully.
+class ProtectedFixtureMethodsTest : public Test {
+ protected:
+  void SetUp() override { Test::SetUp(); }
+  void TearDown() override { Test::TearDown(); }
+};
+
+// StreamingAssertionsTest tests the streaming versions of a representative
+// sample of assertions.
+TEST(StreamingAssertionsTest, Unconditional) {
+  SUCCEED() << "expected success";
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE() << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(FAIL() << "expected failure", "expected failure");
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+#pragma option push -w-ccc -w-rch
+#endif
+
+TEST(StreamingAssertionsTest, Truth) {
+  EXPECT_TRUE(true) << "unexpected failure";
+  ASSERT_TRUE(true) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, Truth2) {
+  EXPECT_FALSE(false) << "unexpected failure";
+  ASSERT_FALSE(false) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(true) << "expected failure",
+                       "expected failure");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them
+#pragma option pop
+#endif
+
+TEST(StreamingAssertionsTest, IntegerEquals) {
+  EXPECT_EQ(1, 1) << "unexpected failure";
+  ASSERT_EQ(1, 1) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(1, 2) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(1, 2) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, IntegerLessThan) {
+  EXPECT_LT(1, 2) << "unexpected failure";
+  ASSERT_LT(1, 2) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_LT(2, 1) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsEqual) {
+  EXPECT_STREQ("foo", "foo") << "unexpected failure";
+  ASSERT_STREQ("foo", "foo") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ("foo", "bar") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("foo", "bar") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsNotEqual) {
+  EXPECT_STRNE("foo", "bar") << "unexpected failure";
+  ASSERT_STRNE("foo", "bar") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("foo", "foo") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRNE("foo", "foo") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsEqualIgnoringCase) {
+  EXPECT_STRCASEEQ("foo", "FOO") << "unexpected failure";
+  ASSERT_STRCASEEQ("foo", "FOO") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ("foo", "bar") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("foo", "bar") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringNotEqualIgnoringCase) {
+  EXPECT_STRCASENE("foo", "bar") << "unexpected failure";
+  ASSERT_STRCASENE("foo", "bar") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("foo", "FOO") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("bar", "BAR") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, FloatingPointEquals) {
+  EXPECT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
+  ASSERT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(0.0, 1.0) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.0) << "expected failure",
+                       "expected failure");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+TEST(StreamingAssertionsTest, Throw) {
+  EXPECT_THROW(ThrowAnInteger(), int) << "unexpected failure";
+  ASSERT_THROW(ThrowAnInteger(), int) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool)
+                              << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_THROW(ThrowAnInteger(), bool)
+                           << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, NoThrow) {
+  EXPECT_NO_THROW(ThrowNothing()) << "unexpected failure";
+  ASSERT_NO_THROW(ThrowNothing()) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger())
+                              << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, AnyThrow) {
+  EXPECT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
+  ASSERT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(ThrowNothing())
+                              << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(ThrowNothing()) << "expected failure",
+                       "expected failure");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that Google Test correctly decides whether to use colors in the output.
+
+TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsYes) {
+  GTEST_FLAG_SET(color, "yes");
+
+  SetEnv("TERM", "xterm");             // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));   // Stdout is a TTY.
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  SetEnv("TERM", "dumb");              // TERM doesn't support colors.
+  EXPECT_TRUE(ShouldUseColor(true));   // Stdout is a TTY.
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsAliasOfYes) {
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+
+  GTEST_FLAG_SET(color, "True");
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  GTEST_FLAG_SET(color, "t");
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  GTEST_FLAG_SET(color, "1");
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsNo) {
+  GTEST_FLAG_SET(color, "no");
+
+  SetEnv("TERM", "xterm");              // TERM supports colors.
+  EXPECT_FALSE(ShouldUseColor(true));   // Stdout is a TTY.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  SetEnv("TERM", "dumb");               // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));   // Stdout is a TTY.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsInvalid) {
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+
+  GTEST_FLAG_SET(color, "F");
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  GTEST_FLAG_SET(color, "0");
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  GTEST_FLAG_SET(color, "unknown");
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenStdoutIsTty) {
+  GTEST_FLAG_SET(color, "auto");
+
+  SetEnv("TERM", "xterm");              // TERM supports colors.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+  EXPECT_TRUE(ShouldUseColor(true));    // Stdout is a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
+  GTEST_FLAG_SET(color, "auto");
+
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW)
+  // On Windows, we ignore the TERM variable as it's usually not set.
+
+  SetEnv("TERM", "dumb");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+#else
+  // On non-Windows platforms, we rely on TERM to determine if the
+  // terminal supports colors.
+
+  SetEnv("TERM", "dumb");              // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "emacs");             // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "vt100");             // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-mono");        // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm");            // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-color");      // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-kitty");      // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "alacritty");        // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-256color");   // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "screen");           // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "screen-256color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "tmux");             // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "tmux-256color");    // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "rxvt-unicode");     // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "rxvt-unicode-256color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));        // Stdout is a TTY.
+
+  SetEnv("TERM", "linux");            // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "cygwin");           // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+#endif  // GTEST_OS_WINDOWS
+}
+
+// Verifies that StaticAssertTypeEq works in a namespace scope.
+
+GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy1 =
+    StaticAssertTypeEq<bool, bool>();
+GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy2 =
+    StaticAssertTypeEq<const int, const int>();
+
+// Verifies that StaticAssertTypeEq works in a class.
+
+template <typename T>
+class StaticAssertTypeEqTestHelper {
+ public:
+  StaticAssertTypeEqTestHelper() { StaticAssertTypeEq<bool, T>(); }
+};
+
+TEST(StaticAssertTypeEqTest, WorksInClass) {
+  StaticAssertTypeEqTestHelper<bool>();
+}
+
+// Verifies that StaticAssertTypeEq works inside a function.
+
+typedef int IntAlias;
+
+TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
+  StaticAssertTypeEq<int, IntAlias>();
+  StaticAssertTypeEq<int*, IntAlias*>();
+}
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+  EXPECT_FALSE(HasNonfatalFailure());
+}
+
+static void FailFatally() { FAIL(); }
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsOnlyFatalFailure) {
+  FailFatally();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_FALSE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+  FailFatally();
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+// A wrapper for calling HasNonfatalFailure outside of a test body.
+static bool HasNonfatalFailureHelper() {
+  return testing::Test::HasNonfatalFailure();
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody) {
+  EXPECT_FALSE(HasNonfatalFailureHelper());
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody2) {
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailureHelper();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+  EXPECT_FALSE(HasFailure());
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsFatalFailure) {
+  FailFatally();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+  ADD_FAILURE();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+  FailFatally();
+  ADD_FAILURE();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+// A wrapper for calling HasFailure outside of a test body.
+static bool HasFailureHelper() { return testing::Test::HasFailure(); }
+
+TEST(HasFailureTest, WorksOutsideOfTestBody) {
+  EXPECT_FALSE(HasFailureHelper());
+}
+
+TEST(HasFailureTest, WorksOutsideOfTestBody2) {
+  ADD_FAILURE();
+  const bool has_failure = HasFailureHelper();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+class TestListener : public EmptyTestEventListener {
+ public:
+  TestListener() : on_start_counter_(nullptr), is_destroyed_(nullptr) {}
+  TestListener(int* on_start_counter, bool* is_destroyed)
+      : on_start_counter_(on_start_counter), is_destroyed_(is_destroyed) {}
+
+  ~TestListener() override {
+    if (is_destroyed_) *is_destroyed_ = true;
+  }
+
+ protected:
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
+    if (on_start_counter_ != nullptr) (*on_start_counter_)++;
+  }
+
+ private:
+  int* on_start_counter_;
+  bool* is_destroyed_;
+};
+
+// Tests the constructor.
+TEST(TestEventListenersTest, ConstructionWorks) {
+  TestEventListeners listeners;
+
+  EXPECT_TRUE(TestEventListenersAccessor::GetRepeater(&listeners) != nullptr);
+  EXPECT_TRUE(listeners.default_result_printer() == nullptr);
+  EXPECT_TRUE(listeners.default_xml_generator() == nullptr);
+}
+
+// Tests that the TestEventListeners destructor deletes all the listeners it
+// owns.
+TEST(TestEventListenersTest, DestructionWorks) {
+  bool default_result_printer_is_destroyed = false;
+  bool default_xml_printer_is_destroyed = false;
+  bool extra_listener_is_destroyed = false;
+  TestListener* default_result_printer =
+      new TestListener(nullptr, &default_result_printer_is_destroyed);
+  TestListener* default_xml_printer =
+      new TestListener(nullptr, &default_xml_printer_is_destroyed);
+  TestListener* extra_listener =
+      new TestListener(nullptr, &extra_listener_is_destroyed);
+
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultResultPrinter(&listeners,
+                                                        default_result_printer);
+    TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners,
+                                                       default_xml_printer);
+    listeners.Append(extra_listener);
+  }
+  EXPECT_TRUE(default_result_printer_is_destroyed);
+  EXPECT_TRUE(default_xml_printer_is_destroyed);
+  EXPECT_TRUE(extra_listener_is_destroyed);
+}
+
+// Tests that a listener Append'ed to a TestEventListeners list starts
+// receiving events.
+TEST(TestEventListenersTest, Append) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    listeners.Append(listener);
+    TestEventListenersAccessor::GetRepeater(&listeners)
+        ->OnTestProgramStart(*UnitTest::GetInstance());
+    EXPECT_EQ(1, on_start_counter);
+  }
+  EXPECT_TRUE(is_destroyed);
+}
+
+// Tests that listeners receive events in the order they were appended to
+// the list, except for *End requests, which must be received in the reverse
+// order.
+class SequenceTestingListener : public EmptyTestEventListener {
+ public:
+  SequenceTestingListener(std::vector<std::string>* vector, const char* id)
+      : vector_(vector), id_(id) {}
+
+ protected:
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
+    vector_->push_back(GetEventDescription("OnTestProgramStart"));
+  }
+
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {
+    vector_->push_back(GetEventDescription("OnTestProgramEnd"));
+  }
+
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int /*iteration*/) override {
+    vector_->push_back(GetEventDescription("OnTestIterationStart"));
+  }
+
+  void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                          int /*iteration*/) override {
+    vector_->push_back(GetEventDescription("OnTestIterationEnd"));
+  }
+
+ private:
+  std::string GetEventDescription(const char* method) {
+    Message message;
+    message << id_ << "." << method;
+    return message.GetString();
+  }
+
+  std::vector<std::string>* vector_;
+  const char* const id_;
+
+  SequenceTestingListener(const SequenceTestingListener&) = delete;
+  SequenceTestingListener& operator=(const SequenceTestingListener&) = delete;
+};
+
+TEST(EventListenerTest, AppendKeepsOrder) {
+  std::vector<std::string> vec;
+  TestEventListeners listeners;
+  listeners.Append(new SequenceTestingListener(&vec, "1st"));
+  listeners.Append(new SequenceTestingListener(&vec, "2nd"));
+  listeners.Append(new SequenceTestingListener(&vec, "3rd"));
+
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramStart(*UnitTest::GetInstance());
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("1st.OnTestProgramStart", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestProgramStart", vec[1].c_str());
+  EXPECT_STREQ("3rd.OnTestProgramStart", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramEnd(*UnitTest::GetInstance());
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("3rd.OnTestProgramEnd", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestProgramEnd", vec[1].c_str());
+  EXPECT_STREQ("1st.OnTestProgramEnd", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestIterationStart(*UnitTest::GetInstance(), 0);
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("1st.OnTestIterationStart", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestIterationStart", vec[1].c_str());
+  EXPECT_STREQ("3rd.OnTestIterationStart", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestIterationEnd(*UnitTest::GetInstance(), 0);
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("3rd.OnTestIterationEnd", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestIterationEnd", vec[1].c_str());
+  EXPECT_STREQ("1st.OnTestIterationEnd", vec[2].c_str());
+}
+
+// Tests that a listener removed from a TestEventListeners list stops receiving
+// events and is not deleted when the list is destroyed.
+TEST(TestEventListenersTest, Release) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    listeners.Append(listener);
+    EXPECT_EQ(listener, listeners.Release(listener));
+    TestEventListenersAccessor::GetRepeater(&listeners)
+        ->OnTestProgramStart(*UnitTest::GetInstance());
+    EXPECT_TRUE(listeners.Release(listener) == nullptr);
+  }
+  EXPECT_EQ(0, on_start_counter);
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests that no events are forwarded when event forwarding is disabled.
+TEST(EventListenerTest, SuppressEventForwarding) {
+  int on_start_counter = 0;
+  TestListener* listener = new TestListener(&on_start_counter, nullptr);
+
+  TestEventListeners listeners;
+  listeners.Append(listener);
+  ASSERT_TRUE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+  TestEventListenersAccessor::SuppressEventForwarding(&listeners);
+  ASSERT_FALSE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramStart(*UnitTest::GetInstance());
+  EXPECT_EQ(0, on_start_counter);
+}
+
+// Tests that events generated by Google Test are not forwarded in
+// death test subprocesses.
+TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprocesses) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        GTEST_CHECK_(TestEventListenersAccessor::EventForwardingEnabled(
+            *GetUnitTestImpl()->listeners()))
+            << "expected failure";
+      },
+      "expected failure");
+}
+
+// Tests that a listener installed via SetDefaultResultPrinter() starts
+// receiving events and is returned via default_result_printer() and that
+// the previous default_result_printer is removed from the list and deleted.
+TEST(EventListenerTest, default_result_printer) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+  TestEventListeners listeners;
+  TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+  EXPECT_EQ(listener, listeners.default_result_printer());
+
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramStart(*UnitTest::GetInstance());
+
+  EXPECT_EQ(1, on_start_counter);
+
+  // Replacing default_result_printer with something else should remove it
+  // from the list and destroy it.
+  TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, nullptr);
+
+  EXPECT_TRUE(listeners.default_result_printer() == nullptr);
+  EXPECT_TRUE(is_destroyed);
+
+  // After broadcasting an event the counter is still the same, indicating
+  // the listener is not in the list anymore.
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramStart(*UnitTest::GetInstance());
+  EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_result_printer listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+    EXPECT_EQ(listener, listeners.Release(listener));
+    EXPECT_TRUE(listeners.default_result_printer() == nullptr);
+    EXPECT_FALSE(is_destroyed);
+
+    // Broadcasting events now should not affect default_result_printer.
+    TestEventListenersAccessor::GetRepeater(&listeners)
+        ->OnTestProgramStart(*UnitTest::GetInstance());
+    EXPECT_EQ(0, on_start_counter);
+  }
+  // Destroying the list should not affect the listener now, too.
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests that a listener installed via SetDefaultXmlGenerator() starts
+// receiving events and is returned via default_xml_generator() and that
+// the previous default_xml_generator is removed from the list and deleted.
+TEST(EventListenerTest, default_xml_generator) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+  TestEventListeners listeners;
+  TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+  EXPECT_EQ(listener, listeners.default_xml_generator());
+
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramStart(*UnitTest::GetInstance());
+
+  EXPECT_EQ(1, on_start_counter);
+
+  // Replacing default_xml_generator with something else should remove it
+  // from the list and destroy it.
+  TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, nullptr);
+
+  EXPECT_TRUE(listeners.default_xml_generator() == nullptr);
+  EXPECT_TRUE(is_destroyed);
+
+  // After broadcasting an event the counter is still the same, indicating
+  // the listener is not in the list anymore.
+  TestEventListenersAccessor::GetRepeater(&listeners)
+      ->OnTestProgramStart(*UnitTest::GetInstance());
+  EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_xml_generator listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+    EXPECT_EQ(listener, listeners.Release(listener));
+    EXPECT_TRUE(listeners.default_xml_generator() == nullptr);
+    EXPECT_FALSE(is_destroyed);
+
+    // Broadcasting events now should not affect default_xml_generator.
+    TestEventListenersAccessor::GetRepeater(&listeners)
+        ->OnTestProgramStart(*UnitTest::GetInstance());
+    EXPECT_EQ(0, on_start_counter);
+  }
+  // Destroying the list should not affect the listener now, too.
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests to ensure that the alternative, verbose spellings of
+// some of the macros work.  We don't test them thoroughly as that
+// would be quite involved.  Since their implementations are
+// straightforward, and they are rarely used, we'll just rely on the
+// users to tell us when they are broken.
+GTEST_TEST(AlternativeNameTest, Works) {  // GTEST_TEST is the same as TEST.
+  GTEST_SUCCEED() << "OK";  // GTEST_SUCCEED is the same as SUCCEED.
+
+  // GTEST_FAIL is the same as FAIL.
+  EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure",
+                       "An expected failure");
+
+  // GTEST_ASSERT_XY is the same as ASSERT_XY.
+
+  GTEST_ASSERT_EQ(0, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(0, 1) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_NE(0, 1);
+  GTEST_ASSERT_NE(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_NE(0, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_LE(0, 0);
+  GTEST_ASSERT_LE(0, 1);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LE(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_LT(0, 1);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(0, 0) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_GE(0, 0);
+  GTEST_ASSERT_GE(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GE(0, 1) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_GT(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(0, 1) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(1, 1) << "An expected failure",
+                       "An expected failure");
+}
+
+// Tests for internal utilities necessary for implementation of the universal
+// printing.
+
+class ConversionHelperBase {};
+class ConversionHelperDerived : public ConversionHelperBase {};
+
+struct HasDebugStringMethods {
+  std::string DebugString() const { return ""; }
+  std::string ShortDebugString() const { return ""; }
+};
+
+struct InheritsDebugStringMethods : public HasDebugStringMethods {};
+
+struct WrongTypeDebugStringMethod {
+  std::string DebugString() const { return ""; }
+  int ShortDebugString() const { return 1; }
+};
+
+struct NotConstDebugStringMethod {
+  std::string DebugString() { return ""; }
+  std::string ShortDebugString() const { return ""; }
+};
+
+struct MissingDebugStringMethod {
+  std::string DebugString() { return ""; }
+};
+
+struct IncompleteType;
+
+// Tests that HasDebugStringAndShortDebugString<T>::value is a compile-time
+// constant.
+TEST(HasDebugStringAndShortDebugStringTest, ValueIsCompileTimeConstant) {
+  static_assert(HasDebugStringAndShortDebugString<HasDebugStringMethods>::value,
+                "const_true");
+  static_assert(
+      HasDebugStringAndShortDebugString<InheritsDebugStringMethods>::value,
+      "const_true");
+  static_assert(HasDebugStringAndShortDebugString<
+                    const InheritsDebugStringMethods>::value,
+                "const_true");
+  static_assert(
+      !HasDebugStringAndShortDebugString<WrongTypeDebugStringMethod>::value,
+      "const_false");
+  static_assert(
+      !HasDebugStringAndShortDebugString<NotConstDebugStringMethod>::value,
+      "const_false");
+  static_assert(
+      !HasDebugStringAndShortDebugString<MissingDebugStringMethod>::value,
+      "const_false");
+  static_assert(!HasDebugStringAndShortDebugString<IncompleteType>::value,
+                "const_false");
+  static_assert(!HasDebugStringAndShortDebugString<int>::value, "const_false");
+}
+
+// Tests that HasDebugStringAndShortDebugString<T>::value is true when T has
+// needed methods.
+TEST(HasDebugStringAndShortDebugStringTest,
+     ValueIsTrueWhenTypeHasDebugStringAndShortDebugString) {
+  EXPECT_TRUE(
+      HasDebugStringAndShortDebugString<InheritsDebugStringMethods>::value);
+}
+
+// Tests that HasDebugStringAndShortDebugString<T>::value is false when T
+// doesn't have needed methods.
+TEST(HasDebugStringAndShortDebugStringTest,
+     ValueIsFalseWhenTypeIsNotAProtocolMessage) {
+  EXPECT_FALSE(HasDebugStringAndShortDebugString<int>::value);
+  EXPECT_FALSE(
+      HasDebugStringAndShortDebugString<const ConversionHelperBase>::value);
+}
+
+// Tests GTEST_REMOVE_REFERENCE_AND_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveReferenceAndConst() {
+  static_assert(std::is_same<T1, GTEST_REMOVE_REFERENCE_AND_CONST_(T2)>::value,
+                "GTEST_REMOVE_REFERENCE_AND_CONST_ failed.");
+}
+
+TEST(RemoveReferenceToConstTest, Works) {
+  TestGTestRemoveReferenceAndConst<int, int>();
+  TestGTestRemoveReferenceAndConst<double, double&>();
+  TestGTestRemoveReferenceAndConst<char, const char>();
+  TestGTestRemoveReferenceAndConst<char, const char&>();
+  TestGTestRemoveReferenceAndConst<const char*, const char*>();
+}
+
+// Tests GTEST_REFERENCE_TO_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestReferenceToConst() {
+  static_assert(std::is_same<T1, GTEST_REFERENCE_TO_CONST_(T2)>::value,
+                "GTEST_REFERENCE_TO_CONST_ failed.");
+}
+
+TEST(GTestReferenceToConstTest, Works) {
+  TestGTestReferenceToConst<const char&, char>();
+  TestGTestReferenceToConst<const int&, const int>();
+  TestGTestReferenceToConst<const double&, double>();
+  TestGTestReferenceToConst<const std::string&, const std::string&>();
+}
+
+// Tests IsContainerTest.
+
+class NonContainer {};
+
+TEST(IsContainerTestTest, WorksForNonContainer) {
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<int>(0)));
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<char[5]>(0)));
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<NonContainer>(0)));
+}
+
+TEST(IsContainerTestTest, WorksForContainer) {
+  EXPECT_EQ(sizeof(IsContainer), sizeof(IsContainerTest<std::vector<bool>>(0)));
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<std::map<int, double>>(0)));
+}
+
+struct ConstOnlyContainerWithPointerIterator {
+  using const_iterator = int*;
+  const_iterator begin() const;
+  const_iterator end() const;
+};
+
+struct ConstOnlyContainerWithClassIterator {
+  struct const_iterator {
+    const int& operator*() const;
+    const_iterator& operator++(/* pre-increment */);
+  };
+  const_iterator begin() const;
+  const_iterator end() const;
+};
+
+TEST(IsContainerTestTest, ConstOnlyContainer) {
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<ConstOnlyContainerWithPointerIterator>(0)));
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<ConstOnlyContainerWithClassIterator>(0)));
+}
+
+// Tests IsHashTable.
+struct AHashTable {
+  typedef void hasher;
+};
+struct NotReallyAHashTable {
+  typedef void hasher;
+  typedef void reverse_iterator;
+};
+TEST(IsHashTable, Basic) {
+  EXPECT_TRUE(testing::internal::IsHashTable<AHashTable>::value);
+  EXPECT_FALSE(testing::internal::IsHashTable<NotReallyAHashTable>::value);
+  EXPECT_FALSE(testing::internal::IsHashTable<std::vector<int>>::value);
+  EXPECT_TRUE(testing::internal::IsHashTable<std::unordered_set<int>>::value);
+}
+
+// Tests ArrayEq().
+
+TEST(ArrayEqTest, WorksForDegeneratedArrays) {
+  EXPECT_TRUE(ArrayEq(5, 5L));
+  EXPECT_FALSE(ArrayEq('a', 0));
+}
+
+TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
+  // Note that a and b are distinct but compatible types.
+  const int a[] = {0, 1};
+  long b[] = {0, 1};
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  b[0] = 2;
+  EXPECT_FALSE(ArrayEq(a, b));
+  EXPECT_FALSE(ArrayEq(a, 1, b));
+}
+
+TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
+  const char a[][3] = {"hi", "lo"};
+  const char b[][3] = {"hi", "lo"};
+  const char c[][3] = {"hi", "li"};
+
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  EXPECT_FALSE(ArrayEq(a, c));
+  EXPECT_FALSE(ArrayEq(a, 2, c));
+}
+
+// Tests ArrayAwareFind().
+
+TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
+  const char a[] = "hello";
+  EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
+  EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
+}
+
+TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
+  int a[][2] = {{0, 1}, {2, 3}, {4, 5}};
+  const int b[2] = {2, 3};
+  EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
+
+  const int c[2] = {6, 7};
+  EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
+}
+
+// Tests CopyArray().
+
+TEST(CopyArrayTest, WorksForDegeneratedArrays) {
+  int n = 0;
+  CopyArray('a', &n);
+  EXPECT_EQ('a', n);
+}
+
+TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
+  const char a[3] = "hi";
+  int b[3];
+#ifndef __BORLANDC__  // C++Builder cannot compile some array size deductions.
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+#endif
+
+  int c[3];
+  CopyArray(a, 3, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
+  const int a[2][3] = {{0, 1, 2}, {3, 4, 5}};
+  int b[2][3];
+#ifndef __BORLANDC__  // C++Builder cannot compile some array size deductions.
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+#endif
+
+  int c[2][3];
+  CopyArray(a, 2, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+// Tests NativeArray.
+
+TEST(NativeArrayTest, ConstructorFromArrayWorks) {
+  const int a[3] = {0, 1, 2};
+  NativeArray<int> na(a, 3, RelationToSourceReference());
+  EXPECT_EQ(3U, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
+  typedef int Array[2];
+  Array* a = new Array[1];
+  (*a)[0] = 0;
+  (*a)[1] = 1;
+  NativeArray<int> na(*a, 2, RelationToSourceCopy());
+  EXPECT_NE(*a, na.begin());
+  delete[] a;
+  EXPECT_EQ(0, na.begin()[0]);
+  EXPECT_EQ(1, na.begin()[1]);
+
+  // We rely on the heap checker to verify that na deletes the copy of
+  // array.
+}
+
+TEST(NativeArrayTest, TypeMembersAreCorrect) {
+  StaticAssertTypeEq<char, NativeArray<char>::value_type>();
+  StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
+
+  StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
+  StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
+}
+
+TEST(NativeArrayTest, MethodsWork) {
+  const int a[3] = {0, 1, 2};
+  NativeArray<int> na(a, 3, RelationToSourceCopy());
+  ASSERT_EQ(3U, na.size());
+  EXPECT_EQ(3, na.end() - na.begin());
+
+  NativeArray<int>::const_iterator it = na.begin();
+  EXPECT_EQ(0, *it);
+  ++it;
+  EXPECT_EQ(1, *it);
+  it++;
+  EXPECT_EQ(2, *it);
+  ++it;
+  EXPECT_EQ(na.end(), it);
+
+  EXPECT_TRUE(na == na);
+
+  NativeArray<int> na2(a, 3, RelationToSourceReference());
+  EXPECT_TRUE(na == na2);
+
+  const int b1[3] = {0, 1, 1};
+  const int b2[4] = {0, 1, 2, 3};
+  EXPECT_FALSE(na == NativeArray<int>(b1, 3, RelationToSourceReference()));
+  EXPECT_FALSE(na == NativeArray<int>(b2, 4, RelationToSourceCopy()));
+}
+
+TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
+  const char a[2][3] = {"hi", "lo"};
+  NativeArray<char[3]> na(a, 2, RelationToSourceReference());
+  ASSERT_EQ(2U, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+// ElemFromList
+TEST(ElemFromList, Basic) {
+  using testing::internal::ElemFromList;
+  EXPECT_TRUE(
+      (std::is_same<int, ElemFromList<0, int, double, char>::type>::value));
+  EXPECT_TRUE(
+      (std::is_same<double, ElemFromList<1, int, double, char>::type>::value));
+  EXPECT_TRUE(
+      (std::is_same<char, ElemFromList<2, int, double, char>::type>::value));
+  EXPECT_TRUE((
+      std::is_same<char, ElemFromList<7, int, int, int, int, int, int, int,
+                                      char, int, int, int, int>::type>::value));
+}
+
+// FlatTuple
+TEST(FlatTuple, Basic) {
+  using testing::internal::FlatTuple;
+
+  FlatTuple<int, double, const char*> tuple = {};
+  EXPECT_EQ(0, tuple.Get<0>());
+  EXPECT_EQ(0.0, tuple.Get<1>());
+  EXPECT_EQ(nullptr, tuple.Get<2>());
+
+  tuple = FlatTuple<int, double, const char*>(
+      testing::internal::FlatTupleConstructTag{}, 7, 3.2, "Foo");
+  EXPECT_EQ(7, tuple.Get<0>());
+  EXPECT_EQ(3.2, tuple.Get<1>());
+  EXPECT_EQ(std::string("Foo"), tuple.Get<2>());
+
+  tuple.Get<1>() = 5.1;
+  EXPECT_EQ(5.1, tuple.Get<1>());
+}
+
+namespace {
+std::string AddIntToString(int i, const std::string& s) {
+  return s + std::to_string(i);
+}
+}  // namespace
+
+TEST(FlatTuple, Apply) {
+  using testing::internal::FlatTuple;
+
+  FlatTuple<int, std::string> tuple{testing::internal::FlatTupleConstructTag{},
+                                    5, "Hello"};
+
+  // Lambda.
+  EXPECT_TRUE(tuple.Apply([](int i, const std::string& s) -> bool {
+    return i == static_cast<int>(s.size());
+  }));
+
+  // Function.
+  EXPECT_EQ(tuple.Apply(AddIntToString), "Hello5");
+
+  // Mutating operations.
+  tuple.Apply([](int& i, std::string& s) {
+    ++i;
+    s += s;
+  });
+  EXPECT_EQ(tuple.Get<0>(), 6);
+  EXPECT_EQ(tuple.Get<1>(), "HelloHello");
+}
+
+struct ConstructionCounting {
+  ConstructionCounting() { ++default_ctor_calls; }
+  ~ConstructionCounting() { ++dtor_calls; }
+  ConstructionCounting(const ConstructionCounting&) { ++copy_ctor_calls; }
+  ConstructionCounting(ConstructionCounting&&) noexcept { ++move_ctor_calls; }
+  ConstructionCounting& operator=(const ConstructionCounting&) {
+    ++copy_assignment_calls;
+    return *this;
+  }
+  ConstructionCounting& operator=(ConstructionCounting&&) noexcept {
+    ++move_assignment_calls;
+    return *this;
+  }
+
+  static void Reset() {
+    default_ctor_calls = 0;
+    dtor_calls = 0;
+    copy_ctor_calls = 0;
+    move_ctor_calls = 0;
+    copy_assignment_calls = 0;
+    move_assignment_calls = 0;
+  }
+
+  static int default_ctor_calls;
+  static int dtor_calls;
+  static int copy_ctor_calls;
+  static int move_ctor_calls;
+  static int copy_assignment_calls;
+  static int move_assignment_calls;
+};
+
+int ConstructionCounting::default_ctor_calls = 0;
+int ConstructionCounting::dtor_calls = 0;
+int ConstructionCounting::copy_ctor_calls = 0;
+int ConstructionCounting::move_ctor_calls = 0;
+int ConstructionCounting::copy_assignment_calls = 0;
+int ConstructionCounting::move_assignment_calls = 0;
+
+TEST(FlatTuple, ConstructorCalls) {
+  using testing::internal::FlatTuple;
+
+  // Default construction.
+  ConstructionCounting::Reset();
+  { FlatTuple<ConstructionCounting> tuple; }
+  EXPECT_EQ(ConstructionCounting::default_ctor_calls, 1);
+  EXPECT_EQ(ConstructionCounting::dtor_calls, 1);
+  EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
+
+  // Copy construction.
+  ConstructionCounting::Reset();
+  {
+    ConstructionCounting elem;
+    FlatTuple<ConstructionCounting> tuple{
+        testing::internal::FlatTupleConstructTag{}, elem};
+  }
+  EXPECT_EQ(ConstructionCounting::default_ctor_calls, 1);
+  EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
+  EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 1);
+  EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
+
+  // Move construction.
+  ConstructionCounting::Reset();
+  {
+    FlatTuple<ConstructionCounting> tuple{
+        testing::internal::FlatTupleConstructTag{}, ConstructionCounting{}};
+  }
+  EXPECT_EQ(ConstructionCounting::default_ctor_calls, 1);
+  EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
+  EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_ctor_calls, 1);
+  EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
+
+  // Copy assignment.
+  // TODO(ofats): it should be testing assignment operator of FlatTuple, not its
+  // elements
+  ConstructionCounting::Reset();
+  {
+    FlatTuple<ConstructionCounting> tuple;
+    ConstructionCounting elem;
+    tuple.Get<0>() = elem;
+  }
+  EXPECT_EQ(ConstructionCounting::default_ctor_calls, 2);
+  EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
+  EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 1);
+  EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
+
+  // Move assignment.
+  // TODO(ofats): it should be testing assignment operator of FlatTuple, not its
+  // elements
+  ConstructionCounting::Reset();
+  {
+    FlatTuple<ConstructionCounting> tuple;
+    tuple.Get<0>() = ConstructionCounting{};
+  }
+  EXPECT_EQ(ConstructionCounting::default_ctor_calls, 2);
+  EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
+  EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
+  EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
+  EXPECT_EQ(ConstructionCounting::move_assignment_calls, 1);
+
+  ConstructionCounting::Reset();
+}
+
+TEST(FlatTuple, ManyTypes) {
+  using testing::internal::FlatTuple;
+
+  // Instantiate FlatTuple with 257 ints.
+  // Tests show that we can do it with thousands of elements, but very long
+  // compile times makes it unusuitable for this test.
+#define GTEST_FLAT_TUPLE_INT8 int, int, int, int, int, int, int, int,
+#define GTEST_FLAT_TUPLE_INT16 GTEST_FLAT_TUPLE_INT8 GTEST_FLAT_TUPLE_INT8
+#define GTEST_FLAT_TUPLE_INT32 GTEST_FLAT_TUPLE_INT16 GTEST_FLAT_TUPLE_INT16
+#define GTEST_FLAT_TUPLE_INT64 GTEST_FLAT_TUPLE_INT32 GTEST_FLAT_TUPLE_INT32
+#define GTEST_FLAT_TUPLE_INT128 GTEST_FLAT_TUPLE_INT64 GTEST_FLAT_TUPLE_INT64
+#define GTEST_FLAT_TUPLE_INT256 GTEST_FLAT_TUPLE_INT128 GTEST_FLAT_TUPLE_INT128
+
+  // Let's make sure that we can have a very long list of types without blowing
+  // up the template instantiation depth.
+  FlatTuple<GTEST_FLAT_TUPLE_INT256 int> tuple;
+
+  tuple.Get<0>() = 7;
+  tuple.Get<99>() = 17;
+  tuple.Get<256>() = 1000;
+  EXPECT_EQ(7, tuple.Get<0>());
+  EXPECT_EQ(17, tuple.Get<99>());
+  EXPECT_EQ(1000, tuple.Get<256>());
+}
+
+// Tests SkipPrefix().
+
+TEST(SkipPrefixTest, SkipsWhenPrefixMatches) {
+  const char* const str = "hello";
+
+  const char* p = str;
+  EXPECT_TRUE(SkipPrefix("", &p));
+  EXPECT_EQ(str, p);
+
+  p = str;
+  EXPECT_TRUE(SkipPrefix("hell", &p));
+  EXPECT_EQ(str + 4, p);
+}
+
+TEST(SkipPrefixTest, DoesNotSkipWhenPrefixDoesNotMatch) {
+  const char* const str = "world";
+
+  const char* p = str;
+  EXPECT_FALSE(SkipPrefix("W", &p));
+  EXPECT_EQ(str, p);
+
+  p = str;
+  EXPECT_FALSE(SkipPrefix("world!", &p));
+  EXPECT_EQ(str, p);
+}
+
+// Tests ad_hoc_test_result().
+TEST(AdHocTestResultTest, AdHocTestResultForUnitTestDoesNotShowFailure) {
+  const testing::TestResult& test_result =
+      testing::UnitTest::GetInstance()->ad_hoc_test_result();
+  EXPECT_FALSE(test_result.Failed());
+}
+
+class DynamicUnitTestFixture : public testing::Test {};
+
+class DynamicTest : public DynamicUnitTestFixture {
+  void TestBody() override { EXPECT_TRUE(true); }
+};
+
+auto* dynamic_test = testing::RegisterTest(
+    "DynamicUnitTestFixture", "DynamicTest", "TYPE", "VALUE", __FILE__,
+    __LINE__, []() -> DynamicUnitTestFixture* { return new DynamicTest; });
+
+TEST(RegisterTest, WasRegistered) {
+  const auto& unittest = testing::UnitTest::GetInstance();
+  for (int i = 0; i < unittest->total_test_suite_count(); ++i) {
+    auto* tests = unittest->GetTestSuite(i);
+    if (tests->name() != std::string("DynamicUnitTestFixture")) continue;
+    for (int j = 0; j < tests->total_test_count(); ++j) {
+      if (tests->GetTestInfo(j)->name() != std::string("DynamicTest")) continue;
+      // Found it.
+      EXPECT_STREQ(tests->GetTestInfo(j)->value_param(), "VALUE");
+      EXPECT_STREQ(tests->GetTestInfo(j)->type_param(), "TYPE");
+      return;
+    }
+  }
+
+  FAIL() << "Didn't find the test!";
+}
+
+// Test that the pattern globbing algorithm is linear. If not, this test should
+// time out.
+TEST(PatternGlobbingTest, MatchesFilterLinearRuntime) {
+  std::string name(100, 'a');  // Construct the string (a^100)b
+  name.push_back('b');
+
+  std::string pattern;  // Construct the string ((a*)^100)b
+  for (int i = 0; i < 100; ++i) {
+    pattern.append("a*");
+  }
+  pattern.push_back('b');
+
+  EXPECT_TRUE(
+      testing::internal::UnitTestOptions::MatchesFilter(name, pattern.c_str()));
+}
+
+TEST(PatternGlobbingTest, MatchesFilterWithMultiplePatterns) {
+  const std::string name = "aaaa";
+  EXPECT_TRUE(testing::internal::UnitTestOptions::MatchesFilter(name, "a*"));
+  EXPECT_TRUE(testing::internal::UnitTestOptions::MatchesFilter(name, "a*:"));
+  EXPECT_FALSE(testing::internal::UnitTestOptions::MatchesFilter(name, "ab"));
+  EXPECT_FALSE(testing::internal::UnitTestOptions::MatchesFilter(name, "ab:"));
+  EXPECT_TRUE(testing::internal::UnitTestOptions::MatchesFilter(name, "ab:a*"));
+}
+
+TEST(PatternGlobbingTest, MatchesFilterEdgeCases) {
+  EXPECT_FALSE(testing::internal::UnitTestOptions::MatchesFilter("", "*a"));
+  EXPECT_TRUE(testing::internal::UnitTestOptions::MatchesFilter("", "*"));
+  EXPECT_FALSE(testing::internal::UnitTestOptions::MatchesFilter("a", ""));
+  EXPECT_TRUE(testing::internal::UnitTestOptions::MatchesFilter("", ""));
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_xml_outfile1_test_.cc b/3rd-party/googletest/googletest/test/gtest_xml_outfile1_test_.cc
new file mode 100644
index 0000000..19aa252
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_xml_outfile1_test_.cc
@@ -0,0 +1,43 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// gtest_xml_outfile1_test_ writes some xml via TestProperty used by
+// gtest_xml_outfiles_test.py
+
+#include "gtest/gtest.h"
+
+class PropertyOne : public testing::Test {
+ protected:
+  void SetUp() override { RecordProperty("SetUpProp", 1); }
+  void TearDown() override { RecordProperty("TearDownProp", 1); }
+};
+
+TEST_F(PropertyOne, TestSomeProperties) {
+  RecordProperty("TestSomeProperty", 1);
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_xml_outfile2_test_.cc b/3rd-party/googletest/googletest/test/gtest_xml_outfile2_test_.cc
new file mode 100644
index 0000000..4a76429
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_xml_outfile2_test_.cc
@@ -0,0 +1,77 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// gtest_xml_outfile2_test_ writes some xml via TestProperty used by
+// gtest_xml_outfiles_test.py
+
+#include <atomic>
+
+#include "gtest/gtest.h"
+
+class PropertyTwo : public testing::Test {
+ protected:
+  void SetUp() override { RecordProperty("SetUpProp", 2); }
+  void TearDown() override { RecordProperty("TearDownProp", 2); }
+};
+
+TEST_F(PropertyTwo, TestInt64ConvertibleProperties) {
+  float float_prop = 3.25;
+  RecordProperty("TestFloatProperty", float_prop);
+
+  double double_prop = 4.75;
+  RecordProperty("TestDoubleProperty", double_prop);
+
+  // Validate we can write an unsigned size_t as a property
+  size_t size_t_prop = 5;
+  RecordProperty("TestSizetProperty", size_t_prop);
+
+  bool bool_prop = true;
+  RecordProperty("TestBoolProperty", bool_prop);
+
+  char char_prop = 'A';
+  RecordProperty("TestCharProperty", char_prop);
+
+  int16_t int16_prop = 6;
+  RecordProperty("TestInt16Property", int16_prop);
+
+  int32_t int32_prop = 7;
+  RecordProperty("TestInt32Property", int32_prop);
+
+  int64_t int64_prop = 8;
+  RecordProperty("TestInt64Property", int64_prop);
+
+  enum Foo {
+    NINE = 9,
+  };
+  Foo enum_prop = NINE;
+  RecordProperty("TestEnumProperty", enum_prop);
+
+  std::atomic<int> atomic_int_prop(10);
+  RecordProperty("TestAtomicIntProperty", atomic_int_prop);
+}
diff --git a/3rd-party/googletest/googletest/test/gtest_xml_outfiles_test.py b/3rd-party/googletest/googletest/test/gtest_xml_outfiles_test.py
new file mode 100755
index 0000000..d17cc0c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_xml_outfiles_test.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for the gtest_xml_output module."""
+
+import os
+from xml.dom import minidom, Node
+from googletest.test import gtest_test_utils
+from googletest.test import gtest_xml_test_utils
+
+GTEST_OUTPUT_SUBDIR = "xml_outfiles"
+GTEST_OUTPUT_1_TEST = "gtest_xml_outfile1_test_"
+GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
+
+EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
+  <testsuite name="PropertyOne" tests="1" failures="0" skipped="0" disabled="0" errors="0" time="*" timestamp="*">
+    <testcase name="TestSomeProperties" file="gtest_xml_outfile1_test_.cc" line="41" status="run" result="completed" time="*" timestamp="*" classname="PropertyOne">
+      <properties>
+        <property name="SetUpProp" value="1"/>
+        <property name="TestSomeProperty" value="1"/>
+        <property name="TearDownProp" value="1"/>
+      </properties>
+    </testcase>
+  </testsuite>
+</testsuites>
+"""
+
+EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
+  <testsuite name="PropertyTwo" tests="1" failures="0" skipped="0" disabled="0" errors="0" time="*" timestamp="*">
+    <testcase name="TestInt64ConvertibleProperties" file="gtest_xml_outfile2_test_.cc" line="43" status="run" result="completed" time="*" timestamp="*" classname="PropertyTwo">
+      <properties>
+        <property name="SetUpProp" value="2"/>
+        <property name="TestFloatProperty" value="3.25"/>
+        <property name="TestDoubleProperty" value="4.75"/>
+        <property name="TestSizetProperty" value="5"/>
+        <property name="TestBoolProperty" value="true"/>
+        <property name="TestCharProperty" value="A"/>
+        <property name="TestInt16Property" value="6"/>
+        <property name="TestInt32Property" value="7"/>
+        <property name="TestInt64Property" value="8"/>
+        <property name="TestEnumProperty" value="9"/>
+        <property name="TestAtomicIntProperty" value="10"/>
+        <property name="TearDownProp" value="2"/>
+      </properties>
+    </testcase>
+  </testsuite>
+</testsuites>
+"""
+
+
+class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
+  """Unit test for Google Test's XML output functionality."""
+
+  def setUp(self):
+    # We want the trailing '/' that the last "" provides in os.path.join, for
+    # telling Google Test to create an output directory instead of a single file
+    # for xml output.
+    self.output_dir_ = os.path.join(
+        gtest_test_utils.GetTempDir(), GTEST_OUTPUT_SUBDIR, ""
+    )
+    self.DeleteFilesAndDir()
+
+  def tearDown(self):
+    self.DeleteFilesAndDir()
+
+  def DeleteFilesAndDir(self):
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + ".xml"))
+    except os.error:
+      pass
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + ".xml"))
+    except os.error:
+      pass
+    try:
+      os.rmdir(self.output_dir_)
+    except os.error:
+      pass
+
+  def testOutfile1(self):
+    self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_XML_1)
+
+  def testOutfile2(self):
+    self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_XML_2)
+
+  def _TestOutFile(self, test_name, expected_xml):
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
+    command = [gtest_prog_path, "--gtest_output=xml:%s" % self.output_dir_]
+    p = gtest_test_utils.Subprocess(
+        command, working_dir=gtest_test_utils.GetTempDir()
+    )
+    self.assertTrue(p.exited)
+    self.assertEqual(0, p.exit_code)
+
+    output_file_name1 = test_name + ".xml"
+    output_file1 = os.path.join(self.output_dir_, output_file_name1)
+    output_file_name2 = "lt-" + output_file_name1
+    output_file2 = os.path.join(self.output_dir_, output_file_name2)
+    self.assertTrue(
+        os.path.isfile(output_file1) or os.path.isfile(output_file2),
+        output_file1,
+    )
+
+    expected = minidom.parseString(expected_xml)
+    if os.path.isfile(output_file1):
+      actual = minidom.parse(output_file1)
+    else:
+      actual = minidom.parse(output_file2)
+    self.NormalizeXml(actual.documentElement)
+    self.AssertEquivalentNodes(expected.documentElement, actual.documentElement)
+    expected.unlink()
+    actual.unlink()
+
+
+if __name__ == "__main__":
+  os.environ["GTEST_STACK_TRACE_DEPTH"] = "0"
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_xml_output_unittest.py b/3rd-party/googletest/googletest/test/gtest_xml_output_unittest.py
new file mode 100755
index 0000000..c3fea2c
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_xml_output_unittest.py
@@ -0,0 +1,472 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for the gtest_xml_output module"""
+
+import datetime
+import errno
+import os
+import re
+import sys
+from xml.dom import minidom, Node
+
+from googletest.test import gtest_test_utils
+from googletest.test import gtest_xml_test_utils
+
+GTEST_FILTER_FLAG = '--gtest_filter'
+GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
+GTEST_OUTPUT_FLAG = '--gtest_output'
+GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml'
+GTEST_PROGRAM_NAME = 'gtest_xml_output_unittest_'
+
+# The flag indicating stacktraces are not supported
+NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support'
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
+
+SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv
+
+if SUPPORTS_STACK_TRACES:
+  STACK_TRACE_TEMPLATE = '\nStack trace:\n*'
+  STACK_TRACE_ENTITY_TEMPLATE = ''
+else:
+  STACK_TRACE_TEMPLATE = '\n'
+  STACK_TRACE_ENTITY_TEMPLATE = '&#x0A;'
+  # unittest.main() can't handle unknown flags
+  sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
+
+EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="26" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
+  <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
+  </testsuite>
+  <testsuite name="FailedTest" tests="1" failures="1" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="Fails" file="gtest_xml_output_unittest_.cc" line="61" status="run" result="completed" time="*" timestamp="*" classname="FailedTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Expected equality of these values:
+  1
+  2%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="MixedResultTest" tests="3" failures="1" disabled="1" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="88" status="run" result="completed" time="*" timestamp="*" classname="MixedResultTest"/>
+    <testcase name="Fails" file="gtest_xml_output_unittest_.cc" line="93" status="run" result="completed" time="*" timestamp="*" classname="MixedResultTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Expected equality of these values:
+  1
+  2%(stack)s]]></failure>
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  2&#x0A;  3%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Expected equality of these values:
+  2
+  3%(stack)s]]></failure>
+    </testcase>
+    <testcase name="DISABLED_test" file="gtest_xml_output_unittest_.cc" line="98" status="notrun" result="suppressed" time="*" timestamp="*" classname="MixedResultTest"/>
+  </testsuite>
+  <testsuite name="XmlQuotingTest" tests="1" failures="1" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="OutputsCData" file="gtest_xml_output_unittest_.cc" line="102" status="run" result="completed" time="*" timestamp="*" classname="XmlQuotingTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Failed&#x0A;XML output: &lt;?xml encoding=&quot;utf-8&quot;&gt;&lt;top&gt;&lt;![CDATA[cdata text]]&gt;&lt;/top&gt;%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]>]]&gt;<![CDATA[</top>%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="InvalidCharactersTest" tests="1" failures="1" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="InvalidCharactersInMessage" file="gtest_xml_output_unittest_.cc" line="109" status="run" result="completed" time="*" timestamp="*" classname="InvalidCharactersTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Failed&#x0A;Invalid characters in brackets []%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+Invalid characters in brackets []%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="DisabledTest" tests="1" failures="0" disabled="1" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="DISABLED_test_not_run" file="gtest_xml_output_unittest_.cc" line="68" status="notrun" result="suppressed" time="*" timestamp="*" classname="DisabledTest"/>
+  </testsuite>
+  <testsuite name="SkippedTest" tests="3" failures="1" disabled="0" skipped="2" errors="0" time="*" timestamp="*">
+    <testcase name="Skipped" status="run" file="gtest_xml_output_unittest_.cc" line="75" result="skipped" time="*" timestamp="*" classname="SkippedTest">
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+
+]]></skipped>
+    </testcase>
+    <testcase name="SkippedWithMessage" file="gtest_xml_output_unittest_.cc" line="79" status="run" result="skipped" time="*" timestamp="*" classname="SkippedTest">
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;It is good practice to tell why you skip a test.&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+It is good practice to tell why you skip a test.
+]]></skipped>
+    </testcase>
+    <testcase name="SkippedAfterFailure" file="gtest_xml_output_unittest_.cc" line="83" status="run" result="completed" time="*" timestamp="*" classname="SkippedTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Expected equality of these values:
+  1
+  2%(stack)s]]></failure>
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;It is good practice to tell why you skip a test.&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+It is good practice to tell why you skip a test.
+]]></skipped>
+    </testcase>
+
+  </testsuite>
+  <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
+    <testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="121" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+      <properties>
+        <property name="key_1" value="1"/>
+      </properties>
+    </testcase>
+    <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+      <properties>
+        <property name="key_int" value="1"/>
+      </properties>
+    </testcase>
+    <testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+      <properties>
+        <property name="key_1" value="1"/>
+        <property name="key_2" value="2"/>
+        <property name="key_3" value="3"/>
+      </properties>
+    </testcase>
+    <testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="135" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+      <properties>
+        <property name="key_1" value="2"/>
+      </properties>
+    </testcase>
+  </testsuite>
+  <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+     <testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="140" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
+       <properties>
+         <property name="key" value="1"/>
+       </properties>
+     </testcase>
+     <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="153" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
+       <properties>
+         <property name="key_for_utility_int" value="1"/>
+       </properties>
+     </testcase>
+     <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
+       <properties>
+         <property name="key_for_utility_string" value="1"/>
+       </properties>
+     </testcase>
+  </testsuite>
+  <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="164" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="165" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="165" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+  </testsuite>
+  <testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
+  </testsuite>
+  <testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
+  </testsuite>
+</testsuites>""" % {
+    'stack': STACK_TRACE_TEMPLATE,
+    'stack_entity': STACK_TRACE_ENTITY_TEMPLATE,
+}
+
+EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*"
+            timestamp="*" name="AllTests" ad_hoc_property="42">
+  <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0"
+             errors="0" time="*" timestamp="*">
+    <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
+  </testsuite>
+</testsuites>"""
+
+EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
+  <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
+  </testsuite>
+  <testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
+    <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+      <properties>
+        <property name="key_int" value="1"/>
+      </properties>
+    </testcase>
+  </testsuite>
+  <testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+  </testsuite>
+</testsuites>"""
+
+EXPECTED_NO_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="0" failures="0" disabled="0" errors="0" time="*"
+            timestamp="*" name="AllTests">
+  <testsuite name="NonTestSuiteFailure" tests="1" failures="1" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="" status="run" result="completed" time="*" timestamp="*" classname="">
+      <failure message="gtest_no_test_unittest.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_no_test_unittest.cc:*
+Expected equality of these values:
+  1
+  2%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+</testsuites>""" % {
+    'stack': STACK_TRACE_TEMPLATE,
+    'stack_entity': STACK_TRACE_ENTITY_TEMPLATE,
+}
+
+GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
+
+SUPPORTS_TYPED_TESTS = (
+    'TypedTest'
+    in gtest_test_utils.Subprocess(
+        [GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False
+    ).output
+)
+
+
+class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
+  """Unit test for Google Test's XML output functionality."""
+
+  # This test currently breaks on platforms that do not support typed and
+  # type-parameterized tests, so we don't run it under them.
+  if SUPPORTS_TYPED_TESTS:
+
+    def testNonEmptyXmlOutput(self):
+      """Generates non-empty XML and verifies it matches the expected output.
+
+      Runs a test program that generates a non-empty XML output, and
+      tests that the XML output is expected.
+      """
+      self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
+
+  def testNoTestXmlOutput(self):
+    """Verifies XML output for a Google Test binary without actual tests.
+
+    Runs a test program that generates an XML output for a binary without tests,
+    and tests that the XML output is expected.
+    """
+
+    self._TestXmlOutput('gtest_no_test_unittest', EXPECTED_NO_TEST_XML, 0)
+
+  def testTimestampValue(self):
+    """Checks whether the timestamp attribute in the XML output is valid.
+
+    Runs a test program that generates an empty XML output, and checks if
+    the timestamp attribute in the testsuites tag is valid.
+    """
+    actual = self._GetXmlOutput('gtest_no_test_unittest', [], {}, 0)
+    date_time_str = actual.documentElement.getAttributeNode('timestamp').value
+    # datetime.strptime() is only available in Python 2.5+ so we have to
+    # parse the expected datetime manually.
+    match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str)
+    self.assertTrue(
+        re.match, 'XML datettime string %s has incorrect format' % date_time_str
+    )
+    date_time_from_xml = datetime.datetime(
+        year=int(match.group(1)),
+        month=int(match.group(2)),
+        day=int(match.group(3)),
+        hour=int(match.group(4)),
+        minute=int(match.group(5)),
+        second=int(match.group(6)),
+    )
+
+    time_delta = abs(datetime.datetime.now() - date_time_from_xml)
+    # timestamp value should be near the current local time
+    self.assertLess(time_delta, datetime.timedelta(seconds=600))
+    actual.unlink()
+
+  def testDefaultOutputFile(self):
+    """Tests XML file with default name is created when name is not specified.
+
+    Confirms that Google Test produces an XML output file with the expected
+    default name if no name is explicitly specified.
+    """
+    output_file = os.path.join(
+        gtest_test_utils.GetTempDir(), GTEST_DEFAULT_OUTPUT_FILE
+    )
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
+        'gtest_no_test_unittest'
+    )
+    try:
+      os.remove(output_file)
+    except OSError:
+      e = sys.exc_info()[1]
+      if e.errno != errno.ENOENT:
+        raise
+
+    p = gtest_test_utils.Subprocess(
+        [gtest_prog_path, '%s=xml' % GTEST_OUTPUT_FLAG],
+        working_dir=gtest_test_utils.GetTempDir(),
+    )
+    self.assertTrue(p.exited)
+    self.assertEqual(0, p.exit_code)
+    self.assertTrue(os.path.isfile(output_file))
+
+  def testSuppressedXmlOutput(self):
+    """Verifies XML output is suppressed if default listener is shut down.
+
+    Tests that no XML file is generated if the default XML listener is
+    shut down before RUN_ALL_TESTS is invoked.
+    """
+
+    xml_path = os.path.join(
+        gtest_test_utils.GetTempDir(), GTEST_PROGRAM_NAME + 'out.xml'
+    )
+    if os.path.isfile(xml_path):
+      os.remove(xml_path)
+
+    command = [
+        GTEST_PROGRAM_PATH,
+        '%s=xml:%s' % (GTEST_OUTPUT_FLAG, xml_path),
+        '--shut_down_xml',
+    ]
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      # p.signal is available only if p.terminated_by_signal is True.
+      self.assertFalse(
+          p.terminated_by_signal,
+          '%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal),
+      )
+    else:
+      self.assertTrue(p.exited)
+      self.assertEqual(
+          1,
+          p.exit_code,
+          "'%s' exited with code %s, which doesn't match "
+          'the expected exit code %s.' % (command, p.exit_code, 1),
+      )
+
+    self.assertFalse(os.path.isfile(xml_path))
+
+  def testFilteredTestXmlOutput(self):
+    """Verifies XML output when a filter is applied.
+
+    Runs a test program that executes only some tests and verifies that
+    non-selected tests do not show up in the XML output.
+    """
+
+    self._TestXmlOutput(
+        GTEST_PROGRAM_NAME,
+        EXPECTED_FILTERED_TEST_XML,
+        0,
+        extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG],
+    )
+
+  def testShardedTestXmlOutput(self):
+    """Verifies XML output when run using multiple shards.
+
+    Runs a test program that executes only one shard and verifies that tests
+    from other shards do not show up in the XML output.
+    """
+
+    self._TestXmlOutput(
+        GTEST_PROGRAM_NAME,
+        EXPECTED_SHARDED_TEST_XML,
+        0,
+        extra_env={SHARD_INDEX_ENV_VAR: '0', TOTAL_SHARDS_ENV_VAR: '10'},
+    )
+
+  def _GetXmlOutput(
+      self, gtest_prog_name, extra_args, extra_env, expected_exit_code
+  ):
+    """Returns the XML output generated by running the program gtest_prog_name.
+
+    Furthermore, the program's exit code must be expected_exit_code.
+
+    Args:
+      gtest_prog_name: Program to run.
+      extra_args: Optional arguments to pass to program.
+      extra_env: Optional environment variables to set.
+      expected_exit_code: Expected exit code from running gtest_prog_name.
+    """
+    xml_path = os.path.join(
+        gtest_test_utils.GetTempDir(), gtest_prog_name + 'out.xml'
+    )
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
+
+    command = [
+        gtest_prog_path,
+        '%s=xml:%s' % (GTEST_OUTPUT_FLAG, xml_path),
+    ] + extra_args
+    environ_copy = os.environ.copy()
+    if extra_env:
+      environ_copy.update(extra_env)
+    p = gtest_test_utils.Subprocess(command, env=environ_copy)
+
+    if p.terminated_by_signal:
+      self.assertTrue(
+          False, '%s was killed by signal %d' % (gtest_prog_name, p.signal)
+      )
+    else:
+      self.assertTrue(p.exited)
+      self.assertEqual(
+          expected_exit_code,
+          p.exit_code,
+          "'%s' exited with code %s, which doesn't match "
+          'the expected exit code %s.'
+          % (command, p.exit_code, expected_exit_code),
+      )
+    actual = minidom.parse(xml_path)
+    return actual
+
+  def _TestXmlOutput(
+      self,
+      gtest_prog_name,
+      expected_xml,
+      expected_exit_code,
+      extra_args=None,
+      extra_env=None,
+  ):
+    """Asserts that the XML document matches.
+
+    Asserts that the XML document generated by running the program
+    gtest_prog_name matches expected_xml, a string containing another
+    XML document.  Furthermore, the program's exit code must be
+    expected_exit_code.
+
+    Args:
+      gtest_prog_name: Program to run.
+      expected_xml: Path to XML document to match.
+      expected_exit_code: Expected exit code from running gtest_prog_name.
+      extra_args: Optional arguments to pass to program.
+      extra_env: Optional environment variables to set.
+    """
+
+    actual = self._GetXmlOutput(
+        gtest_prog_name, extra_args or [], extra_env or {}, expected_exit_code
+    )
+    expected = minidom.parseString(expected_xml)
+    self.NormalizeXml(actual.documentElement)
+    self.AssertEquivalentNodes(expected.documentElement, actual.documentElement)
+    expected.unlink()
+    actual.unlink()
+
+
+if __name__ == '__main__':
+  os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
+  gtest_test_utils.Main()
diff --git a/3rd-party/googletest/googletest/test/gtest_xml_output_unittest_.cc b/3rd-party/googletest/googletest/test/gtest_xml_output_unittest_.cc
new file mode 100644
index 0000000..0ab3302
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_xml_output_unittest_.cc
@@ -0,0 +1,197 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test XML output.
+//
+// A user can specify XML output in a Google Test program to run via
+// either the GTEST_OUTPUT environment variable or the --gtest_output
+// flag.  This is used for testing such functionality.
+//
+// This program will be invoked from a Python unit test.  Don't run it
+// directly.
+// clang-format off
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestWithParam;
+using ::testing::UnitTest;
+using ::testing::Values;
+
+class SuccessfulTest : public Test {};
+
+TEST_F(SuccessfulTest, Succeeds) {
+  SUCCEED() << "This is a success.";
+  ASSERT_EQ(1, 1);
+}
+
+class FailedTest : public Test {
+};
+
+TEST_F(FailedTest, Fails) {
+  ASSERT_EQ(1, 2);
+}
+
+class DisabledTest : public Test {
+};
+
+TEST_F(DisabledTest, DISABLED_test_not_run) {
+  FAIL() << "Unexpected failure: Disabled test should not be run";
+}
+
+class SkippedTest : public Test {
+};
+
+TEST_F(SkippedTest, Skipped) {
+  GTEST_SKIP();
+}
+
+TEST_F(SkippedTest, SkippedWithMessage) {
+  GTEST_SKIP() << "It is good practice to tell why you skip a test.";
+}
+
+TEST_F(SkippedTest, SkippedAfterFailure) {
+  EXPECT_EQ(1, 2);
+  GTEST_SKIP() << "It is good practice to tell why you skip a test.";
+}
+
+TEST(MixedResultTest, Succeeds) {
+  EXPECT_EQ(1, 1);
+  ASSERT_EQ(1, 1);
+}
+
+TEST(MixedResultTest, Fails) {
+  EXPECT_EQ(1, 2);
+  ASSERT_EQ(2, 3);
+}
+
+TEST(MixedResultTest, DISABLED_test) {
+  FAIL() << "Unexpected failure: Disabled test should not be run";
+}
+
+TEST(XmlQuotingTest, OutputsCData) {
+  FAIL() << "XML output: "
+            "<?xml encoding=\"utf-8\"><top><![CDATA[cdata text]]></top>";
+}
+
+// Helps to test that invalid characters produced by test code do not make
+// it into the XML file.
+TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
+  FAIL() << "Invalid characters in brackets [\x1\x2]";
+}
+
+class PropertyRecordingTest : public Test {
+ public:
+  static void SetUpTestSuite() { RecordProperty("SetUpTestSuite", "yes"); }
+  static void TearDownTestSuite() {
+    RecordProperty("TearDownTestSuite", "aye");
+  }
+};
+
+TEST_F(PropertyRecordingTest, OneProperty) {
+  RecordProperty("key_1", "1");
+}
+
+TEST_F(PropertyRecordingTest, IntValuedProperty) {
+  RecordProperty("key_int", 1);
+}
+
+TEST_F(PropertyRecordingTest, ThreeProperties) {
+  RecordProperty("key_1", "1");
+  RecordProperty("key_2", "2");
+  RecordProperty("key_3", "3");
+}
+
+TEST_F(PropertyRecordingTest, TwoValuesForOneKeyUsesLastValue) {
+  RecordProperty("key_1", "1");
+  RecordProperty("key_1", "2");
+}
+
+TEST(NoFixtureTest, RecordProperty) {
+  RecordProperty("key", "1");
+}
+
+void ExternalUtilityThatCallsRecordProperty(const std::string& key, int value) {
+  testing::Test::RecordProperty(key, value);
+}
+
+void ExternalUtilityThatCallsRecordProperty(const std::string& key,
+                                            const std::string& value) {
+  testing::Test::RecordProperty(key, value);
+}
+
+TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
+  ExternalUtilityThatCallsRecordProperty("key_for_utility_int", 1);
+}
+
+TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
+  ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
+}
+
+// Verifies that the test parameter value is output in the 'value_param'
+// XML attribute for value-parameterized tests.
+class ValueParamTest : public TestWithParam<int> {};
+TEST_P(ValueParamTest, HasValueParamAttribute) {}
+TEST_P(ValueParamTest, AnotherTestThatHasValueParamAttribute) {}
+INSTANTIATE_TEST_SUITE_P(Single, ValueParamTest, Values(33, 42));
+
+// Verifies that the type parameter name is output in the 'type_param'
+// XML attribute for typed tests.
+template <typename T> class TypedTest : public Test {};
+typedef testing::Types<int, long> TypedTestTypes;
+TYPED_TEST_SUITE(TypedTest, TypedTestTypes);
+TYPED_TEST(TypedTest, HasTypeParamAttribute) {}
+
+// Verifies that the type parameter name is output in the 'type_param'
+// XML attribute for type-parameterized tests.
+template <typename T>
+class TypeParameterizedTestSuite : public Test {};
+TYPED_TEST_SUITE_P(TypeParameterizedTestSuite);
+TYPED_TEST_P(TypeParameterizedTestSuite, HasTypeParamAttribute) {}
+REGISTER_TYPED_TEST_SUITE_P(TypeParameterizedTestSuite, HasTypeParamAttribute);
+typedef testing::Types<int, long> TypeParameterizedTestSuiteTypes;  // NOLINT
+INSTANTIATE_TYPED_TEST_SUITE_P(Single, TypeParameterizedTestSuite,
+                               TypeParameterizedTestSuiteTypes);
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+    delete listeners.Release(listeners.default_xml_generator());
+  }
+  testing::Test::RecordProperty("ad_hoc_property", "42");
+  return RUN_ALL_TESTS();
+}
+
+// clang-format on
diff --git a/3rd-party/googletest/googletest/test/gtest_xml_test_utils.py b/3rd-party/googletest/googletest/test/gtest_xml_test_utils.py
new file mode 100755
index 0000000..74e0f4a
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/gtest_xml_test_utils.py
@@ -0,0 +1,242 @@
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for gtest_xml_output"""
+
+import re
+from xml.dom import minidom, Node
+from googletest.test import gtest_test_utils
+
+GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml'
+
+
+class GTestXMLTestCase(gtest_test_utils.TestCase):
+  """Base class for tests of Google Test's XML output functionality."""
+
+  def AssertEquivalentNodes(self, expected_node, actual_node):
+    """Asserts that actual_node is equivalent to expected_node.
+
+    Asserts that actual_node (a DOM node object) is equivalent to
+    expected_node (another DOM node object), in that either both of
+    them are CDATA nodes and have the same value, or both are DOM
+    elements and actual_node meets all of the following conditions:
+
+    *  It has the same tag name as expected_node.
+    *  It has the same set of attributes as expected_node, each with
+       the same value as the corresponding attribute of expected_node.
+       Exceptions are any attribute named "time", which needs only be
+       convertible to a floating-point number and any attribute named
+       "type_param" which only has to be non-empty.
+    *  It has an equivalent set of child nodes (including elements and
+       CDATA sections) as expected_node.  Note that we ignore the
+       order of the children as they are not guaranteed to be in any
+       particular order.
+
+    Args:
+      expected_node: expected DOM node object
+      actual_node: actual DOM node object
+    """
+
+    if expected_node.nodeType == Node.CDATA_SECTION_NODE:
+      self.assertEqual(Node.CDATA_SECTION_NODE, actual_node.nodeType)
+      self.assertEqual(expected_node.nodeValue, actual_node.nodeValue)
+      return
+
+    self.assertEqual(Node.ELEMENT_NODE, actual_node.nodeType)
+    self.assertEqual(Node.ELEMENT_NODE, expected_node.nodeType)
+    self.assertEqual(expected_node.tagName, actual_node.tagName)
+
+    expected_attributes = expected_node.attributes
+    actual_attributes = actual_node.attributes
+    self.assertEqual(
+        expected_attributes.length,
+        actual_attributes.length,
+        'attribute numbers differ in element %s:\nExpected: %r\nActual: %r'
+        % (
+            actual_node.tagName,
+            expected_attributes.keys(),
+            actual_attributes.keys(),
+        ),
+    )
+    for i in range(expected_attributes.length):
+      expected_attr = expected_attributes.item(i)
+      actual_attr = actual_attributes.get(expected_attr.name)
+      self.assertTrue(
+          actual_attr is not None,
+          'expected attribute %s not found in element %s'
+          % (expected_attr.name, actual_node.tagName),
+      )
+      self.assertEqual(
+          expected_attr.value,
+          actual_attr.value,
+          ' values of attribute %s in element %s differ: %s vs %s'
+          % (
+              expected_attr.name,
+              actual_node.tagName,
+              expected_attr.value,
+              actual_attr.value,
+          ),
+      )
+
+    expected_children = self._GetChildren(expected_node)
+    actual_children = self._GetChildren(actual_node)
+    self.assertEqual(
+        len(expected_children),
+        len(actual_children),
+        'number of child elements differ in element ' + actual_node.tagName,
+    )
+    for child_id, child in expected_children.items():
+      self.assertTrue(
+          child_id in actual_children,
+          '<%s> is not in <%s> (in element %s)'
+          % (child_id, actual_children, actual_node.tagName),
+      )
+      self.AssertEquivalentNodes(child, actual_children[child_id])
+
+  identifying_attribute = {
+      'testsuites': 'name',
+      'testsuite': 'name',
+      'testcase': 'name',
+      'failure': 'message',
+      'skipped': 'message',
+      'property': 'name',
+  }
+
+  def _GetChildren(self, element):
+    """Fetches all of the child nodes of element, a DOM Element object.
+
+    Returns them as the values of a dictionary keyed by the IDs of the children.
+    For <testsuites>, <testsuite>, <testcase>, and <property> elements, the ID
+    is the value of their "name" attribute; for <failure> elements, it is the
+    value of the "message" attribute; for <properties> elements, it is the value
+    of their parent's "name" attribute plus the literal string "properties";
+    CDATA sections and non-whitespace text nodes are concatenated into a single
+    CDATA section with ID "detail".  An exception is raised if any element other
+    than the above four is encountered, if two child elements with the same
+    identifying attributes are encountered, or if any other type of node is
+    encountered.
+
+    Args:
+      element: DOM Element object
+
+    Returns:
+      Dictionary where keys are the IDs of the children.
+    """
+
+    children = {}
+    for child in element.childNodes:
+      if child.nodeType == Node.ELEMENT_NODE:
+        if child.tagName == 'properties':
+          self.assertTrue(
+              child.parentNode is not None,
+              'Encountered <properties> element without a parent',
+          )
+          child_id = child.parentNode.getAttribute('name') + '-properties'
+        else:
+          self.assertTrue(
+              child.tagName in self.identifying_attribute,
+              'Encountered unknown element <%s>' % child.tagName,
+          )
+          child_id = child.getAttribute(
+              self.identifying_attribute[child.tagName]
+          )
+        self.assertNotIn(child_id, children)
+        children[child_id] = child
+      elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
+        if 'detail' not in children:
+          if (
+              child.nodeType == Node.CDATA_SECTION_NODE
+              or not child.nodeValue.isspace()
+          ):
+            children['detail'] = child.ownerDocument.createCDATASection(
+                child.nodeValue
+            )
+        else:
+          children['detail'].nodeValue += child.nodeValue
+      else:
+        self.fail('Encountered unexpected node type %d' % child.nodeType)
+    return children
+
+  def NormalizeXml(self, element):
+    """Normalizes XML that may change from run to run.
+
+    Normalizes Google Test's XML output to eliminate references to transient
+    information that may change from run to run.
+
+    *  The "time" attribute of <testsuites>, <testsuite> and <testcase>
+       elements is replaced with a single asterisk, if it contains
+       only digit characters.
+    *  The "timestamp" attribute of <testsuites> elements is replaced with a
+       single asterisk, if it contains a valid ISO8601 datetime value.
+    *  The "type_param" attribute of <testcase> elements is replaced with a
+       single asterisk (if it sn non-empty) as it is the type name returned
+       by the compiler and is platform dependent.
+    *  The line info reported in the first line of the "message"
+       attribute and CDATA section of <failure> elements is replaced with the
+       file's basename and a single asterisk for the line number.
+    *  The directory names in file paths are removed.
+    *  The stack traces are removed.
+
+    Args:
+      element: DOM element to normalize
+    """
+
+    if element.tagName == 'testcase':
+      source_file = element.getAttributeNode('file')
+      if source_file:
+        source_file.value = re.sub(r'^.*[/\\](.*)', '\\1', source_file.value)
+    if element.tagName in ('testsuites', 'testsuite', 'testcase'):
+      timestamp = element.getAttributeNode('timestamp')
+      timestamp.value = re.sub(
+          r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\d$', '*', timestamp.value
+      )
+    if element.tagName in ('testsuites', 'testsuite', 'testcase'):
+      time = element.getAttributeNode('time')
+      # The value for exact N seconds has a trailing decimal point (e.g., "10."
+      # instead of "10")
+      time.value = re.sub(r'^\d+\.(\d+)?$', '*', time.value)
+      type_param = element.getAttributeNode('type_param')
+      if type_param and type_param.value:
+        type_param.value = '*'
+    elif element.tagName == 'failure' or element.tagName == 'skipped':
+      source_line_pat = r'^.*[/\\](.*:)\d+\n'
+      # Replaces the source line information with a normalized form.
+      message = element.getAttributeNode('message')
+      message.value = re.sub(source_line_pat, '\\1*\n', message.value)
+      for child in element.childNodes:
+        if child.nodeType == Node.CDATA_SECTION_NODE:
+          # Replaces the source line information with a normalized form.
+          cdata = re.sub(source_line_pat, '\\1*\n', child.nodeValue)
+          # Removes the actual stack trace.
+          child.nodeValue = re.sub(
+              r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', cdata
+          )
+    for child in element.childNodes:
+      if child.nodeType == Node.ELEMENT_NODE:
+        self.NormalizeXml(child)
diff --git a/3rd-party/googletest/googletest/test/production.cc b/3rd-party/googletest/googletest/test/production.cc
new file mode 100644
index 0000000..0f69f6d
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/production.cc
@@ -0,0 +1,35 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// This is part of the unit test for gtest_prod.h.
+
+#include "production.h"
+
+PrivateCode::PrivateCode() : x_(0) {}
diff --git a/3rd-party/googletest/googletest/test/production.h b/3rd-party/googletest/googletest/test/production.h
new file mode 100644
index 0000000..4dec8d4
--- /dev/null
+++ b/3rd-party/googletest/googletest/test/production.h
@@ -0,0 +1,55 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// This is part of the unit test for gtest_prod.h.
+
+#ifndef GOOGLETEST_TEST_PRODUCTION_H_
+#define GOOGLETEST_TEST_PRODUCTION_H_
+
+#include "gtest/gtest_prod.h"
+
+class PrivateCode {
+ public:
+  // Declares a friend test that does not use a fixture.
+  FRIEND_TEST(PrivateCodeTest, CanAccessPrivateMembers);
+
+  // Declares a friend test that uses a fixture.
+  FRIEND_TEST(PrivateCodeFixtureTest, CanAccessPrivateMembers);
+
+  PrivateCode();
+
+  int x() const { return x_; }
+
+ private:
+  void set_x(int an_x) { x_ = an_x; }
+  int x_;
+};
+
+#endif  // GOOGLETEST_TEST_PRODUCTION_H_
diff --git a/3rd-party/googletest/googletest_deps.bzl b/3rd-party/googletest/googletest_deps.bzl
new file mode 100644
index 0000000..281af5c
--- /dev/null
+++ b/3rd-party/googletest/googletest_deps.bzl
@@ -0,0 +1,28 @@
+"""Load dependencies needed to use the googletest library as a 3rd-party consumer."""
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
+
+def googletest_deps():
+    """Loads common dependencies needed to use the googletest library."""
+
+    if not native.existing_rule("re2"):
+        http_archive(
+            name = "re2",
+            sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
+            strip_prefix = "re2-2024-07-02",
+            urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
+        )
+
+    if not native.existing_rule("abseil-cpp"):
+        http_archive(
+            name = "abseil-cpp",
+            sha256 = "733726b8c3a6d39a4120d7e45ea8b41a434cdacde401cba500f14236c49b39dc",
+            strip_prefix = "abseil-cpp-20240116.2",
+            urls = ["https://github.com/abseil/abseil-cpp/releases/download/20240116.2/abseil-cpp-20240116.2.tar.gz"],
+        )
+
+    if not native.existing_rule("fuchsia_sdk"):
+        fake_fuchsia_sdk(
+            name = "fuchsia_sdk",
+        )
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/.github/workflows/update.yml b/3rd-party/nlohmann_json_cmake_fetchcontent/.github/workflows/update.yml
new file mode 100644
index 0000000..17680b5
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/.github/workflows/update.yml
@@ -0,0 +1,27 @@
+on:
+  # For the initial commit:
+  push:
+    branches:
+      - master
+
+  # For the future releases:
+  schedule:
+    - cron:  '0 0 * * 0' # every week
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@master
+      with:
+        persist-credentials: false
+        fetch-depth: 0
+    - name: Commit files
+      run: |
+        git config --local user.email "action@github.com"
+        git config --local user.name "GitHub Actions"
+        ./update.py
+    - name: Push changes
+      uses: ad-m/github-push-action@master
+      with:
+        github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/CMakeLists.txt b/3rd-party/nlohmann_json_cmake_fetchcontent/CMakeLists.txt
new file mode 100644
index 0000000..8cc2768
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/CMakeLists.txt
@@ -0,0 +1,209 @@
+cmake_minimum_required(VERSION 3.1)
+
+##
+## PROJECT
+## name and version
+##
+project(nlohmann_json VERSION 3.11.2 LANGUAGES CXX)
+
+##
+## MAIN_PROJECT CHECK
+## determine if nlohmann_json is built as a subproject (using add_subdirectory) or if it is the main project
+##
+set(MAIN_PROJECT OFF)
+if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+    set(MAIN_PROJECT ON)
+endif()
+
+##
+## INCLUDE
+##
+##
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
+include(ExternalProject)
+
+##
+## OPTIONS
+##
+
+if (POLICY CMP0077)
+    # Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory.
+    cmake_policy(SET CMP0077 NEW)
+endif ()
+
+# VERSION_GREATER_EQUAL is not available in CMake 3.1
+if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13))
+    set(JSON_BuildTests_INIT ON)
+else()
+    set(JSON_BuildTests_INIT OFF)
+endif()
+option(JSON_BuildTests                     "Build the unit tests when BUILD_TESTING is enabled." ${JSON_BuildTests_INIT})
+option(JSON_CI                             "Enable CI build targets." OFF)
+option(JSON_Diagnostics                    "Use extended diagnostic messages." OFF)
+option(JSON_GlobalUDLs                     "Place use-defined string literals in the global namespace." ON)
+option(JSON_ImplicitConversions            "Enable implicit conversions." ON)
+option(JSON_DisableEnumSerialization       "Disable default integer enum serialization." OFF)
+option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF)           
+option(JSON_Install                        "Install CMake targets during install step." ${MAIN_PROJECT})
+option(JSON_MultipleHeaders                "Use non-amalgamated version of the library." OFF)
+option(JSON_SystemInclude                  "Include as system headers (skip for clang-tidy)." OFF)
+
+if (JSON_CI)
+    include(ci)
+endif ()
+
+##
+## CONFIGURATION
+##
+include(GNUInstallDirs)
+
+set(NLOHMANN_JSON_TARGET_NAME               ${PROJECT_NAME})
+set(NLOHMANN_JSON_CONFIG_INSTALL_DIR        "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "")
+set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR       "${CMAKE_INSTALL_INCLUDEDIR}")
+set(NLOHMANN_JSON_TARGETS_EXPORT_NAME       "${PROJECT_NAME}Targets")
+set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE     "cmake/config.cmake.in")
+set(NLOHMANN_JSON_CMAKE_CONFIG_DIR          "${CMAKE_CURRENT_BINARY_DIR}")
+set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
+set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
+set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
+set(NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR     "${CMAKE_INSTALL_DATADIR}/pkgconfig")
+
+if (JSON_MultipleHeaders)
+    set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")
+    message(STATUS "Using the multi-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
+else()
+    set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/single_include/")
+    message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
+endif()
+
+if (NOT JSON_ImplicitConversions)
+    message(STATUS "Implicit conversions are disabled")
+endif()
+
+if (JSON_DisableEnumSerialization)
+    message(STATUS "Enum integer serialization is disabled")
+endif()
+
+if (JSON_LegacyDiscardedValueComparison)
+    message(STATUS "Legacy discarded value comparison enabled")
+endif()
+
+if (JSON_Diagnostics)
+    message(STATUS "Diagnostics enabled")
+endif()
+
+if (JSON_SystemInclude)
+    set(NLOHMANN_JSON_SYSTEM_INCLUDE "SYSTEM")
+endif()
+
+##
+## TARGET
+## create target and add include path
+##
+add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
+add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
+if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
+    target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_range_for)
+else()
+    target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
+endif()
+
+target_compile_definitions(
+    ${NLOHMANN_JSON_TARGET_NAME}
+    INTERFACE
+    $<$<NOT:$<BOOL:${JSON_GlobalUDLs}>>:JSON_USE_GLOBAL_UDLS=0>
+    $<$<NOT:$<BOOL:${JSON_ImplicitConversions}>>:JSON_USE_IMPLICIT_CONVERSIONS=0>
+    $<$<BOOL:${JSON_DisableEnumSerialization}>:JSON_DISABLE_ENUM_SERIALIZATION=1>
+    $<$<BOOL:${JSON_Diagnostics}>:JSON_DIAGNOSTICS=1>
+    $<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
+)
+
+target_include_directories(
+    ${NLOHMANN_JSON_TARGET_NAME}
+    ${NLOHMANN_JSON_SYSTEM_INCLUDE} INTERFACE
+    $<BUILD_INTERFACE:${NLOHMANN_JSON_INCLUDE_BUILD_DIR}>
+    $<INSTALL_INTERFACE:include>
+)
+
+## add debug view definition file for msvc (natvis)
+if (MSVC)
+    set(NLOHMANN_ADD_NATVIS TRUE)
+    set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis")
+    target_sources(
+        ${NLOHMANN_JSON_TARGET_NAME}
+        INTERFACE
+            $<INSTALL_INTERFACE:${NLOHMANN_NATVIS_FILE}>
+            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NLOHMANN_NATVIS_FILE}>
+    )
+endif()
+
+# Install a pkg-config file, so other tools can find this.
+CONFIGURE_FILE(
+    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
+    "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
+)
+
+##
+## TESTS
+## create and configure the unit test target
+##
+if (JSON_BuildTests)
+    include(CTest)
+    enable_testing()
+    add_subdirectory(tests)
+endif()
+
+##
+## INSTALL
+## install header files, generate and install cmake config files for find_package()
+##
+include(CMakePackageConfigHelpers)
+# use a custom package version config file instead of
+# write_basic_package_version_file to ensure that it's architecture-independent
+# https://github.com/nlohmann/json/issues/1697
+configure_file(
+    "cmake/nlohmann_jsonConfigVersion.cmake.in"
+    ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
+    @ONLY
+)
+configure_file(
+    ${NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE}
+    ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE}
+    @ONLY
+)
+
+if(JSON_Install)
+    install(
+        DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
+        DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
+    )
+    install(
+        FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
+        DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
+    )
+    if (NLOHMANN_ADD_NATVIS)
+        install(
+            FILES ${NLOHMANN_NATVIS_FILE}
+            DESTINATION .
+    )
+    endif()
+    export(
+        TARGETS ${NLOHMANN_JSON_TARGET_NAME}
+        NAMESPACE ${PROJECT_NAME}::
+        FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
+    )
+    install(
+        TARGETS ${NLOHMANN_JSON_TARGET_NAME}
+        EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
+        INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
+    )
+    install(
+        EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
+        NAMESPACE ${PROJECT_NAME}::
+        DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
+    )
+    install(
+        FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
+        DESTINATION ${NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR}
+    )
+endif()
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/LICENSE.MIT b/3rd-party/nlohmann_json_cmake_fetchcontent/LICENSE.MIT
new file mode 100644
index 0000000..1c1f7a6
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/LICENSE.MIT
@@ -0,0 +1,21 @@
+MIT License 
+
+Copyright (c) 2013-2022 Niels Lohmann
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/README.md b/3rd-party/nlohmann_json_cmake_fetchcontent/README.md
new file mode 100644
index 0000000..94ae3ac
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/README.md
@@ -0,0 +1,71 @@
+This repository is not more useful. Indeed, since v3.11.3, you can use:
+```cmake
+include(FetchContent)
+
+FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
+FetchContent_MakeAvailable(json)
+
+target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
+```
+
+# Release-tracking repository for nlohmann/json
+
+Goal is to provide a lightweight and autonomous repository tracking every
+releases of [nlohmann/json](https://github.com/nlohmann/json).
+
+It is meant to be used with CMake
+[FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html).
+
+You can always replace the URL by the official repository:
+<https://github.com/nlohmann/json>.
+The only differences are:
+
+* The download size: ~500KB vs ~150MB (300× difference)
+* Some options are not available. See [the unsupported options section](#Unsupported-options).
+
+## Example
+
+~~~cmake
+include(FetchContent)
+
+# Optional: set this to ON if your target publicly links to nlohmann_json and needs to install() 
+# set(JSON_Install ON)
+
+FetchContent_Declare(json
+  GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent
+  GIT_PROGRESS TRUE  GIT_SHALLOW TRUE
+  GIT_TAG v3.11.2)
+
+FetchContent_MakeAvailable(json)
+
+target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
+~~~
+
+## Unsupported options
+
+The following options are currently not supported. This is done on purpose
+because they do not really make sense for a mirror repository, or they have not
+been thoroughly tested. Consider using the official repository if you need these
+options.
+
+* `JSON_CI`
+* `JSON_BuildTests`
+
+## Updates
+
+This repository is fully autonomous. It updates itself every week using github
+actions.
+
+### Thanks
+
+This repository is based on: [astoeckel/json](https://github.com/astoeckel/json).
+
+### Addressed `nlohmann/json` issues:
+
+* [#2073](https://github.com/nlohmann/json/issues/2073),
+* [#732](https://github.com/nlohmann/json/issues/732),
+* [#620](https://github.com/nlohmann/json/issues/620),
+* [#556](https://github.com/nlohmann/json/issues/556),
+* [#482](https://github.com/nlohmann/json/issues/482),
+* [#96](https://github.com/nlohmann/json/issues/96)
+
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/ci.cmake b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/ci.cmake
new file mode 100644
index 0000000..0897869
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/ci.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "The JSON_CI option is not availablewhen using the nlohmann_json_cmake_fetchcontent repository.")
\ No newline at end of file
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/config.cmake.in b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/config.cmake.in
new file mode 100644
index 0000000..9a17a7d
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/config.cmake.in
@@ -0,0 +1,15 @@
+include(FindPackageHandleStandardArgs)
+set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE})
+find_package_handle_standard_args(@PROJECT_NAME@ CONFIG_MODE)
+
+if(NOT TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
+    include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
+    if((NOT TARGET @NLOHMANN_JSON_TARGET_NAME@) AND
+       (NOT @PROJECT_NAME@_FIND_VERSION OR
+        @PROJECT_NAME@_FIND_VERSION VERSION_LESS 3.2.0))
+        add_library(@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED)
+        set_target_properties(@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
+            INTERFACE_LINK_LIBRARIES @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@
+        )
+    endif()
+endif()
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/download_test_data.cmake b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/download_test_data.cmake
new file mode 100644
index 0000000..1bb998d
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/download_test_data.cmake
@@ -0,0 +1,56 @@
+set(JSON_TEST_DATA_URL     https://github.com/nlohmann/json_test_data)
+set(JSON_TEST_DATA_VERSION 3.1.0)
+
+# if variable is set, use test data from given directory rather than downloading them
+if(JSON_TestDataDirectory)
+    message(STATUS "Using test data in ${JSON_TestDataDirectory}.")
+    add_custom_target(download_test_data)
+    file(WRITE ${CMAKE_BINARY_DIR}/include/test_data.hpp "#define TEST_DATA_DIRECTORY \"${JSON_TestDataDirectory}\"\n")
+else()
+    find_package(Git)
+    # target to download test data
+    add_custom_target(download_test_data
+        COMMAND test -d json_test_data || ${GIT_EXECUTABLE} clone -c advice.detachedHead=false --branch v${JSON_TEST_DATA_VERSION} ${JSON_TEST_DATA_URL}.git --quiet --depth 1
+        COMMENT "Downloading test data from ${JSON_TEST_DATA_URL} (v${JSON_TEST_DATA_VERSION})"
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+    )
+    # create a header with the path to the downloaded test data
+    file(WRITE ${CMAKE_BINARY_DIR}/include/test_data.hpp "#define TEST_DATA_DIRECTORY \"${CMAKE_BINARY_DIR}/json_test_data\"\n")
+endif()
+
+# determine the operating system (for debug and support purposes)
+find_program(UNAME_COMMAND uname)
+find_program(VER_COMMAND ver)
+find_program(LSB_RELEASE_COMMAND lsb_release)
+find_program(SW_VERS_COMMAND sw_vers)
+set(OS_VERSION_STRINGS "${CMAKE_SYSTEM}")
+if (VER_COMMAND)
+    execute_process(COMMAND ${VER_COMMAND} OUTPUT_VARIABLE VER_COMMAND_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE)
+    set(OS_VERSION_STRINGS "${OS_VERSION_STRINGS}; ${VER_COMMAND_RESULT}")
+endif()
+if (SW_VERS_COMMAND)
+    execute_process(COMMAND ${SW_VERS_COMMAND} OUTPUT_VARIABLE SW_VERS_COMMAND_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
+    string(REGEX REPLACE "[ ]*\n" "; " SW_VERS_COMMAND_RESULT "${SW_VERS_COMMAND_RESULT}")
+    set(OS_VERSION_STRINGS "${OS_VERSION_STRINGS}; ${SW_VERS_COMMAND_RESULT}")
+endif()
+if (LSB_RELEASE_COMMAND)
+    execute_process(COMMAND ${LSB_RELEASE_COMMAND} -a OUTPUT_VARIABLE LSB_RELEASE_COMMAND_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
+    string(REGEX REPLACE "[ ]*\n" "; " LSB_RELEASE_COMMAND_RESULT "${LSB_RELEASE_COMMAND_RESULT}")
+    set(OS_VERSION_STRINGS "${OS_VERSION_STRINGS}; ${LSB_RELEASE_COMMAND_RESULT}")
+endif()
+if (UNAME_COMMAND)
+    execute_process(COMMAND ${UNAME_COMMAND} -a OUTPUT_VARIABLE UNAME_COMMAND_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
+    set(OS_VERSION_STRINGS "${OS_VERSION_STRINGS}; ${UNAME_COMMAND_RESULT}")
+endif()
+
+message(STATUS "Operating system: ${OS_VERSION_STRINGS}")
+
+# determine the compiler (for debug and support purposes)
+if (MSVC)
+    execute_process(COMMAND ${CMAKE_CXX_COMPILER} OUTPUT_VARIABLE CXX_VERSION_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE CXX_VERSION_RESULT ERROR_STRIP_TRAILING_WHITESPACE)
+    set(CXX_VERSION_RESULT "${CXX_VERSION_RESULT}; MSVC_VERSION=${MSVC_VERSION}; MSVC_TOOLSET_VERSION=${MSVC_TOOLSET_VERSION}")
+else()
+    execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE CXX_VERSION_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif()
+string(REGEX REPLACE "[ ]*\n" "; " CXX_VERSION_RESULT "${CXX_VERSION_RESULT}")
+message(STATUS "Compiler: ${CXX_VERSION_RESULT}")
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/nlohmann_jsonConfigVersion.cmake.in b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/nlohmann_jsonConfigVersion.cmake.in
new file mode 100644
index 0000000..1091085
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/nlohmann_jsonConfigVersion.cmake.in
@@ -0,0 +1,20 @@
+# This is essentially cmake's BasicConfigVersion-SameMajorVersion.cmake.in but
+# without the 32/64-bit check.  Since json is a header-only library, it doesn't
+# matter if it was built on a different platform than what it is used on (see
+# https://github.com/nlohmann/json/issues/1697).
+set(PACKAGE_VERSION "@PROJECT_VERSION@")
+
+if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
+  set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+
+  if(PACKAGE_FIND_VERSION_MAJOR STREQUAL "@PROJECT_VERSION_MAJOR@")
+    set(PACKAGE_VERSION_COMPATIBLE TRUE)
+  else()
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+  endif()
+
+  if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
+      set(PACKAGE_VERSION_EXACT TRUE)
+  endif()
+endif()
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/pkg-config.pc.in b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/pkg-config.pc.in
new file mode 100644
index 0000000..d36317f
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/pkg-config.pc.in
@@ -0,0 +1,4 @@
+Name: ${PROJECT_NAME}
+Description: JSON for Modern C++
+Version: ${PROJECT_VERSION}
+Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR}
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/test.cmake b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/test.cmake
new file mode 100644
index 0000000..bb840c6
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/cmake/test.cmake
@@ -0,0 +1,273 @@
+set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE})
+
+#############################################################################
+# download test data
+#############################################################################
+
+include(download_test_data)
+
+# test fixture to download test data
+add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
+    --target download_test_data
+)
+set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA)
+
+if(JSON_Valgrind)
+    find_program(CMAKE_MEMORYCHECK_COMMAND valgrind)
+    message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})")
+    set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
+    separate_arguments(memcheck_command)
+endif()
+
+#############################################################################
+# detect standard support
+#############################################################################
+
+# C++11 is the minimum required
+set(compiler_supports_cpp_11 TRUE)
+
+foreach(feature ${CMAKE_CXX_COMPILE_FEATURES})
+    if (${feature} STREQUAL cxx_std_14)
+        set(compiler_supports_cpp_14 TRUE)
+    elseif (${feature} STREQUAL cxx_std_17)
+        set(compiler_supports_cpp_17 TRUE)
+    elseif (${feature} STREQUAL cxx_std_20)
+        set(compiler_supports_cpp_20 TRUE)
+    elseif (${feature} STREQUAL cxx_std_23)
+        set(compiler_supports_cpp_23 TRUE)
+    endif()
+endforeach()
+
+#############################################################################
+# test functions
+#############################################################################
+
+#############################################################################
+# json_test_set_test_options(
+#     all|<tests>
+#     [CXX_STANDARDS all|<args>...]
+#     [COMPILE_DEFINITIONS <args>...]
+#     [COMPILE_FEATURES <args>...]
+#     [COMPILE_OPTIONS <args>...]
+#     [LINK_LIBRARIES <args>...]
+#     [LINK_OPTIONS <args>...]
+#     [TEST_PROPERTIES <args>...])
+#
+# Supply test- and standard-specific build settings and/or test properties.
+# Specify multiple tests using a list e.g., "test-foo;test-bar".
+#
+# Must be called BEFORE the test is created.
+#############################################################################
+
+function(json_test_set_test_options tests)
+    cmake_parse_arguments(args "" ""
+        "CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS;TEST_PROPERTIES"
+        ${ARGN})
+
+    if(NOT args_CXX_STANDARDS)
+        set(args_CXX_STANDARDS "all")
+    endif()
+
+    foreach(test ${tests})
+        if("${test}" STREQUAL "all")
+            set(test "")
+        endif()
+
+        foreach(cxx_standard ${args_CXX_STANDARDS})
+            if("${cxx_standard}" STREQUAL "all")
+                if("${test}" STREQUAL "")
+                    message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}")
+                endif()
+                set(test_interface _json_test_interface_${test})
+            else()
+                set(test_interface _json_test_interface_${test}_cpp_${cxx_standard})
+            endif()
+
+            if(NOT TARGET ${test_interface})
+                add_library(${test_interface} INTERFACE)
+            endif()
+
+            target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS})
+            target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES})
+            target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS})
+            target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES})
+            target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS})
+            #set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}")
+            set_property(DIRECTORY PROPERTY
+                ${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}"
+            )
+        endforeach()
+    endforeach()
+endfunction()
+
+# for internal use by _json_test_add_test()
+function(_json_test_apply_test_properties test_target properties_target)
+    #get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES)
+    get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES)
+    if(test_properties)
+        set_tests_properties(${test_target} PROPERTIES ${test_properties})
+    endif()
+endfunction()
+
+# for internal use by json_test_add_test_for()
+function(_json_test_add_test test_name file main cxx_standard)
+    set(test_target ${test_name}_cpp${cxx_standard})
+
+    if(TARGET ${test_target})
+        message(FATAL_ERROR "Target ${test_target} has already been added.")
+    endif()
+
+    add_executable(${test_target} ${file})
+    target_link_libraries(${test_target} PRIVATE ${main})
+
+    # set and require C++ standard
+    set_target_properties(${test_target} PROPERTIES
+        CXX_STANDARD ${cxx_standard}
+        CXX_STANDARD_REQUIRED ON
+    )
+
+    # apply standard-specific build settings
+    if(TARGET _json_test_interface__cpp_${cxx_standard})
+        target_link_libraries(${test_target} PRIVATE _json_test_interface__cpp_${cxx_standard})
+    endif()
+
+    # apply test-specific build settings
+    if(TARGET _json_test_interface_${test_name})
+        target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name})
+    endif()
+
+    # apply test- and standard-specific build settings
+    if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
+        target_link_libraries(${test_target} PRIVATE
+            _json_test_interface_${test_name}_cpp_${cxx_standard}
+        )
+    endif()
+
+    if (JSON_FastTests)
+        add_test(NAME ${test_target}
+            COMMAND ${test_target} ${DOCTEST_TEST_FILTER}
+            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+        )
+    else()
+        add_test(NAME ${test_target}
+            COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip
+            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+        )
+    endif()
+    set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
+
+    # apply standard-specific test properties
+    if(TARGET _json_test_interface__cpp_${cxx_standard})
+        _json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard})
+    endif()
+
+    # apply test-specific test properties
+    if(TARGET _json_test_interface_${test_name})
+        _json_test_apply_test_properties(${test_target} _json_test_interface_${test_name})
+    endif()
+
+    # apply test- and standard-specific test properties
+    if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
+        _json_test_apply_test_properties(${test_target}
+            _json_test_interface_${test_name}_cpp_${cxx_standard}
+        )
+    endif()
+
+    if(JSON_Valgrind)
+        add_test(NAME ${test_target}_valgrind
+            COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER}
+            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+        )
+        set_tests_properties(${test_target}_valgrind PROPERTIES
+            LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA
+        )
+    endif()
+endfunction()
+
+#############################################################################
+# json_test_add_test_for(
+#     <file>
+#     [NAME <name>]
+#     MAIN <main>
+#     [CXX_STANDARDS <version_number>...] [FORCE])
+#
+# Given a <file> unit-foo.cpp, produces
+#
+#     test-foo_cpp<version_number>
+#
+# if C++ standard <version_number> is supported by the compiler and the
+# source file contains JSON_HAS_CPP_<version_number>.
+# Use NAME <name> to override the filename-derived test name.
+# Use FORCE to create the test regardless of the file containing
+# JSON_HAS_CPP_<version_number>.
+# Test targets are linked against <main>.
+# CXX_STANDARDS defaults to "11".
+#############################################################################
+
+function(json_test_add_test_for file)
+    cmake_parse_arguments(args "FORCE" "MAIN;NAME" "CXX_STANDARDS" ${ARGN})
+
+    if("${args_MAIN}" STREQUAL "")
+        message(FATAL_ERROR "Required argument MAIN <main> missing.")
+    endif()
+
+    if("${args_NAME}" STREQUAL "")
+        get_filename_component(file_basename ${file} NAME_WE)
+        string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename})
+    else()
+        set(test_name ${args_NAME})
+        if(NOT test_name MATCHES "test-[^$]+")
+            message(FATAL_ERROR "Test name must start with 'test-'.")
+        endif()
+    endif()
+
+    if("${args_CXX_STANDARDS}" STREQUAL "")
+        set(args_CXX_STANDARDS 11)
+    endif()
+
+    file(READ ${file} file_content)
+    foreach(cxx_standard ${args_CXX_STANDARDS})
+        if(NOT compiler_supports_cpp_${cxx_standard})
+            continue()
+        endif()
+
+        # add unconditionally if C++11 (default) or forced
+        if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE))
+            string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found)
+            if(${has_cpp_found} EQUAL -1)
+                continue()
+            endif()
+        endif()
+
+        _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard})
+    endforeach()
+endfunction()
+
+#############################################################################
+# json_test_should_build_32bit_test(
+#     <build_32bit_var> <build_32bit_only_var> <input>)
+#
+# Check if the 32bit unit test should be built based on the value of <input>
+# and store the result in the variables <build_32bit_var> and
+# <build_32bit_only_var>.
+#############################################################################
+
+function(json_test_should_build_32bit_test build_32bit_var build_32bit_only_var input)
+    set(${build_32bit_only_var} OFF PARENT_SCOPE)
+    string(TOUPPER "${input}" ${build_32bit_var})
+    if("${${build_32bit_var}}" STREQUAL AUTO)
+        # check if compiler is targeting 32bit by default
+        include(CheckTypeSize)
+        check_type_size("size_t" sizeof_size_t LANGUAGE CXX)
+        if(sizeof_size_t AND ${sizeof_size_t} EQUAL 4)
+            message(STATUS "Auto-enabling 32bit unit test.")
+            set(${build_32bit_var} ON)
+        else()
+            set(${build_32bit_var} OFF)
+        endif()
+    elseif("${${build_32bit_var}}" STREQUAL ONLY)
+        set(${build_32bit_only_var} ON PARENT_SCOPE)
+    endif()
+
+    set(${build_32bit_var} "${${build_32bit_var}}" PARENT_SCOPE)
+endfunction()
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/meson.build b/3rd-party/nlohmann_json_cmake_fetchcontent/meson.build
new file mode 100644
index 0000000..e2fb86f
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/meson.build
@@ -0,0 +1,24 @@
+project('nlohmann_json',
+    'cpp',
+    version : '3.11.2',
+    license : 'MIT',
+)
+
+nlohmann_json_dep = declare_dependency(
+    include_directories: include_directories('single_include')
+)
+
+nlohmann_json_multiple_headers = declare_dependency(
+    include_directories: include_directories('include')
+)
+
+if not meson.is_subproject()
+install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
+install_headers('single_include/nlohmann/json_fwd.hpp', subdir: 'nlohmann')
+
+pkgc = import('pkgconfig')
+pkgc.generate(name: 'nlohmann_json',
+    version: meson.project_version(),
+    description: 'JSON for Modern C++'
+)
+endif
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/single_include/nlohmann/json.hpp b/3rd-party/nlohmann_json_cmake_fetchcontent/single_include/nlohmann/json.hpp
new file mode 100644
index 0000000..4d1a37a
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/single_include/nlohmann/json.hpp
@@ -0,0 +1,24596 @@
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+/****************************************************************************\
+ * Note on documentation: The source files contain links to the online      *
+ * documentation of the public API at https://json.nlohmann.me. This URL    *
+ * contains the most recent documentation and should also be applicable to  *
+ * previous versions; documentation for deprecated functions is not         *
+ * removed, but marked deprecated. See "Generate documentation" section in  *
+ * file docs/README.md.                                                     *
+\****************************************************************************/
+
+#ifndef INCLUDE_NLOHMANN_JSON_HPP_
+#define INCLUDE_NLOHMANN_JSON_HPP_
+
+#include <algorithm> // all_of, find, for_each
+#include <cstddef> // nullptr_t, ptrdiff_t, size_t
+#include <functional> // hash, less
+#include <initializer_list> // initializer_list
+#ifndef JSON_NO_IO
+    #include <iosfwd> // istream, ostream
+#endif  // JSON_NO_IO
+#include <iterator> // random_access_iterator_tag
+#include <memory> // unique_ptr
+#include <numeric> // accumulate
+#include <string> // string, stoi, to_string
+#include <utility> // declval, forward, move, pair, swap
+#include <vector> // vector
+
+// #include <nlohmann/adl_serializer.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <utility>
+
+// #include <nlohmann/detail/abi_macros.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// This file contains all macro definitions affecting or depending on the ABI
+
+#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
+    #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
+        #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
+            #warning "Already included a different version of the library!"
+        #endif
+    #endif
+#endif
+
+#define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum)
+#define NLOHMANN_JSON_VERSION_MINOR 11  // NOLINT(modernize-macro-to-enum)
+#define NLOHMANN_JSON_VERSION_PATCH 2   // NOLINT(modernize-macro-to-enum)
+
+#ifndef JSON_DIAGNOSTICS
+    #define JSON_DIAGNOSTICS 0
+#endif
+
+#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+    #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
+#endif
+
+#if JSON_DIAGNOSTICS
+    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
+#else
+    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
+#endif
+
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+    #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
+#else
+    #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
+#endif
+
+#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
+    #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
+#endif
+
+// Construct the namespace ABI tags component
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
+
+#define NLOHMANN_JSON_ABI_TAGS                                       \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
+            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
+            NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
+
+// Construct the namespace version component
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
+    _v ## major ## _ ## minor ## _ ## patch
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
+
+#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
+#define NLOHMANN_JSON_NAMESPACE_VERSION
+#else
+#define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
+                                           NLOHMANN_JSON_VERSION_MINOR, \
+                                           NLOHMANN_JSON_VERSION_PATCH)
+#endif
+
+// Combine namespace components
+#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
+#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
+    NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
+
+#ifndef NLOHMANN_JSON_NAMESPACE
+#define NLOHMANN_JSON_NAMESPACE               \
+    nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
+            NLOHMANN_JSON_ABI_TAGS,           \
+            NLOHMANN_JSON_NAMESPACE_VERSION)
+#endif
+
+#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
+#define NLOHMANN_JSON_NAMESPACE_BEGIN                \
+    namespace nlohmann                               \
+    {                                                \
+    inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
+                NLOHMANN_JSON_ABI_TAGS,              \
+                NLOHMANN_JSON_NAMESPACE_VERSION)     \
+    {
+#endif
+
+#ifndef NLOHMANN_JSON_NAMESPACE_END
+#define NLOHMANN_JSON_NAMESPACE_END                                     \
+    }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
+    }  // namespace nlohmann
+#endif
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // transform
+#include <array> // array
+#include <forward_list> // forward_list
+#include <iterator> // inserter, front_inserter, end
+#include <map> // map
+#include <string> // string
+#include <tuple> // tuple, make_tuple
+#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
+#include <unordered_map> // unordered_map
+#include <utility> // pair, declval
+#include <valarray> // valarray
+
+// #include <nlohmann/detail/exceptions.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstddef> // nullptr_t
+#include <exception> // exception
+#include <stdexcept> // runtime_error
+#include <string> // to_string
+#include <vector> // vector
+
+// #include <nlohmann/detail/value_t.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t
+#include <string> // string
+
+// #include <nlohmann/detail/macro_scope.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <utility> // declval, pair
+// #include <nlohmann/detail/meta/detected.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <type_traits>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename ...Ts> struct make_void
+{
+    using type = void;
+};
+template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+// https://en.cppreference.com/w/cpp/experimental/is_detected
+struct nonesuch
+{
+    nonesuch() = delete;
+    ~nonesuch() = delete;
+    nonesuch(nonesuch const&) = delete;
+    nonesuch(nonesuch const&&) = delete;
+    void operator=(nonesuch const&) = delete;
+    void operator=(nonesuch&&) = delete;
+};
+
+template<class Default,
+         class AlwaysVoid,
+         template<class...> class Op,
+         class... Args>
+struct detector
+{
+    using value_t = std::false_type;
+    using type = Default;
+};
+
+template<class Default, template<class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+    using value_t = std::true_type;
+    using type = Op<Args...>;
+};
+
+template<template<class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
+
+template<template<class...> class Op, class... Args>
+struct is_detected_lazy : is_detected<Op, Args...> { };
+
+template<template<class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template<class Expected, template<class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template<class To, template<class...> class Op, class... Args>
+using is_detected_convertible =
+    std::is_convertible<detected_t<Op, Args...>, To>;
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/thirdparty/hedley/hedley.hpp>
+
+
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
+// SPDX-License-Identifier: MIT
+
+/* Hedley - https://nemequ.github.io/hedley
+ * Created by Evan Nemerson <evan@nemerson.com>
+ */
+
+#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
+#if defined(JSON_HEDLEY_VERSION)
+    #undef JSON_HEDLEY_VERSION
+#endif
+#define JSON_HEDLEY_VERSION 15
+
+#if defined(JSON_HEDLEY_STRINGIFY_EX)
+    #undef JSON_HEDLEY_STRINGIFY_EX
+#endif
+#define JSON_HEDLEY_STRINGIFY_EX(x) #x
+
+#if defined(JSON_HEDLEY_STRINGIFY)
+    #undef JSON_HEDLEY_STRINGIFY
+#endif
+#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
+
+#if defined(JSON_HEDLEY_CONCAT_EX)
+    #undef JSON_HEDLEY_CONCAT_EX
+#endif
+#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
+
+#if defined(JSON_HEDLEY_CONCAT)
+    #undef JSON_HEDLEY_CONCAT
+#endif
+#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
+
+#if defined(JSON_HEDLEY_CONCAT3_EX)
+    #undef JSON_HEDLEY_CONCAT3_EX
+#endif
+#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
+
+#if defined(JSON_HEDLEY_CONCAT3)
+    #undef JSON_HEDLEY_CONCAT3
+#endif
+#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
+
+#if defined(JSON_HEDLEY_VERSION_ENCODE)
+    #undef JSON_HEDLEY_VERSION_ENCODE
+#endif
+#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
+    #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
+    #undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
+    #undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
+
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+    #undef JSON_HEDLEY_GNUC_VERSION
+#endif
+#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
+    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#elif defined(__GNUC__)
+    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
+    #undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION)
+    #undef JSON_HEDLEY_MSVC_VERSION
+#endif
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
+#elif defined(_MSC_FULL_VER) && !defined(__ICL)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
+#elif defined(_MSC_VER) && !defined(__ICL)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
+    #undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#endif
+#if !defined(JSON_HEDLEY_MSVC_VERSION)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
+#else
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+    #undef JSON_HEDLEY_INTEL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
+    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
+#elif defined(__INTEL_COMPILER) && !defined(__ICL)
+    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
+    #undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
+    #undef JSON_HEDLEY_INTEL_CL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
+    #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
+    #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
+    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION)
+    #undef JSON_HEDLEY_PGI_VERSION
+#endif
+#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
+    #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
+    #undef JSON_HEDLEY_PGI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PGI_VERSION)
+    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+    #undef JSON_HEDLEY_SUNPRO_VERSION
+#endif
+#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
+#elif defined(__SUNPRO_C)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
+#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
+#elif defined(__SUNPRO_CC)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
+    #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#endif
+#if defined(__EMSCRIPTEN__)
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
+    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION)
+    #undef JSON_HEDLEY_ARM_VERSION
+#endif
+#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
+#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
+    #undef JSON_HEDLEY_ARM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_ARM_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION)
+    #undef JSON_HEDLEY_IBM_VERSION
+#endif
+#if defined(__ibmxl__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
+#elif defined(__xlC__) && defined(__xlC_ver__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
+#elif defined(__xlC__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
+    #undef JSON_HEDLEY_IBM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IBM_VERSION)
+    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION)
+    #undef JSON_HEDLEY_TI_VERSION
+#endif
+#if \
+    defined(__TI_COMPILER_VERSION__) && \
+    ( \
+      defined(__TMS470__) || defined(__TI_ARM__) || \
+      defined(__MSP430__) || \
+      defined(__TMS320C2000__) \
+    )
+#if (__TI_COMPILER_VERSION__ >= 16000000)
+    #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_VERSION)
+    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
+    #undef JSON_HEDLEY_TI_CL2000_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
+    #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
+    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL430_VERSION)
+    #undef JSON_HEDLEY_TI_CL430_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
+    #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL430_VERSION)
+    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
+    #undef JSON_HEDLEY_TI_ARMCL_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
+    #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
+    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
+    #undef JSON_HEDLEY_TI_CL6X_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
+    #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
+    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
+    #undef JSON_HEDLEY_TI_CL7X_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
+    #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
+    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
+    #undef JSON_HEDLEY_TI_CLPRU_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
+    #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
+    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+    #undef JSON_HEDLEY_CRAY_VERSION
+#endif
+#if defined(_CRAYC)
+    #if defined(_RELEASE_PATCHLEVEL)
+        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
+    #else
+        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
+    #endif
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
+    #undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION)
+    #undef JSON_HEDLEY_IAR_VERSION
+#endif
+#if defined(__IAR_SYSTEMS_ICC__)
+    #if __VER__ > 1000
+        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
+    #else
+        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
+    #endif
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
+    #undef JSON_HEDLEY_IAR_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IAR_VERSION)
+    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+    #undef JSON_HEDLEY_TINYC_VERSION
+#endif
+#if defined(__TINYC__)
+    #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
+    #undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION)
+    #undef JSON_HEDLEY_DMC_VERSION
+#endif
+#if defined(__DMC__)
+    #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
+    #undef JSON_HEDLEY_DMC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_DMC_VERSION)
+    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+    #undef JSON_HEDLEY_COMPCERT_VERSION
+#endif
+#if defined(__COMPCERT_VERSION__)
+    #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
+    #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+    #undef JSON_HEDLEY_PELLES_VERSION
+#endif
+#if defined(__POCC__)
+    #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
+    #undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
+    #undef JSON_HEDLEY_MCST_LCC_VERSION
+#endif
+#if defined(__LCC__) && defined(__LCC_MINOR__)
+    #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
+#endif
+
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
+    #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
+    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION)
+    #undef JSON_HEDLEY_GCC_VERSION
+#endif
+#if \
+    defined(JSON_HEDLEY_GNUC_VERSION) && \
+    !defined(__clang__) && \
+    !defined(JSON_HEDLEY_INTEL_VERSION) && \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_ARM_VERSION) && \
+    !defined(JSON_HEDLEY_CRAY_VERSION) && \
+    !defined(JSON_HEDLEY_TI_VERSION) && \
+    !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
+    !defined(__COMPCERT__) && \
+    !defined(JSON_HEDLEY_MCST_LCC_VERSION)
+    #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
+    #undef JSON_HEDLEY_GCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GCC_VERSION)
+    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_ATTRIBUTE
+#endif
+#if \
+  defined(__has_attribute) && \
+  ( \
+    (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
+  )
+#  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
+#else
+#  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#endif
+#if \
+    defined(__has_cpp_attribute) && \
+    defined(__cplusplus) && \
+    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
+    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#endif
+#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#elif \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_IAR_VERSION) && \
+    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
+    (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
+#else
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_BUILTIN)
+    #undef JSON_HEDLEY_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
+    #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
+    #undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_FEATURE)
+    #undef JSON_HEDLEY_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
+    #undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
+    #undef JSON_HEDLEY_GCC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_EXTENSION)
+    #undef JSON_HEDLEY_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
+    #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
+    #undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_WARNING)
+    #undef JSON_HEDLEY_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_HAS_WARNING(warning) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
+    #undef JSON_HEDLEY_GNUC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
+    #undef JSON_HEDLEY_GCC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if \
+    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+    defined(__clang__) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
+    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
+    #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
+#else
+    #define JSON_HEDLEY_PRAGMA(value)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
+    #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#endif
+#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
+    #undef JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+#if defined(__clang__)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
+    #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
+#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH
+    #define JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+
+/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
+   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#endif
+#if defined(__cplusplus)
+#  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
+#    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
+#      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
+#        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
+    _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#      else
+#        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#      endif
+#    else
+#      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#    endif
+#  endif
+#endif
+#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
+#endif
+
+#if defined(JSON_HEDLEY_CONST_CAST)
+    #undef JSON_HEDLEY_CONST_CAST
+#endif
+#if defined(__cplusplus)
+#  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
+#elif \
+  JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
+        JSON_HEDLEY_DIAGNOSTIC_PUSH \
+        JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
+        ((T) (expr)); \
+        JSON_HEDLEY_DIAGNOSTIC_POP \
+    }))
+#else
+#  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_REINTERPRET_CAST)
+    #undef JSON_HEDLEY_REINTERPRET_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
+#else
+    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_CAST)
+    #undef JSON_HEDLEY_STATIC_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
+#else
+    #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_CPP_CAST)
+    #undef JSON_HEDLEY_CPP_CAST
+#endif
+#if defined(__cplusplus)
+#  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
+#    define JSON_HEDLEY_CPP_CAST(T, expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
+    ((T) (expr)) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
+#    define JSON_HEDLEY_CPP_CAST(T, expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("diag_suppress=Pe137") \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  else
+#    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
+#  endif
+#else
+#  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#endif
+
+#if defined(JSON_HEDLEY_DEPRECATED)
+    #undef JSON_HEDLEY_DEPRECATED
+#endif
+#if defined(JSON_HEDLEY_DEPRECATED_FOR)
+    #undef JSON_HEDLEY_DEPRECATED_FOR
+#endif
+#if \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
+#elif \
+    (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
+#elif defined(__cplusplus) && (__cplusplus >= 201402L)
+    #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
+#else
+    #define JSON_HEDLEY_DEPRECATED(since)
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
+#endif
+
+#if defined(JSON_HEDLEY_UNAVAILABLE)
+    #undef JSON_HEDLEY_UNAVAILABLE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
+#else
+    #define JSON_HEDLEY_UNAVAILABLE(available_since)
+#endif
+
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
+    #undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#endif
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
+    #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
+#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+#elif defined(_Check_return_) /* SAL */
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
+#else
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
+#endif
+
+#if defined(JSON_HEDLEY_SENTINEL)
+    #undef JSON_HEDLEY_SENTINEL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
+#else
+    #define JSON_HEDLEY_SENTINEL(position)
+#endif
+
+#if defined(JSON_HEDLEY_NO_RETURN)
+    #undef JSON_HEDLEY_NO_RETURN
+#endif
+#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_NO_RETURN __noreturn
+#elif \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+    #define JSON_HEDLEY_NO_RETURN _Noreturn
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+    #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+    #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#else
+    #define JSON_HEDLEY_NO_RETURN
+#endif
+
+#if defined(JSON_HEDLEY_NO_ESCAPE)
+    #undef JSON_HEDLEY_NO_ESCAPE
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
+    #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
+#else
+    #define JSON_HEDLEY_NO_ESCAPE
+#endif
+
+#if defined(JSON_HEDLEY_UNREACHABLE)
+    #undef JSON_HEDLEY_UNREACHABLE
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
+    #undef JSON_HEDLEY_UNREACHABLE_RETURN
+#endif
+#if defined(JSON_HEDLEY_ASSUME)
+    #undef JSON_HEDLEY_ASSUME
+#endif
+#if \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
+#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
+    #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
+#elif \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
+    #if defined(__cplusplus)
+        #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
+    #else
+        #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
+    #endif
+#endif
+#if \
+    (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
+#elif defined(JSON_HEDLEY_ASSUME)
+    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
+#endif
+#if !defined(JSON_HEDLEY_ASSUME)
+    #if defined(JSON_HEDLEY_UNREACHABLE)
+        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
+    #else
+        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
+    #endif
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE)
+    #if  \
+        JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
+        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
+    #else
+        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
+    #endif
+#else
+    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
+#endif
+#if !defined(JSON_HEDLEY_UNREACHABLE)
+    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
+#endif
+
+JSON_HEDLEY_DIAGNOSTIC_PUSH
+#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
+    #pragma clang diagnostic ignored "-Wpedantic"
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
+    #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif
+#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
+    #if defined(__clang__)
+        #pragma clang diagnostic ignored "-Wvariadic-macros"
+    #elif defined(JSON_HEDLEY_GCC_VERSION)
+        #pragma GCC diagnostic ignored "-Wvariadic-macros"
+    #endif
+#endif
+#if defined(JSON_HEDLEY_NON_NULL)
+    #undef JSON_HEDLEY_NON_NULL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+    #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
+#else
+    #define JSON_HEDLEY_NON_NULL(...)
+#endif
+JSON_HEDLEY_DIAGNOSTIC_POP
+
+#if defined(JSON_HEDLEY_PRINTF_FORMAT)
+    #undef JSON_HEDLEY_PRINTF_FORMAT
+#endif
+#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
+#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
+#else
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
+#endif
+
+#if defined(JSON_HEDLEY_CONSTEXPR)
+    #undef JSON_HEDLEY_CONSTEXPR
+#endif
+#if defined(__cplusplus)
+    #if __cplusplus >= 201103L
+        #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
+    #endif
+#endif
+#if !defined(JSON_HEDLEY_CONSTEXPR)
+    #define JSON_HEDLEY_CONSTEXPR
+#endif
+
+#if defined(JSON_HEDLEY_PREDICT)
+    #undef JSON_HEDLEY_PREDICT
+#endif
+#if defined(JSON_HEDLEY_LIKELY)
+    #undef JSON_HEDLEY_LIKELY
+#endif
+#if defined(JSON_HEDLEY_UNLIKELY)
+    #undef JSON_HEDLEY_UNLIKELY
+#endif
+#if defined(JSON_HEDLEY_UNPREDICTABLE)
+    #undef JSON_HEDLEY_UNPREDICTABLE
+#endif
+#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
+    #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
+#endif
+#if \
+  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
+#  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
+#  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
+#elif \
+  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
+  JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
+  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
+  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+  JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
+  JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
+    (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
+    (__extension__ ({ \
+        double hedley_probability_ = (probability); \
+        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
+    }))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
+    (__extension__ ({ \
+        double hedley_probability_ = (probability); \
+        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
+    }))
+#  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
+#  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
+#else
+#  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
+#  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
+#  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
+#endif
+#if !defined(JSON_HEDLEY_UNPREDICTABLE)
+    #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
+#endif
+
+#if defined(JSON_HEDLEY_MALLOC)
+    #undef JSON_HEDLEY_MALLOC
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_MALLOC __declspec(restrict)
+#else
+    #define JSON_HEDLEY_MALLOC
+#endif
+
+#if defined(JSON_HEDLEY_PURE)
+    #undef JSON_HEDLEY_PURE
+#endif
+#if \
+  JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+  JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#  define JSON_HEDLEY_PURE __attribute__((__pure__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+#  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
+#elif defined(__cplusplus) && \
+    ( \
+      JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
+      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
+      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
+    )
+#  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
+#else
+#  define JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_CONST)
+    #undef JSON_HEDLEY_CONST
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_CONST __attribute__((__const__))
+#elif \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
+#else
+    #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_RESTRICT)
+    #undef JSON_HEDLEY_RESTRICT
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
+    #define JSON_HEDLEY_RESTRICT restrict
+#elif \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+    defined(__clang__) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_RESTRICT __restrict
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
+    #define JSON_HEDLEY_RESTRICT _Restrict
+#else
+    #define JSON_HEDLEY_RESTRICT
+#endif
+
+#if defined(JSON_HEDLEY_INLINE)
+    #undef JSON_HEDLEY_INLINE
+#endif
+#if \
+    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+    (defined(__cplusplus) && (__cplusplus >= 199711L))
+    #define JSON_HEDLEY_INLINE inline
+#elif \
+    defined(JSON_HEDLEY_GCC_VERSION) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
+    #define JSON_HEDLEY_INLINE __inline__
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_INLINE __inline
+#else
+    #define JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_ALWAYS_INLINE)
+    #undef JSON_HEDLEY_ALWAYS_INLINE
+#endif
+#if \
+  JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+  JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+#  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
+#elif \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+#  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
+#elif defined(__cplusplus) && \
+    ( \
+      JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+      JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+      JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+      JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
+    )
+#  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+#  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
+#else
+#  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_NEVER_INLINE)
+    #undef JSON_HEDLEY_NEVER_INLINE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+    #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+    #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#else
+    #define JSON_HEDLEY_NEVER_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_PRIVATE)
+    #undef JSON_HEDLEY_PRIVATE
+#endif
+#if defined(JSON_HEDLEY_PUBLIC)
+    #undef JSON_HEDLEY_PUBLIC
+#endif
+#if defined(JSON_HEDLEY_IMPORT)
+    #undef JSON_HEDLEY_IMPORT
+#endif
+#if defined(_WIN32) || defined(__CYGWIN__)
+#  define JSON_HEDLEY_PRIVATE
+#  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
+#  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
+#else
+#  if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+    ( \
+      defined(__TI_EABI__) && \
+      ( \
+        (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
+      ) \
+    ) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
+#    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
+#  else
+#    define JSON_HEDLEY_PRIVATE
+#    define JSON_HEDLEY_PUBLIC
+#  endif
+#  define JSON_HEDLEY_IMPORT    extern
+#endif
+
+#if defined(JSON_HEDLEY_NO_THROW)
+    #undef JSON_HEDLEY_NO_THROW
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+    #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
+#else
+    #define JSON_HEDLEY_NO_THROW
+#endif
+
+#if defined(JSON_HEDLEY_FALL_THROUGH)
+    #undef JSON_HEDLEY_FALL_THROUGH
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
+    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
+    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
+#elif defined(__fallthrough) /* SAL */
+    #define JSON_HEDLEY_FALL_THROUGH __fallthrough
+#else
+    #define JSON_HEDLEY_FALL_THROUGH
+#endif
+
+#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
+    #undef JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
+#elif defined(_Ret_notnull_) /* SAL */
+    #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
+#else
+    #define JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+
+#if defined(JSON_HEDLEY_ARRAY_PARAM)
+    #undef JSON_HEDLEY_ARRAY_PARAM
+#endif
+#if \
+    defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+    !defined(__STDC_NO_VLA__) && \
+    !defined(__cplusplus) && \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_TINYC_VERSION)
+    #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
+#else
+    #define JSON_HEDLEY_ARRAY_PARAM(name)
+#endif
+
+#if defined(JSON_HEDLEY_IS_CONSTANT)
+    #undef JSON_HEDLEY_IS_CONSTANT
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
+    #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#endif
+/* JSON_HEDLEY_IS_CONSTEXPR_ is for
+   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+    #undef JSON_HEDLEY_IS_CONSTEXPR_
+#endif
+#if \
+    JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
+#endif
+#if !defined(__cplusplus)
+#  if \
+       JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
+       JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+       JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+       JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+       JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+       JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
+#if defined(__INTPTR_TYPE__)
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
+#else
+    #include <stdint.h>
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
+#endif
+#  elif \
+       ( \
+          defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
+          !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
+          !defined(JSON_HEDLEY_PGI_VERSION) && \
+          !defined(JSON_HEDLEY_IAR_VERSION)) || \
+       (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
+       JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+       JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
+       JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+       JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
+#if defined(__INTPTR_TYPE__)
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
+#else
+    #include <stdint.h>
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
+#endif
+#  elif \
+       defined(JSON_HEDLEY_GCC_VERSION) || \
+       defined(JSON_HEDLEY_INTEL_VERSION) || \
+       defined(JSON_HEDLEY_TINYC_VERSION) || \
+       defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
+       JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
+       defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
+       defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
+       defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
+       defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
+       defined(__clang__)
+#    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
+        sizeof(void) != \
+        sizeof(*( \
+                  1 ? \
+                  ((void*) ((expr) * 0L) ) : \
+((struct { char v[sizeof(void) * 2]; } *) 1) \
+                ) \
+              ) \
+                                            )
+#  endif
+#endif
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+    #if !defined(JSON_HEDLEY_IS_CONSTANT)
+        #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
+    #endif
+    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
+#else
+    #if !defined(JSON_HEDLEY_IS_CONSTANT)
+        #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
+    #endif
+    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
+    #undef JSON_HEDLEY_BEGIN_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_END_C_DECLS)
+    #undef JSON_HEDLEY_END_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_C_DECL)
+    #undef JSON_HEDLEY_C_DECL
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
+    #define JSON_HEDLEY_END_C_DECLS }
+    #define JSON_HEDLEY_C_DECL extern "C"
+#else
+    #define JSON_HEDLEY_BEGIN_C_DECLS
+    #define JSON_HEDLEY_END_C_DECLS
+    #define JSON_HEDLEY_C_DECL
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_ASSERT)
+    #undef JSON_HEDLEY_STATIC_ASSERT
+#endif
+#if \
+  !defined(__cplusplus) && ( \
+      (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
+      (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
+      JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
+      JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+      defined(_Static_assert) \
+    )
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
+#elif \
+  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
+  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
+#else
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
+#endif
+
+#if defined(JSON_HEDLEY_NULL)
+    #undef JSON_HEDLEY_NULL
+#endif
+#if defined(__cplusplus)
+    #if __cplusplus >= 201103L
+        #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
+    #elif defined(NULL)
+        #define JSON_HEDLEY_NULL NULL
+    #else
+        #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
+    #endif
+#elif defined(NULL)
+    #define JSON_HEDLEY_NULL NULL
+#else
+    #define JSON_HEDLEY_NULL ((void*) 0)
+#endif
+
+#if defined(JSON_HEDLEY_MESSAGE)
+    #undef JSON_HEDLEY_MESSAGE
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+#  define JSON_HEDLEY_MESSAGE(msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+    JSON_HEDLEY_PRAGMA(message msg) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
+#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+#  define JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_WARNING)
+    #undef JSON_HEDLEY_WARNING
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+#  define JSON_HEDLEY_WARNING(msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+    JSON_HEDLEY_PRAGMA(clang warning msg) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
+  JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
+#elif \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
+  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_REQUIRE)
+    #undef JSON_HEDLEY_REQUIRE
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_MSG)
+    #undef JSON_HEDLEY_REQUIRE_MSG
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
+#  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
+#    define JSON_HEDLEY_REQUIRE(expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+    __attribute__((diagnose_if(!(expr), #expr, "error"))) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+    __attribute__((diagnose_if(!(expr), msg, "error"))) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  else
+#    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
+#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
+#  endif
+#else
+#  define JSON_HEDLEY_REQUIRE(expr)
+#  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS)
+    #undef JSON_HEDLEY_FLAGS
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
+    #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
+#else
+    #define JSON_HEDLEY_FLAGS
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS_CAST)
+    #undef JSON_HEDLEY_FLAGS_CAST
+#endif
+#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
+#  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
+        JSON_HEDLEY_DIAGNOSTIC_PUSH \
+        _Pragma("warning(disable:188)") \
+        ((T) (expr)); \
+        JSON_HEDLEY_DIAGNOSTIC_POP \
+    }))
+#else
+#  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
+#endif
+
+#if defined(JSON_HEDLEY_EMPTY_BASES)
+    #undef JSON_HEDLEY_EMPTY_BASES
+#endif
+#if \
+    (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
+#else
+    #define JSON_HEDLEY_EMPTY_BASES
+#endif
+
+/* Remaining macros are deprecated. */
+
+#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
+    #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#endif
+#if defined(__clang__)
+    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
+#else
+    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
+    #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#endif
+#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
+    #undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
+    #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#endif
+#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
+    #undef JSON_HEDLEY_CLANG_HAS_WARNING
+#endif
+#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
+
+#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
+
+
+// This file contains all internal macro definitions (except those affecting ABI)
+// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+// exclude unsupported compilers
+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
+    #if defined(__clang__)
+        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+        #endif
+    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
+            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+        #endif
+    #endif
+#endif
+
+// C++ language standard detection
+// if the user manually specified the used c++ version this is skipped
+#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
+    #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
+        #define JSON_HAS_CPP_20
+        #define JSON_HAS_CPP_17
+        #define JSON_HAS_CPP_14
+    #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+        #define JSON_HAS_CPP_17
+        #define JSON_HAS_CPP_14
+    #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+        #define JSON_HAS_CPP_14
+    #endif
+    // the cpp 11 flag is always specified because it is the minimal required version
+    #define JSON_HAS_CPP_11
+#endif
+
+#ifdef __has_include
+    #if __has_include(<version>)
+        #include <version>
+    #endif
+#endif
+
+#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
+    #ifdef JSON_HAS_CPP_17
+        #if defined(__cpp_lib_filesystem)
+            #define JSON_HAS_FILESYSTEM 1
+        #elif defined(__cpp_lib_experimental_filesystem)
+            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
+        #elif !defined(__has_include)
+            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
+        #elif __has_include(<filesystem>)
+            #define JSON_HAS_FILESYSTEM 1
+        #elif __has_include(<experimental/filesystem>)
+            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
+        #endif
+
+        // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
+        #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
+            #undef JSON_HAS_FILESYSTEM
+            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+        #endif
+
+        // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
+        #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
+            #undef JSON_HAS_FILESYSTEM
+            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+        #endif
+
+        // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
+        #if defined(__clang_major__) && __clang_major__ < 7
+            #undef JSON_HAS_FILESYSTEM
+            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+        #endif
+
+        // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
+        #if defined(_MSC_VER) && _MSC_VER < 1914
+            #undef JSON_HAS_FILESYSTEM
+            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+        #endif
+
+        // no filesystem support before iOS 13
+        #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
+            #undef JSON_HAS_FILESYSTEM
+            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+        #endif
+
+        // no filesystem support before macOS Catalina
+        #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
+            #undef JSON_HAS_FILESYSTEM
+            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+        #endif
+    #endif
+#endif
+
+#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+    #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
+#endif
+
+#ifndef JSON_HAS_FILESYSTEM
+    #define JSON_HAS_FILESYSTEM 0
+#endif
+
+#ifndef JSON_HAS_THREE_WAY_COMPARISON
+    #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
+        && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
+        #define JSON_HAS_THREE_WAY_COMPARISON 1
+    #else
+        #define JSON_HAS_THREE_WAY_COMPARISON 0
+    #endif
+#endif
+
+#ifndef JSON_HAS_RANGES
+    // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
+    #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
+        #define JSON_HAS_RANGES 0
+    #elif defined(__cpp_lib_ranges)
+        #define JSON_HAS_RANGES 1
+    #else
+        #define JSON_HAS_RANGES 0
+    #endif
+#endif
+
+#ifdef JSON_HAS_CPP_17
+    #define JSON_INLINE_VARIABLE inline
+#else
+    #define JSON_INLINE_VARIABLE
+#endif
+
+#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
+    #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+    #define JSON_NO_UNIQUE_ADDRESS
+#endif
+
+// disable documentation warnings on clang
+#if defined(__clang__)
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wdocumentation"
+    #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
+#endif
+
+// allow disabling exceptions
+#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
+    #define JSON_THROW(exception) throw exception
+    #define JSON_TRY try
+    #define JSON_CATCH(exception) catch(exception)
+    #define JSON_INTERNAL_CATCH(exception) catch(exception)
+#else
+    #include <cstdlib>
+    #define JSON_THROW(exception) std::abort()
+    #define JSON_TRY if(true)
+    #define JSON_CATCH(exception) if(false)
+    #define JSON_INTERNAL_CATCH(exception) if(false)
+#endif
+
+// override exception macros
+#if defined(JSON_THROW_USER)
+    #undef JSON_THROW
+    #define JSON_THROW JSON_THROW_USER
+#endif
+#if defined(JSON_TRY_USER)
+    #undef JSON_TRY
+    #define JSON_TRY JSON_TRY_USER
+#endif
+#if defined(JSON_CATCH_USER)
+    #undef JSON_CATCH
+    #define JSON_CATCH JSON_CATCH_USER
+    #undef JSON_INTERNAL_CATCH
+    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
+#endif
+#if defined(JSON_INTERNAL_CATCH_USER)
+    #undef JSON_INTERNAL_CATCH
+    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
+#endif
+
+// allow overriding assert
+#if !defined(JSON_ASSERT)
+    #include <cassert> // assert
+    #define JSON_ASSERT(x) assert(x)
+#endif
+
+// allow to access some private functions (needed by the test suite)
+#if defined(JSON_TESTS_PRIVATE)
+    #define JSON_PRIVATE_UNLESS_TESTED public
+#else
+    #define JSON_PRIVATE_UNLESS_TESTED private
+#endif
+
+/*!
+@brief macro to briefly define a mapping between an enum and JSON
+@def NLOHMANN_JSON_SERIALIZE_ENUM
+@since version 3.4.0
+*/
+#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
+    template<typename BasicJsonType>                                                            \
+    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
+    {                                                                                           \
+        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
+        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
+        auto it = std::find_if(std::begin(m), std::end(m),                                      \
+                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
+        {                                                                                       \
+            return ej_pair.first == e;                                                          \
+        });                                                                                     \
+        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
+    }                                                                                           \
+    template<typename BasicJsonType>                                                            \
+    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
+    {                                                                                           \
+        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
+        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
+        auto it = std::find_if(std::begin(m), std::end(m),                                      \
+                               [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
+        {                                                                                       \
+            return ej_pair.second == j;                                                         \
+        });                                                                                     \
+        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
+    }
+
+// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
+// may be removed in the future once the class is split.
+
+#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
+    template<template<typename, typename, typename...> class ObjectType,   \
+             template<typename, typename...> class ArrayType,              \
+             class StringType, class BooleanType, class NumberIntegerType, \
+             class NumberUnsignedType, class NumberFloatType,              \
+             template<typename> class AllocatorType,                       \
+             template<typename, typename = void> class JSONSerializer,     \
+             class BinaryType>
+
+#define NLOHMANN_BASIC_JSON_TPL                                            \
+    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
+    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
+    AllocatorType, JSONSerializer, BinaryType>
+
+// Macros to simplify conversion from/to types
+
+#define NLOHMANN_JSON_EXPAND( x ) x
+#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
+#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
+        NLOHMANN_JSON_PASTE64, \
+        NLOHMANN_JSON_PASTE63, \
+        NLOHMANN_JSON_PASTE62, \
+        NLOHMANN_JSON_PASTE61, \
+        NLOHMANN_JSON_PASTE60, \
+        NLOHMANN_JSON_PASTE59, \
+        NLOHMANN_JSON_PASTE58, \
+        NLOHMANN_JSON_PASTE57, \
+        NLOHMANN_JSON_PASTE56, \
+        NLOHMANN_JSON_PASTE55, \
+        NLOHMANN_JSON_PASTE54, \
+        NLOHMANN_JSON_PASTE53, \
+        NLOHMANN_JSON_PASTE52, \
+        NLOHMANN_JSON_PASTE51, \
+        NLOHMANN_JSON_PASTE50, \
+        NLOHMANN_JSON_PASTE49, \
+        NLOHMANN_JSON_PASTE48, \
+        NLOHMANN_JSON_PASTE47, \
+        NLOHMANN_JSON_PASTE46, \
+        NLOHMANN_JSON_PASTE45, \
+        NLOHMANN_JSON_PASTE44, \
+        NLOHMANN_JSON_PASTE43, \
+        NLOHMANN_JSON_PASTE42, \
+        NLOHMANN_JSON_PASTE41, \
+        NLOHMANN_JSON_PASTE40, \
+        NLOHMANN_JSON_PASTE39, \
+        NLOHMANN_JSON_PASTE38, \
+        NLOHMANN_JSON_PASTE37, \
+        NLOHMANN_JSON_PASTE36, \
+        NLOHMANN_JSON_PASTE35, \
+        NLOHMANN_JSON_PASTE34, \
+        NLOHMANN_JSON_PASTE33, \
+        NLOHMANN_JSON_PASTE32, \
+        NLOHMANN_JSON_PASTE31, \
+        NLOHMANN_JSON_PASTE30, \
+        NLOHMANN_JSON_PASTE29, \
+        NLOHMANN_JSON_PASTE28, \
+        NLOHMANN_JSON_PASTE27, \
+        NLOHMANN_JSON_PASTE26, \
+        NLOHMANN_JSON_PASTE25, \
+        NLOHMANN_JSON_PASTE24, \
+        NLOHMANN_JSON_PASTE23, \
+        NLOHMANN_JSON_PASTE22, \
+        NLOHMANN_JSON_PASTE21, \
+        NLOHMANN_JSON_PASTE20, \
+        NLOHMANN_JSON_PASTE19, \
+        NLOHMANN_JSON_PASTE18, \
+        NLOHMANN_JSON_PASTE17, \
+        NLOHMANN_JSON_PASTE16, \
+        NLOHMANN_JSON_PASTE15, \
+        NLOHMANN_JSON_PASTE14, \
+        NLOHMANN_JSON_PASTE13, \
+        NLOHMANN_JSON_PASTE12, \
+        NLOHMANN_JSON_PASTE11, \
+        NLOHMANN_JSON_PASTE10, \
+        NLOHMANN_JSON_PASTE9, \
+        NLOHMANN_JSON_PASTE8, \
+        NLOHMANN_JSON_PASTE7, \
+        NLOHMANN_JSON_PASTE6, \
+        NLOHMANN_JSON_PASTE5, \
+        NLOHMANN_JSON_PASTE4, \
+        NLOHMANN_JSON_PASTE3, \
+        NLOHMANN_JSON_PASTE2, \
+        NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
+#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
+#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
+#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
+#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
+#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
+#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
+#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
+#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
+#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
+#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
+#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
+#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
+#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
+#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
+#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
+#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
+#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
+#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
+#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
+#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
+#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
+#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
+#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
+#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
+#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
+#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
+#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
+#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
+#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
+#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
+#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
+#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
+#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
+#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
+#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
+#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
+#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
+#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
+#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
+#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
+#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
+#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
+#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
+#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
+#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
+#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
+#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
+#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
+#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
+#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
+#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
+#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
+#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
+#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
+#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
+#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
+#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
+#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
+#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
+#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
+#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
+#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
+#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
+
+#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
+#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
+#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
+
+/*!
+@brief macro
+@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
+@since version 3.9.0
+*/
+#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
+    friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+    friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
+
+#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
+    friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+    friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
+
+/*!
+@brief macro
+@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
+@since version 3.9.0
+*/
+#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
+    inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+    inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
+
+#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
+    inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+    inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
+
+
+// inspired from https://stackoverflow.com/a/26745591
+// allows to call any std function as if (e.g. with begin):
+// using std::begin; begin(x);
+//
+// it allows using the detected idiom to retrieve the return type
+// of such an expression
+#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \
+    namespace detail {                                                            \
+    using std::std_name;                                                          \
+    \
+    template<typename... T>                                                       \
+    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
+    }                                                                             \
+    \
+    namespace detail2 {                                                           \
+    struct std_name##_tag                                                         \
+    {                                                                             \
+    };                                                                            \
+    \
+    template<typename... T>                                                       \
+    std_name##_tag std_name(T&&...);                                              \
+    \
+    template<typename... T>                                                       \
+    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
+    \
+    template<typename... T>                                                       \
+    struct would_call_std_##std_name                                              \
+    {                                                                             \
+        static constexpr auto const value = ::nlohmann::detail::                  \
+                                            is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
+    };                                                                            \
+    } /* namespace detail2 */ \
+    \
+    template<typename... T>                                                       \
+    struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \
+    {                                                                             \
+    }
+
+#ifndef JSON_USE_IMPLICIT_CONVERSIONS
+    #define JSON_USE_IMPLICIT_CONVERSIONS 1
+#endif
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+    #define JSON_EXPLICIT
+#else
+    #define JSON_EXPLICIT explicit
+#endif
+
+#ifndef JSON_DISABLE_ENUM_SERIALIZATION
+    #define JSON_DISABLE_ENUM_SERIALIZATION 0
+#endif
+
+#ifndef JSON_USE_GLOBAL_UDLS
+    #define JSON_USE_GLOBAL_UDLS 1
+#endif
+
+#if JSON_HAS_THREE_WAY_COMPARISON
+    #include <compare> // partial_ordering
+#endif
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+///////////////////////////
+// JSON type enumeration //
+///////////////////////////
+
+/*!
+@brief the JSON type enumeration
+
+This enumeration collects the different JSON types. It is internally used to
+distinguish the stored values, and the functions @ref basic_json::is_null(),
+@ref basic_json::is_object(), @ref basic_json::is_array(),
+@ref basic_json::is_string(), @ref basic_json::is_boolean(),
+@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
+@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
+@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
+@ref basic_json::is_structured() rely on it.
+
+@note There are three enumeration entries (number_integer, number_unsigned, and
+number_float), because the library distinguishes these three types for numbers:
+@ref basic_json::number_unsigned_t is used for unsigned integers,
+@ref basic_json::number_integer_t is used for signed integers, and
+@ref basic_json::number_float_t is used for floating-point numbers or to
+approximate integers which do not fit in the limits of their respective type.
+
+@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
+value with the default value for a given type
+
+@since version 1.0.0
+*/
+enum class value_t : std::uint8_t
+{
+    null,             ///< null value
+    object,           ///< object (unordered set of name/value pairs)
+    array,            ///< array (ordered collection of values)
+    string,           ///< string value
+    boolean,          ///< boolean value
+    number_integer,   ///< number value (signed integer)
+    number_unsigned,  ///< number value (unsigned integer)
+    number_float,     ///< number value (floating-point)
+    binary,           ///< binary array (ordered collection of bytes)
+    discarded         ///< discarded by the parser callback function
+};
+
+/*!
+@brief comparison operator for JSON types
+
+Returns an ordering that is similar to Python:
+- order: null < boolean < number < object < array < string < binary
+- furthermore, each type is not smaller than itself
+- discarded values are not comparable
+- binary is represented as a b"" string in python and directly comparable to a
+  string; however, making a binary array directly comparable with a string would
+  be surprising behavior in a JSON file.
+
+@since version 1.0.0
+*/
+#if JSON_HAS_THREE_WAY_COMPARISON
+    inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
+#else
+    inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+#endif
+{
+    static constexpr std::array<std::uint8_t, 9> order = {{
+            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
+            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
+            6 /* binary */
+        }
+    };
+
+    const auto l_index = static_cast<std::size_t>(lhs);
+    const auto r_index = static_cast<std::size_t>(rhs);
+#if JSON_HAS_THREE_WAY_COMPARISON
+    if (l_index < order.size() && r_index < order.size())
+    {
+        return order[l_index] <=> order[r_index]; // *NOPAD*
+    }
+    return std::partial_ordering::unordered;
+#else
+    return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
+#endif
+}
+
+// GCC selects the built-in operator< over an operator rewritten from
+// a user-defined spaceship operator
+// Clang, MSVC, and ICC select the rewritten candidate
+// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
+#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
+inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+{
+    return std::is_lt(lhs <=> rhs); // *NOPAD*
+}
+#endif
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/string_escape.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/*!
+@brief replace all occurrences of a substring by another string
+
+@param[in,out] s  the string to manipulate; changed so that all
+               occurrences of @a f are replaced with @a t
+@param[in]     f  the substring to replace with @a t
+@param[in]     t  the string to replace @a f
+
+@pre The search string @a f must not be empty. **This precondition is
+enforced with an assertion.**
+
+@since version 2.0.0
+*/
+template<typename StringType>
+inline void replace_substring(StringType& s, const StringType& f,
+                              const StringType& t)
+{
+    JSON_ASSERT(!f.empty());
+    for (auto pos = s.find(f);                // find first occurrence of f
+            pos != StringType::npos;          // make sure f was found
+            s.replace(pos, f.size(), t),      // replace with t, and
+            pos = s.find(f, pos + t.size()))  // find next occurrence of f
+    {}
+}
+
+/*!
+ * @brief string escaping as described in RFC 6901 (Sect. 4)
+ * @param[in] s string to escape
+ * @return    escaped string
+ *
+ * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
+ */
+template<typename StringType>
+inline StringType escape(StringType s)
+{
+    replace_substring(s, StringType{"~"}, StringType{"~0"});
+    replace_substring(s, StringType{"/"}, StringType{"~1"});
+    return s;
+}
+
+/*!
+ * @brief string unescaping as described in RFC 6901 (Sect. 4)
+ * @param[in] s string to unescape
+ * @return    unescaped string
+ *
+ * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
+ */
+template<typename StringType>
+static void unescape(StringType& s)
+{
+    replace_substring(s, StringType{"~1"}, StringType{"/"});
+    replace_substring(s, StringType{"~0"}, StringType{"~"});
+}
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/input/position_t.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstddef> // size_t
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/// struct to capture the start position of the current token
+struct position_t
+{
+    /// the total number of characters read
+    std::size_t chars_read_total = 0;
+    /// the number of characters read in the current line
+    std::size_t chars_read_current_line = 0;
+    /// the number of lines read
+    std::size_t lines_read = 0;
+
+    /// conversion to size_t to preserve SAX interface
+    constexpr operator size_t() const
+    {
+        return chars_read_total;
+    }
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-FileCopyrightText: 2018 The Abseil Authors
+// SPDX-License-Identifier: MIT
+
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
+#include <utility> // index_sequence, make_index_sequence, index_sequence_for
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename T>
+using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+#ifdef JSON_HAS_CPP_14
+
+// the following utilities are natively available in C++14
+using std::enable_if_t;
+using std::index_sequence;
+using std::make_index_sequence;
+using std::index_sequence_for;
+
+#else
+
+// alias templates to reduce boilerplate
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
+// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
+
+//// START OF CODE FROM GOOGLE ABSEIL
+
+// integer_sequence
+//
+// Class template representing a compile-time integer sequence. An instantiation
+// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
+// type through its template arguments (which is a common need when
+// working with C++11 variadic templates). `absl::integer_sequence` is designed
+// to be a drop-in replacement for C++14's `std::integer_sequence`.
+//
+// Example:
+//
+//   template< class T, T... Ints >
+//   void user_function(integer_sequence<T, Ints...>);
+//
+//   int main()
+//   {
+//     // user_function's `T` will be deduced to `int` and `Ints...`
+//     // will be deduced to `0, 1, 2, 3, 4`.
+//     user_function(make_integer_sequence<int, 5>());
+//   }
+template <typename T, T... Ints>
+struct integer_sequence
+{
+    using value_type = T;
+    static constexpr std::size_t size() noexcept
+    {
+        return sizeof...(Ints);
+    }
+};
+
+// index_sequence
+//
+// A helper template for an `integer_sequence` of `size_t`,
+// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
+// `std::index_sequence`.
+template <size_t... Ints>
+using index_sequence = integer_sequence<size_t, Ints...>;
+
+namespace utility_internal
+{
+
+template <typename Seq, size_t SeqSize, size_t Rem>
+struct Extend;
+
+// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
+{
+    using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
+};
+
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
+{
+    using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
+};
+
+// Recursion helper for 'make_integer_sequence<T, N>'.
+// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
+template <typename T, size_t N>
+struct Gen
+{
+    using type =
+        typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
+};
+
+template <typename T>
+struct Gen<T, 0>
+{
+    using type = integer_sequence<T>;
+};
+
+}  // namespace utility_internal
+
+// Compile-time sequences of integers
+
+// make_integer_sequence
+//
+// This template alias is equivalent to
+// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
+// replacement for C++14's `std::make_integer_sequence`.
+template <typename T, T N>
+using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
+
+// make_index_sequence
+//
+// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
+// and is designed to be a drop-in replacement for C++14's
+// `std::make_index_sequence`.
+template <size_t N>
+using make_index_sequence = make_integer_sequence<size_t, N>;
+
+// index_sequence_for
+//
+// Converts a typename pack into an index sequence of the same length, and
+// is designed to be a drop-in replacement for C++14's
+// `std::index_sequence_for()`
+template <typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+//// END OF CODE FROM GOOGLE ABSEIL
+
+#endif
+
+// dispatch utility (taken from ranges-v3)
+template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
+template<> struct priority_tag<0> {};
+
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+    static JSON_INLINE_VARIABLE constexpr T value{};
+};
+
+#ifndef JSON_HAS_CPP_17
+    template<typename T>
+    constexpr T static_const<T>::value;
+#endif
+
+template<typename T, typename... Args>
+inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
+{
+    return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
+}
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <limits> // numeric_limits
+#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
+#include <utility> // declval
+#include <tuple> // tuple
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <iterator> // random_access_iterator_tag
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename It, typename = void>
+struct iterator_types {};
+
+template<typename It>
+struct iterator_types <
+    It,
+    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
+    typename It::reference, typename It::iterator_category >>
+{
+    using difference_type = typename It::difference_type;
+    using value_type = typename It::value_type;
+    using pointer = typename It::pointer;
+    using reference = typename It::reference;
+    using iterator_category = typename It::iterator_category;
+};
+
+// This is required as some compilers implement std::iterator_traits in a way that
+// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
+template<typename T, typename = void>
+struct iterator_traits
+{
+};
+
+template<typename T>
+struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
+            : iterator_types<T>
+{
+};
+
+template<typename T>
+struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
+{
+    using iterator_category = std::random_access_iterator_tag;
+    using value_type = T;
+    using difference_type = ptrdiff_t;
+    using pointer = T*;
+    using reference = T&;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/call_std/begin.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/call_std/end.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
+    #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+    #include <cstdint> // int64_t, uint64_t
+    #include <map> // map
+    #include <memory> // allocator
+    #include <string> // string
+    #include <vector> // vector
+
+    // #include <nlohmann/detail/abi_macros.hpp>
+
+
+    /*!
+    @brief namespace for Niels Lohmann
+    @see https://github.com/nlohmann
+    @since version 1.0.0
+    */
+    NLOHMANN_JSON_NAMESPACE_BEGIN
+
+    /*!
+    @brief default JSONSerializer template argument
+
+    This serializer ignores the template arguments and uses ADL
+    ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
+    for serialization.
+    */
+    template<typename T = void, typename SFINAE = void>
+    struct adl_serializer;
+
+    /// a class to store JSON values
+    /// @sa https://json.nlohmann.me/api/basic_json/
+    template<template<typename U, typename V, typename... Args> class ObjectType =
+    std::map,
+    template<typename U, typename... Args> class ArrayType = std::vector,
+    class StringType = std::string, class BooleanType = bool,
+    class NumberIntegerType = std::int64_t,
+    class NumberUnsignedType = std::uint64_t,
+    class NumberFloatType = double,
+    template<typename U> class AllocatorType = std::allocator,
+    template<typename T, typename SFINAE = void> class JSONSerializer =
+    adl_serializer,
+    class BinaryType = std::vector<std::uint8_t>>
+    class basic_json;
+
+    /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
+    /// @sa https://json.nlohmann.me/api/json_pointer/
+    template<typename RefStringType>
+    class json_pointer;
+
+    /*!
+    @brief default specialization
+    @sa https://json.nlohmann.me/api/json/
+    */
+    using json = basic_json<>;
+
+    /// @brief a minimal map-like container that preserves insertion order
+    /// @sa https://json.nlohmann.me/api/ordered_map/
+    template<class Key, class T, class IgnoredLess, class Allocator>
+    struct ordered_map;
+
+    /// @brief specialization that maintains the insertion order of object keys
+    /// @sa https://json.nlohmann.me/api/ordered_json/
+    using ordered_json = basic_json<nlohmann::ordered_map>;
+
+    NLOHMANN_JSON_NAMESPACE_END
+
+#endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+/*!
+@brief detail namespace with internal helper functions
+
+This namespace collects functions that should not be exposed,
+implementations of some @ref basic_json methods, and meta-programming helpers.
+
+@since version 2.1.0
+*/
+namespace detail
+{
+
+/////////////
+// helpers //
+/////////////
+
+// Note to maintainers:
+//
+// Every trait in this file expects a non CV-qualified type.
+// The only exceptions are in the 'aliases for detected' section
+// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
+//
+// In this case, T has to be properly CV-qualified to constraint the function arguments
+// (e.g. to_json(BasicJsonType&, const T&))
+
+template<typename> struct is_basic_json : std::false_type {};
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+
+// used by exceptions create() member functions
+// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
+// false_type otherwise
+template<typename BasicJsonContext>
+struct is_basic_json_context :
+    std::integral_constant < bool,
+    is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
+    || std::is_same<BasicJsonContext, std::nullptr_t>::value >
+{};
+
+//////////////////////
+// json_ref helpers //
+//////////////////////
+
+template<typename>
+class json_ref;
+
+template<typename>
+struct is_json_ref : std::false_type {};
+
+template<typename T>
+struct is_json_ref<json_ref<T>> : std::true_type {};
+
+//////////////////////////
+// aliases for detected //
+//////////////////////////
+
+template<typename T>
+using mapped_type_t = typename T::mapped_type;
+
+template<typename T>
+using key_type_t = typename T::key_type;
+
+template<typename T>
+using value_type_t = typename T::value_type;
+
+template<typename T>
+using difference_type_t = typename T::difference_type;
+
+template<typename T>
+using pointer_t = typename T::pointer;
+
+template<typename T>
+using reference_t = typename T::reference;
+
+template<typename T>
+using iterator_category_t = typename T::iterator_category;
+
+template<typename T, typename... Args>
+using to_json_function = decltype(T::to_json(std::declval<Args>()...));
+
+template<typename T, typename... Args>
+using from_json_function = decltype(T::from_json(std::declval<Args>()...));
+
+template<typename T, typename U>
+using get_template_function = decltype(std::declval<T>().template get<U>());
+
+// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
+template<typename BasicJsonType, typename T, typename = void>
+struct has_from_json : std::false_type {};
+
+// trait checking if j.get<T> is valid
+// use this trait instead of std::is_constructible or std::is_convertible,
+// both rely on, or make use of implicit conversions, and thus fail when T
+// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
+template <typename BasicJsonType, typename T>
+struct is_getable
+{
+    static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
+};
+
+template<typename BasicJsonType, typename T>
+struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<void, from_json_function, serializer,
+        const BasicJsonType&, T&>::value;
+};
+
+// This trait checks if JSONSerializer<T>::from_json(json const&) exists
+// this overload is used for non-default-constructible user-defined-types
+template<typename BasicJsonType, typename T, typename = void>
+struct has_non_default_from_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<T, from_json_function, serializer,
+        const BasicJsonType&>::value;
+};
+
+// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
+// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
+template<typename BasicJsonType, typename T, typename = void>
+struct has_to_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
+        T>::value;
+};
+
+template<typename T>
+using detect_key_compare = typename T::key_compare;
+
+template<typename T>
+struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
+
+// obtains the actual object key comparator
+template<typename BasicJsonType>
+struct actual_object_comparator
+{
+    using object_t = typename BasicJsonType::object_t;
+    using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
+    using type = typename std::conditional < has_key_compare<object_t>::value,
+          typename object_t::key_compare, object_comparator_t>::type;
+};
+
+template<typename BasicJsonType>
+using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
+
+///////////////////
+// is_ functions //
+///////////////////
+
+// https://en.cppreference.com/w/cpp/types/conjunction
+template<class...> struct conjunction : std::true_type { };
+template<class B> struct conjunction<B> : B { };
+template<class B, class... Bn>
+struct conjunction<B, Bn...>
+: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
+
+// https://en.cppreference.com/w/cpp/types/negation
+template<class B> struct negation : std::integral_constant < bool, !B::value > { };
+
+// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
+// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
+// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
+template <typename T>
+struct is_default_constructible : std::is_default_constructible<T> {};
+
+template <typename T1, typename T2>
+struct is_default_constructible<std::pair<T1, T2>>
+            : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
+
+template <typename T1, typename T2>
+struct is_default_constructible<const std::pair<T1, T2>>
+            : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
+
+template <typename... Ts>
+struct is_default_constructible<std::tuple<Ts...>>
+            : conjunction<is_default_constructible<Ts>...> {};
+
+template <typename... Ts>
+struct is_default_constructible<const std::tuple<Ts...>>
+            : conjunction<is_default_constructible<Ts>...> {};
+
+
+template <typename T, typename... Args>
+struct is_constructible : std::is_constructible<T, Args...> {};
+
+template <typename T1, typename T2>
+struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
+
+template <typename T1, typename T2>
+struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
+
+template <typename... Ts>
+struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
+
+template <typename... Ts>
+struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
+
+
+template<typename T, typename = void>
+struct is_iterator_traits : std::false_type {};
+
+template<typename T>
+struct is_iterator_traits<iterator_traits<T>>
+{
+  private:
+    using traits = iterator_traits<T>;
+
+  public:
+    static constexpr auto value =
+        is_detected<value_type_t, traits>::value &&
+        is_detected<difference_type_t, traits>::value &&
+        is_detected<pointer_t, traits>::value &&
+        is_detected<iterator_category_t, traits>::value &&
+        is_detected<reference_t, traits>::value;
+};
+
+template<typename T>
+struct is_range
+{
+  private:
+    using t_ref = typename std::add_lvalue_reference<T>::type;
+
+    using iterator = detected_t<result_of_begin, t_ref>;
+    using sentinel = detected_t<result_of_end, t_ref>;
+
+    // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
+    // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
+    // but reimplementing these would be too much work, as a lot of other concepts are used underneath
+    static constexpr auto is_iterator_begin =
+        is_iterator_traits<iterator_traits<iterator>>::value;
+
+  public:
+    static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
+};
+
+template<typename R>
+using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
+
+template<typename T>
+using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
+
+// The following implementation of is_complete_type is taken from
+// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
+// and is written by Xiang Fan who agreed to using it in this library.
+
+template<typename T, typename = void>
+struct is_complete_type : std::false_type {};
+
+template<typename T>
+struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
+
+template<typename BasicJsonType, typename CompatibleObjectType,
+         typename = void>
+struct is_compatible_object_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type_impl <
+    BasicJsonType, CompatibleObjectType,
+    enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
+    is_detected<key_type_t, CompatibleObjectType>::value >>
+{
+    using object_t = typename BasicJsonType::object_t;
+
+    // macOS's is_constructible does not play well with nonesuch...
+    static constexpr bool value =
+        is_constructible<typename object_t::key_type,
+        typename CompatibleObjectType::key_type>::value &&
+        is_constructible<typename object_t::mapped_type,
+        typename CompatibleObjectType::mapped_type>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type
+    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+         typename = void>
+struct is_constructible_object_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type_impl <
+    BasicJsonType, ConstructibleObjectType,
+    enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
+    is_detected<key_type_t, ConstructibleObjectType>::value >>
+{
+    using object_t = typename BasicJsonType::object_t;
+
+    static constexpr bool value =
+        (is_default_constructible<ConstructibleObjectType>::value &&
+         (std::is_move_assignable<ConstructibleObjectType>::value ||
+          std::is_copy_assignable<ConstructibleObjectType>::value) &&
+         (is_constructible<typename ConstructibleObjectType::key_type,
+          typename object_t::key_type>::value &&
+          std::is_same <
+          typename object_t::mapped_type,
+          typename ConstructibleObjectType::mapped_type >::value)) ||
+        (has_from_json<BasicJsonType,
+         typename ConstructibleObjectType::mapped_type>::value ||
+         has_non_default_from_json <
+         BasicJsonType,
+         typename ConstructibleObjectType::mapped_type >::value);
+};
+
+template<typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type
+    : is_constructible_object_type_impl<BasicJsonType,
+      ConstructibleObjectType> {};
+
+template<typename BasicJsonType, typename CompatibleStringType>
+struct is_compatible_string_type
+{
+    static constexpr auto value =
+        is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
+};
+
+template<typename BasicJsonType, typename ConstructibleStringType>
+struct is_constructible_string_type
+{
+    // launder type through decltype() to fix compilation failure on ICPC
+#ifdef __INTEL_COMPILER
+    using laundered_type = decltype(std::declval<ConstructibleStringType>());
+#else
+    using laundered_type = ConstructibleStringType;
+#endif
+
+    static constexpr auto value =
+        conjunction <
+        is_constructible<laundered_type, typename BasicJsonType::string_t>,
+        is_detected_exact<typename BasicJsonType::string_t::value_type,
+        value_type_t, laundered_type >>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
+struct is_compatible_array_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type_impl <
+    BasicJsonType, CompatibleArrayType,
+    enable_if_t <
+    is_detected<iterator_t, CompatibleArrayType>::value&&
+    is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
+// special case for types like std::filesystem::path whose iterator's value_type are themselves
+// c.f. https://github.com/nlohmann/json/pull/3073
+    !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
+{
+    static constexpr bool value =
+        is_constructible<BasicJsonType,
+        range_value_t<CompatibleArrayType>>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type
+    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
+struct is_constructible_array_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+    BasicJsonType, ConstructibleArrayType,
+    enable_if_t<std::is_same<ConstructibleArrayType,
+    typename BasicJsonType::value_type>::value >>
+            : std::true_type {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+    BasicJsonType, ConstructibleArrayType,
+    enable_if_t < !std::is_same<ConstructibleArrayType,
+    typename BasicJsonType::value_type>::value&&
+    !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
+    is_default_constructible<ConstructibleArrayType>::value&&
+(std::is_move_assignable<ConstructibleArrayType>::value ||
+ std::is_copy_assignable<ConstructibleArrayType>::value)&&
+is_detected<iterator_t, ConstructibleArrayType>::value&&
+is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
+is_detected<range_value_t, ConstructibleArrayType>::value&&
+// special case for types like std::filesystem::path whose iterator's value_type are themselves
+// c.f. https://github.com/nlohmann/json/pull/3073
+!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
+        is_complete_type <
+        detected_t<range_value_t, ConstructibleArrayType >>::value >>
+{
+    using value_type = range_value_t<ConstructibleArrayType>;
+
+    static constexpr bool value =
+        std::is_same<value_type,
+        typename BasicJsonType::array_t::value_type>::value ||
+        has_from_json<BasicJsonType,
+        value_type>::value ||
+        has_non_default_from_json <
+        BasicJsonType,
+        value_type >::value;
+};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type
+    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType,
+         typename = void>
+struct is_compatible_integer_type_impl : std::false_type {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type_impl <
+    RealIntegerType, CompatibleNumberIntegerType,
+    enable_if_t < std::is_integral<RealIntegerType>::value&&
+    std::is_integral<CompatibleNumberIntegerType>::value&&
+    !std::is_same<bool, CompatibleNumberIntegerType>::value >>
+{
+    // is there an assert somewhere on overflows?
+    using RealLimits = std::numeric_limits<RealIntegerType>;
+    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
+
+    static constexpr auto value =
+        is_constructible<RealIntegerType,
+        CompatibleNumberIntegerType>::value &&
+        CompatibleLimits::is_integer &&
+        RealLimits::is_signed == CompatibleLimits::is_signed;
+};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type
+    : is_compatible_integer_type_impl<RealIntegerType,
+      CompatibleNumberIntegerType> {};
+
+template<typename BasicJsonType, typename CompatibleType, typename = void>
+struct is_compatible_type_impl: std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type_impl <
+    BasicJsonType, CompatibleType,
+    enable_if_t<is_complete_type<CompatibleType>::value >>
+{
+    static constexpr bool value =
+        has_to_json<BasicJsonType, CompatibleType>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type
+    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
+
+template<typename T1, typename T2>
+struct is_constructible_tuple : std::false_type {};
+
+template<typename T1, typename... Args>
+struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
+
+template<typename BasicJsonType, typename T>
+struct is_json_iterator_of : std::false_type {};
+
+template<typename BasicJsonType>
+struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
+
+template<typename BasicJsonType>
+struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
+{};
+
+// checks if a given type T is a template specialization of Primary
+template<template <typename...> class Primary, typename T>
+struct is_specialization_of : std::false_type {};
+
+template<template <typename...> class Primary, typename... Args>
+struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
+
+template<typename T>
+using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
+
+// checks if A and B are comparable using Compare functor
+template<typename Compare, typename A, typename B, typename = void>
+struct is_comparable : std::false_type {};
+
+template<typename Compare, typename A, typename B>
+struct is_comparable<Compare, A, B, void_t<
+decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
+decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
+>> : std::true_type {};
+
+template<typename T>
+using detect_is_transparent = typename T::is_transparent;
+
+// type trait to check if KeyType can be used as object key (without a BasicJsonType)
+// see is_usable_as_basic_json_key_type below
+template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
+         bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
+using is_usable_as_key_type = typename std::conditional <
+                              is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
+                              && !(ExcludeObjectKeyType && std::is_same<KeyType,
+                                   ObjectKeyType>::value)
+                              && (!RequireTransparentComparator
+                                  || is_detected <detect_is_transparent, Comparator>::value)
+                              && !is_json_pointer<KeyType>::value,
+                              std::true_type,
+                              std::false_type >::type;
+
+// type trait to check if KeyType can be used as object key
+// true if:
+//   - KeyType is comparable with BasicJsonType::object_t::key_type
+//   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
+//   - the comparator is transparent or RequireTransparentComparator is false
+//   - KeyType is not a JSON iterator or json_pointer
+template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
+         bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
+using is_usable_as_basic_json_key_type = typename std::conditional <
+        is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
+        typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
+        RequireTransparentComparator, ExcludeObjectKeyType>::value
+        && !is_json_iterator_of<BasicJsonType, KeyType>::value,
+        std::true_type,
+        std::false_type >::type;
+
+template<typename ObjectType, typename KeyType>
+using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
+
+// type trait to check if object_t has an erase() member functions accepting KeyType
+template<typename BasicJsonType, typename KeyType>
+using has_erase_with_key_type = typename std::conditional <
+                                is_detected <
+                                detect_erase_with_key_type,
+                                typename BasicJsonType::object_t, KeyType >::value,
+                                std::true_type,
+                                std::false_type >::type;
+
+// a naive helper to check if a type is an ordered_map (exploits the fact that
+// ordered_map inherits capacity() from std::vector)
+template <typename T>
+struct is_ordered_map
+{
+    using one = char;
+
+    struct two
+    {
+        char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+    };
+
+    template <typename C> static one test( decltype(&C::capacity) ) ;
+    template <typename C> static two test(...);
+
+    enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+};
+
+// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
+template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
+T conditional_static_cast(U value)
+{
+    return static_cast<T>(value);
+}
+
+template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
+T conditional_static_cast(U value)
+{
+    return value;
+}
+
+template<typename... Types>
+using all_integral = conjunction<std::is_integral<Types>...>;
+
+template<typename... Types>
+using all_signed = conjunction<std::is_signed<Types>...>;
+
+template<typename... Types>
+using all_unsigned = conjunction<std::is_unsigned<Types>...>;
+
+// there's a disjunction trait in another PR; replace when merged
+template<typename... Types>
+using same_sign = std::integral_constant < bool,
+      all_signed<Types...>::value || all_unsigned<Types...>::value >;
+
+template<typename OfType, typename T>
+using never_out_of_range = std::integral_constant < bool,
+      (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
+      || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
+
+template<typename OfType, typename T,
+         bool OfTypeSigned = std::is_signed<OfType>::value,
+         bool TSigned = std::is_signed<T>::value>
+struct value_in_range_of_impl2;
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, false, false>
+{
+    static constexpr bool test(T val)
+    {
+        using CommonType = typename std::common_type<OfType, T>::type;
+        return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+    }
+};
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, true, false>
+{
+    static constexpr bool test(T val)
+    {
+        using CommonType = typename std::common_type<OfType, T>::type;
+        return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+    }
+};
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, false, true>
+{
+    static constexpr bool test(T val)
+    {
+        using CommonType = typename std::common_type<OfType, T>::type;
+        return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+    }
+};
+
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, true, true>
+{
+    static constexpr bool test(T val)
+    {
+        using CommonType = typename std::common_type<OfType, T>::type;
+        return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
+               && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+    }
+};
+
+template<typename OfType, typename T,
+         bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
+         typename = detail::enable_if_t<all_integral<OfType, T>::value>>
+struct value_in_range_of_impl1;
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl1<OfType, T, false>
+{
+    static constexpr bool test(T val)
+    {
+        return value_in_range_of_impl2<OfType, T>::test(val);
+    }
+};
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl1<OfType, T, true>
+{
+    static constexpr bool test(T /*val*/)
+    {
+        return true;
+    }
+};
+
+template<typename OfType, typename T>
+inline constexpr bool value_in_range_of(T val)
+{
+    return value_in_range_of_impl1<OfType, T>::test(val);
+}
+
+template<bool Value>
+using bool_constant = std::integral_constant<bool, Value>;
+
+///////////////////////////////////////////////////////////////////////////////
+// is_c_string
+///////////////////////////////////////////////////////////////////////////////
+
+namespace impl
+{
+
+template<typename T>
+inline constexpr bool is_c_string()
+{
+    using TUnExt = typename std::remove_extent<T>::type;
+    using TUnCVExt = typename std::remove_cv<TUnExt>::type;
+    using TUnPtr = typename std::remove_pointer<T>::type;
+    using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
+    return
+        (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
+        || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
+}
+
+}  // namespace impl
+
+// checks whether T is a [cv] char */[cv] char[] C string
+template<typename T>
+struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
+
+template<typename T>
+using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
+
+///////////////////////////////////////////////////////////////////////////////
+// is_transparent
+///////////////////////////////////////////////////////////////////////////////
+
+namespace impl
+{
+
+template<typename T>
+inline constexpr bool is_transparent()
+{
+    return is_detected<detect_is_transparent, T>::value;
+}
+
+}  // namespace impl
+
+// checks whether T has a member named is_transparent
+template<typename T>
+struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/string_concat.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstring> // strlen
+#include <string> // string
+#include <utility> // forward
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+inline std::size_t concat_length()
+{
+    return 0;
+}
+
+template<typename... Args>
+inline std::size_t concat_length(const char* cstr, Args&& ... rest);
+
+template<typename StringType, typename... Args>
+inline std::size_t concat_length(const StringType& str, Args&& ... rest);
+
+template<typename... Args>
+inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
+{
+    return 1 + concat_length(std::forward<Args>(rest)...);
+}
+
+template<typename... Args>
+inline std::size_t concat_length(const char* cstr, Args&& ... rest)
+{
+    // cppcheck-suppress ignoredReturnValue
+    return ::strlen(cstr) + concat_length(std::forward<Args>(rest)...);
+}
+
+template<typename StringType, typename... Args>
+inline std::size_t concat_length(const StringType& str, Args&& ... rest)
+{
+    return str.size() + concat_length(std::forward<Args>(rest)...);
+}
+
+template<typename OutStringType>
+inline void concat_into(OutStringType& /*out*/)
+{}
+
+template<typename StringType, typename Arg>
+using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
+
+template<typename StringType, typename Arg>
+using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
+
+template<typename StringType, typename Arg>
+using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
+
+template<typename StringType, typename Arg>
+using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
+
+template<typename StringType, typename Arg>
+using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
+
+template<typename StringType, typename Arg>
+using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
+
+template<typename StringType, typename Arg>
+using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
+
+template<typename StringType, typename Arg>
+using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
+
+template < typename OutStringType, typename Arg, typename... Args,
+           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+                         && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
+inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
+
+template < typename OutStringType, typename Arg, typename... Args,
+           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+                         && !detect_string_can_append_op<OutStringType, Arg>::value
+                         && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
+inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
+
+template < typename OutStringType, typename Arg, typename... Args,
+           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+                         && !detect_string_can_append_op<OutStringType, Arg>::value
+                         && !detect_string_can_append_iter<OutStringType, Arg>::value
+                         && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
+inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
+
+template<typename OutStringType, typename Arg, typename... Args,
+         enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
+inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
+{
+    out.append(std::forward<Arg>(arg));
+    concat_into(out, std::forward<Args>(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+                         && detect_string_can_append_op<OutStringType, Arg>::value, int > >
+inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
+{
+    out += std::forward<Arg>(arg);
+    concat_into(out, std::forward<Args>(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+                         && !detect_string_can_append_op<OutStringType, Arg>::value
+                         && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
+inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
+{
+    out.append(arg.begin(), arg.end());
+    concat_into(out, std::forward<Args>(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+                         && !detect_string_can_append_op<OutStringType, Arg>::value
+                         && !detect_string_can_append_iter<OutStringType, Arg>::value
+                         && detect_string_can_append_data<OutStringType, Arg>::value, int > >
+inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
+{
+    out.append(arg.data(), arg.size());
+    concat_into(out, std::forward<Args>(rest)...);
+}
+
+template<typename OutStringType = std::string, typename... Args>
+inline OutStringType concat(Args && ... args)
+{
+    OutStringType str;
+    str.reserve(concat_length(std::forward<Args>(args)...));
+    concat_into(str, std::forward<Args>(args)...);
+    return str;
+}
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+////////////////
+// exceptions //
+////////////////
+
+/// @brief general exception of the @ref basic_json class
+/// @sa https://json.nlohmann.me/api/basic_json/exception/
+class exception : public std::exception
+{
+  public:
+    /// returns the explanatory string
+    const char* what() const noexcept override
+    {
+        return m.what();
+    }
+
+    /// the id of the exception
+    const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
+
+  protected:
+    JSON_HEDLEY_NON_NULL(3)
+    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
+
+    static std::string name(const std::string& ename, int id_)
+    {
+        return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
+    }
+
+    static std::string diagnostics(std::nullptr_t /*leaf_element*/)
+    {
+        return "";
+    }
+
+    template<typename BasicJsonType>
+    static std::string diagnostics(const BasicJsonType* leaf_element)
+    {
+#if JSON_DIAGNOSTICS
+        std::vector<std::string> tokens;
+        for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
+        {
+            switch (current->m_parent->type())
+            {
+                case value_t::array:
+                {
+                    for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
+                    {
+                        if (&current->m_parent->m_value.array->operator[](i) == current)
+                        {
+                            tokens.emplace_back(std::to_string(i));
+                            break;
+                        }
+                    }
+                    break;
+                }
+
+                case value_t::object:
+                {
+                    for (const auto& element : *current->m_parent->m_value.object)
+                    {
+                        if (&element.second == current)
+                        {
+                            tokens.emplace_back(element.first.c_str());
+                            break;
+                        }
+                    }
+                    break;
+                }
+
+                case value_t::null: // LCOV_EXCL_LINE
+                case value_t::string: // LCOV_EXCL_LINE
+                case value_t::boolean: // LCOV_EXCL_LINE
+                case value_t::number_integer: // LCOV_EXCL_LINE
+                case value_t::number_unsigned: // LCOV_EXCL_LINE
+                case value_t::number_float: // LCOV_EXCL_LINE
+                case value_t::binary: // LCOV_EXCL_LINE
+                case value_t::discarded: // LCOV_EXCL_LINE
+                default:   // LCOV_EXCL_LINE
+                    break; // LCOV_EXCL_LINE
+            }
+        }
+
+        if (tokens.empty())
+        {
+            return "";
+        }
+
+        auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
+                                   [](const std::string & a, const std::string & b)
+        {
+            return concat(a, '/', detail::escape(b));
+        });
+        return concat('(', str, ") ");
+#else
+        static_cast<void>(leaf_element);
+        return "";
+#endif
+    }
+
+  private:
+    /// an exception object as storage for error messages
+    std::runtime_error m;
+};
+
+/// @brief exception indicating a parse error
+/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
+class parse_error : public exception
+{
+  public:
+    /*!
+    @brief create a parse error exception
+    @param[in] id_       the id of the exception
+    @param[in] pos       the position where the error occurred (or with
+                         chars_read_total=0 if the position cannot be
+                         determined)
+    @param[in] what_arg  the explanatory string
+    @return parse_error object
+    */
+    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+    static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
+    {
+        std::string w = concat(exception::name("parse_error", id_), "parse error",
+                               position_string(pos), ": ", exception::diagnostics(context), what_arg);
+        return {id_, pos.chars_read_total, w.c_str()};
+    }
+
+    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
+    {
+        std::string w = concat(exception::name("parse_error", id_), "parse error",
+                               (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
+                               ": ", exception::diagnostics(context), what_arg);
+        return {id_, byte_, w.c_str()};
+    }
+
+    /*!
+    @brief byte index of the parse error
+
+    The byte index of the last read character in the input file.
+
+    @note For an input with n bytes, 1 is the index of the first character and
+          n+1 is the index of the terminating null byte or the end of file.
+          This also holds true when reading a byte vector (CBOR or MessagePack).
+    */
+    const std::size_t byte;
+
+  private:
+    parse_error(int id_, std::size_t byte_, const char* what_arg)
+        : exception(id_, what_arg), byte(byte_) {}
+
+    static std::string position_string(const position_t& pos)
+    {
+        return concat(" at line ", std::to_string(pos.lines_read + 1),
+                      ", column ", std::to_string(pos.chars_read_current_line));
+    }
+};
+
+/// @brief exception indicating errors with iterators
+/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
+class invalid_iterator : public exception
+{
+  public:
+    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+    static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
+    {
+        std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    invalid_iterator(int id_, const char* what_arg)
+        : exception(id_, what_arg) {}
+};
+
+/// @brief exception indicating executing a member function with a wrong type
+/// @sa https://json.nlohmann.me/api/basic_json/type_error/
+class type_error : public exception
+{
+  public:
+    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+    static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
+    {
+        std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/// @brief exception indicating access out of the defined range
+/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
+class out_of_range : public exception
+{
+  public:
+    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+    static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
+    {
+        std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/// @brief exception indicating other library errors
+/// @sa https://json.nlohmann.me/api/basic_json/other_error/
+class other_error : public exception
+{
+  public:
+    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+    static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
+    {
+        std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+// dispatching helper struct
+template <class T> struct identity_tag {};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/std_fs.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
+#include <experimental/filesystem>
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+namespace std_fs = std::experimental::filesystem;
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+#elif JSON_HAS_FILESYSTEM
+#include <filesystem>
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+namespace std_fs = std::filesystem;
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+#endif
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
+    }
+    n = nullptr;
+}
+
+// overloads for basic_json template parameters
+template < typename BasicJsonType, typename ArithmeticType,
+           enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
+                         !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+                         int > = 0 >
+void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
+{
+    switch (static_cast<value_t>(j))
+    {
+        case value_t::number_unsigned:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+            break;
+        }
+        case value_t::number_integer:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+            break;
+        }
+        case value_t::number_float:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+            break;
+        }
+
+        case value_t::null:
+        case value_t::object:
+        case value_t::array:
+        case value_t::string:
+        case value_t::boolean:
+        case value_t::binary:
+        case value_t::discarded:
+        default:
+            JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
+    }
+}
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
+    }
+    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
+}
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
+    }
+    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template <
+    typename BasicJsonType, typename StringType,
+    enable_if_t <
+        std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
+        && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
+        && !std::is_same<typename BasicJsonType::string_t, StringType>::value
+        && !is_json_ref<StringType>::value, int > = 0 >
+inline void from_json(const BasicJsonType& j, StringType& s)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
+    }
+
+    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+#if !JSON_DISABLE_ENUM_SERIALIZATION
+template<typename BasicJsonType, typename EnumType,
+         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+inline void from_json(const BasicJsonType& j, EnumType& e)
+{
+    typename std::underlying_type<EnumType>::type val;
+    get_arithmetic_value(j, val);
+    e = static_cast<EnumType>(val);
+}
+#endif  // JSON_DISABLE_ENUM_SERIALIZATION
+
+// forward_list doesn't have an insert method
+template<typename BasicJsonType, typename T, typename Allocator,
+         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
+inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+    l.clear();
+    std::transform(j.rbegin(), j.rend(),
+                   std::front_inserter(l), [](const BasicJsonType & i)
+    {
+        return i.template get<T>();
+    });
+}
+
+// valarray doesn't have an insert method
+template<typename BasicJsonType, typename T,
+         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
+inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+    l.resize(j.size());
+    std::transform(j.begin(), j.end(), std::begin(l),
+                   [](const BasicJsonType & elem)
+    {
+        return elem.template get<T>();
+    });
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+-> decltype(j.template get<T>(), void())
+{
+    for (std::size_t i = 0; i < N; ++i)
+    {
+        arr[i] = j.at(i).template get<T>();
+    }
+}
+
+template<typename BasicJsonType>
+inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
+{
+    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
+                          priority_tag<2> /*unused*/)
+-> decltype(j.template get<T>(), void())
+{
+    for (std::size_t i = 0; i < N; ++i)
+    {
+        arr[i] = j.at(i).template get<T>();
+    }
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType,
+         enable_if_t<
+             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
+             int> = 0>
+auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
+-> decltype(
+    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
+    j.template get<typename ConstructibleArrayType::value_type>(),
+    void())
+{
+    using std::end;
+
+    ConstructibleArrayType ret;
+    ret.reserve(j.size());
+    std::transform(j.begin(), j.end(),
+                   std::inserter(ret, end(ret)), [](const BasicJsonType & i)
+    {
+        // get<BasicJsonType>() returns *this, this won't call a from_json
+        // method when value_type is BasicJsonType
+        return i.template get<typename ConstructibleArrayType::value_type>();
+    });
+    arr = std::move(ret);
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType,
+         enable_if_t<
+             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
+             int> = 0>
+inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
+                                 priority_tag<0> /*unused*/)
+{
+    using std::end;
+
+    ConstructibleArrayType ret;
+    std::transform(
+        j.begin(), j.end(), std::inserter(ret, end(ret)),
+        [](const BasicJsonType & i)
+    {
+        // get<BasicJsonType>() returns *this, this won't call a from_json
+        // method when value_type is BasicJsonType
+        return i.template get<typename ConstructibleArrayType::value_type>();
+    });
+    arr = std::move(ret);
+}
+
+template < typename BasicJsonType, typename ConstructibleArrayType,
+           enable_if_t <
+               is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
+               !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
+               !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
+               !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
+               !is_basic_json<ConstructibleArrayType>::value,
+               int > = 0 >
+auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
+-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
+j.template get<typename ConstructibleArrayType::value_type>(),
+void())
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+
+    from_json_array_impl(j, arr, priority_tag<3> {});
+}
+
+template < typename BasicJsonType, typename T, std::size_t... Idx >
+std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
+        identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
+{
+    return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
+}
+
+template < typename BasicJsonType, typename T, std::size_t N >
+auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
+-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+
+    return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
+}
+
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
+    }
+
+    bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
+}
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
+inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
+    }
+
+    ConstructibleObjectType ret;
+    const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
+    using value_type = typename ConstructibleObjectType::value_type;
+    std::transform(
+        inner_object->begin(), inner_object->end(),
+        std::inserter(ret, ret.begin()),
+        [](typename BasicJsonType::object_t::value_type const & p)
+    {
+        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
+    });
+    obj = std::move(ret);
+}
+
+// overload for arithmetic types, not chosen for basic_json template arguments
+// (BooleanType, etc..); note: Is it really necessary to provide explicit
+// overloads for boolean_t etc. in case of a custom BooleanType which is not
+// an arithmetic type?
+template < typename BasicJsonType, typename ArithmeticType,
+           enable_if_t <
+               std::is_arithmetic<ArithmeticType>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+               int > = 0 >
+inline void from_json(const BasicJsonType& j, ArithmeticType& val)
+{
+    switch (static_cast<value_t>(j))
+    {
+        case value_t::number_unsigned:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+            break;
+        }
+        case value_t::number_integer:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+            break;
+        }
+        case value_t::number_float:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+            break;
+        }
+        case value_t::boolean:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
+            break;
+        }
+
+        case value_t::null:
+        case value_t::object:
+        case value_t::array:
+        case value_t::string:
+        case value_t::binary:
+        case value_t::discarded:
+        default:
+            JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
+    }
+}
+
+template<typename BasicJsonType, typename... Args, std::size_t... Idx>
+std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
+{
+    return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
+}
+
+template < typename BasicJsonType, class A1, class A2 >
+std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
+{
+    return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
+            std::forward<BasicJsonType>(j).at(1).template get<A2>()};
+}
+
+template<typename BasicJsonType, typename A1, typename A2>
+inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
+{
+    p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
+}
+
+template<typename BasicJsonType, typename... Args>
+std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
+{
+    return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
+}
+
+template<typename BasicJsonType, typename... Args>
+inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
+{
+    t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
+}
+
+template<typename BasicJsonType, typename TupleRelated>
+auto from_json(BasicJsonType&& j, TupleRelated&& t)
+-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+
+    return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
+}
+
+template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
+           typename = enable_if_t < !std::is_constructible <
+                                        typename BasicJsonType::string_t, Key >::value >>
+inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+    m.clear();
+    for (const auto& p : j)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
+        {
+            JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
+        }
+        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+    }
+}
+
+template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
+           typename = enable_if_t < !std::is_constructible <
+                                        typename BasicJsonType::string_t, Key >::value >>
+inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
+    }
+    m.clear();
+    for (const auto& p : j)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
+        {
+            JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
+        }
+        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+    }
+}
+
+#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
+template<typename BasicJsonType>
+inline void from_json(const BasicJsonType& j, std_fs::path& p)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
+    }
+    p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+#endif
+
+struct from_json_fn
+{
+    template<typename BasicJsonType, typename T>
+    auto operator()(const BasicJsonType& j, T&& val) const
+    noexcept(noexcept(from_json(j, std::forward<T>(val))))
+    -> decltype(from_json(j, std::forward<T>(val)))
+    {
+        return from_json(j, std::forward<T>(val));
+    }
+};
+
+}  // namespace detail
+
+#ifndef JSON_HAS_CPP_17
+/// namespace to hold default `from_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
+{
+#endif
+JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
+    detail::static_const<detail::from_json_fn>::value;
+#ifndef JSON_HAS_CPP_17
+}  // namespace
+#endif
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // copy
+#include <iterator> // begin, end
+#include <string> // string
+#include <tuple> // tuple, get
+#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
+#include <utility> // move, forward, declval, pair
+#include <valarray> // valarray
+#include <vector> // vector
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstddef> // size_t
+#include <iterator> // input_iterator_tag
+#include <string> // string, to_string
+#include <tuple> // tuple_size, get, tuple_element
+#include <utility> // move
+
+#if JSON_HAS_RANGES
+    #include <ranges> // enable_borrowed_range
+#endif
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename string_type>
+void int_to_string( string_type& target, std::size_t value )
+{
+    // For ADL
+    using std::to_string;
+    target = to_string(value);
+}
+template<typename IteratorType> class iteration_proxy_value
+{
+  public:
+    using difference_type = std::ptrdiff_t;
+    using value_type = iteration_proxy_value;
+    using pointer = value_type *;
+    using reference = value_type &;
+    using iterator_category = std::input_iterator_tag;
+    using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
+
+  private:
+    /// the iterator
+    IteratorType anchor{};
+    /// an index for arrays (used to create key names)
+    std::size_t array_index = 0;
+    /// last stringified array index
+    mutable std::size_t array_index_last = 0;
+    /// a string representation of the array index
+    mutable string_type array_index_str = "0";
+    /// an empty string (to return a reference for primitive values)
+    string_type empty_str{};
+
+  public:
+    explicit iteration_proxy_value() = default;
+    explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
+    noexcept(std::is_nothrow_move_constructible<IteratorType>::value
+             && std::is_nothrow_default_constructible<string_type>::value)
+        : anchor(std::move(it))
+        , array_index(array_index_)
+    {}
+
+    iteration_proxy_value(iteration_proxy_value const&) = default;
+    iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
+    // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
+    iteration_proxy_value(iteration_proxy_value&&)
+    noexcept(std::is_nothrow_move_constructible<IteratorType>::value
+             && std::is_nothrow_move_constructible<string_type>::value) = default;
+    iteration_proxy_value& operator=(iteration_proxy_value&&)
+    noexcept(std::is_nothrow_move_assignable<IteratorType>::value
+             && std::is_nothrow_move_assignable<string_type>::value) = default;
+    ~iteration_proxy_value() = default;
+
+    /// dereference operator (needed for range-based for)
+    const iteration_proxy_value& operator*() const
+    {
+        return *this;
+    }
+
+    /// increment operator (needed for range-based for)
+    iteration_proxy_value& operator++()
+    {
+        ++anchor;
+        ++array_index;
+
+        return *this;
+    }
+
+    iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
+    {
+        auto tmp = iteration_proxy_value(anchor, array_index);
+        ++anchor;
+        ++array_index;
+        return tmp;
+    }
+
+    /// equality operator (needed for InputIterator)
+    bool operator==(const iteration_proxy_value& o) const
+    {
+        return anchor == o.anchor;
+    }
+
+    /// inequality operator (needed for range-based for)
+    bool operator!=(const iteration_proxy_value& o) const
+    {
+        return anchor != o.anchor;
+    }
+
+    /// return key of the iterator
+    const string_type& key() const
+    {
+        JSON_ASSERT(anchor.m_object != nullptr);
+
+        switch (anchor.m_object->type())
+        {
+            // use integer array index as key
+            case value_t::array:
+            {
+                if (array_index != array_index_last)
+                {
+                    int_to_string( array_index_str, array_index );
+                    array_index_last = array_index;
+                }
+                return array_index_str;
+            }
+
+            // use key from the object
+            case value_t::object:
+                return anchor.key();
+
+            // use an empty key for all primitive types
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return empty_str;
+        }
+    }
+
+    /// return value of the iterator
+    typename IteratorType::reference value() const
+    {
+        return anchor.value();
+    }
+};
+
+/// proxy class for the items() function
+template<typename IteratorType> class iteration_proxy
+{
+  private:
+    /// the container to iterate
+    typename IteratorType::pointer container = nullptr;
+
+  public:
+    explicit iteration_proxy() = default;
+
+    /// construct iteration proxy from a container
+    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
+        : container(&cont) {}
+
+    iteration_proxy(iteration_proxy const&) = default;
+    iteration_proxy& operator=(iteration_proxy const&) = default;
+    iteration_proxy(iteration_proxy&&) noexcept = default;
+    iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
+    ~iteration_proxy() = default;
+
+    /// return iterator begin (needed for range-based for)
+    iteration_proxy_value<IteratorType> begin() const noexcept
+    {
+        return iteration_proxy_value<IteratorType>(container->begin());
+    }
+
+    /// return iterator end (needed for range-based for)
+    iteration_proxy_value<IteratorType> end() const noexcept
+    {
+        return iteration_proxy_value<IteratorType>(container->end());
+    }
+};
+
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
+{
+    return i.key();
+}
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
+{
+    return i.value();
+}
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// The Addition to the STD Namespace is required to add
+// Structured Bindings Support to the iteration_proxy_value class
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+namespace std
+{
+
+#if defined(__clang__)
+    // Fix: https://github.com/nlohmann/json/issues/1401
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+template<typename IteratorType>
+class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
+            : public std::integral_constant<std::size_t, 2> {};
+
+template<std::size_t N, typename IteratorType>
+class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
+{
+  public:
+    using type = decltype(
+                     get<N>(std::declval <
+                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
+};
+#if defined(__clang__)
+    #pragma clang diagnostic pop
+#endif
+
+}  // namespace std
+
+#if JSON_HAS_RANGES
+    template <typename IteratorType>
+    inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
+#endif
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/std_fs.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+//////////////////
+// constructors //
+//////////////////
+
+/*
+ * Note all external_constructor<>::construct functions need to call
+ * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
+ * allocated value (e.g., a string). See bug issue
+ * https://github.com/nlohmann/json/issues/2865 for more information.
+ */
+
+template<value_t> struct external_constructor;
+
+template<>
+struct external_constructor<value_t::boolean>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::boolean;
+        j.m_value = b;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::string>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::string;
+        j.m_value = s;
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::string;
+        j.m_value = std::move(s);
+        j.assert_invariant();
+    }
+
+    template < typename BasicJsonType, typename CompatibleStringType,
+               enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
+                             int > = 0 >
+    static void construct(BasicJsonType& j, const CompatibleStringType& str)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::string;
+        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::binary>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::binary;
+        j.m_value = typename BasicJsonType::binary_t(b);
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::binary;
+        j.m_value = typename BasicJsonType::binary_t(std::move(b));
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_float>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::number_float;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_unsigned>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::number_unsigned;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_integer>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::number_integer;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::array>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = arr;
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = std::move(arr);
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template < typename BasicJsonType, typename CompatibleArrayType,
+               enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
+                             int > = 0 >
+    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
+    {
+        using std::begin;
+        using std::end;
+
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = value_t::array;
+        j.m_value.array->reserve(arr.size());
+        for (const bool x : arr)
+        {
+            j.m_value.array->push_back(x);
+            j.set_parent(j.m_value.array->back());
+        }
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType, typename T,
+             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = value_t::array;
+        j.m_value.array->resize(arr.size());
+        if (arr.size() > 0)
+        {
+            std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
+        }
+        j.set_parents();
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::object>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::object;
+        j.m_value = obj;
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::object;
+        j.m_value = std::move(obj);
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template < typename BasicJsonType, typename CompatibleObjectType,
+               enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
+    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
+    {
+        using std::begin;
+        using std::end;
+
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::object;
+        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
+        j.set_parents();
+        j.assert_invariant();
+    }
+};
+
+/////////////
+// to_json //
+/////////////
+
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
+inline void to_json(BasicJsonType& j, T b) noexcept
+{
+    external_constructor<value_t::boolean>::construct(j, b);
+}
+
+template < typename BasicJsonType, typename BoolRef,
+           enable_if_t <
+               ((std::is_same<std::vector<bool>::reference, BoolRef>::value
+                 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
+                || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
+                    && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
+                                      typename BasicJsonType::boolean_t >::value))
+               && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
+inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
+{
+    external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
+}
+
+template<typename BasicJsonType, typename CompatibleString,
+         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
+inline void to_json(BasicJsonType& j, const CompatibleString& s)
+{
+    external_constructor<value_t::string>::construct(j, s);
+}
+
+template<typename BasicJsonType>
+inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+{
+    external_constructor<value_t::string>::construct(j, std::move(s));
+}
+
+template<typename BasicJsonType, typename FloatType,
+         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
+inline void to_json(BasicJsonType& j, FloatType val) noexcept
+{
+    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
+         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
+inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
+{
+    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberIntegerType,
+         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
+inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
+{
+    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
+}
+
+#if !JSON_DISABLE_ENUM_SERIALIZATION
+template<typename BasicJsonType, typename EnumType,
+         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+inline void to_json(BasicJsonType& j, EnumType e) noexcept
+{
+    using underlying_type = typename std::underlying_type<EnumType>::type;
+    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
+}
+#endif  // JSON_DISABLE_ENUM_SERIALIZATION
+
+template<typename BasicJsonType>
+inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
+{
+    external_constructor<value_t::array>::construct(j, e);
+}
+
+template < typename BasicJsonType, typename CompatibleArrayType,
+           enable_if_t < is_compatible_array_type<BasicJsonType,
+                         CompatibleArrayType>::value&&
+                         !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
+                         !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
+                         !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
+                         !is_basic_json<CompatibleArrayType>::value,
+                         int > = 0 >
+inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
+{
+    external_constructor<value_t::array>::construct(j, arr);
+}
+
+template<typename BasicJsonType>
+inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
+{
+    external_constructor<value_t::binary>::construct(j, bin);
+}
+
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
+{
+    external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType>
+inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+{
+    external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template < typename BasicJsonType, typename CompatibleObjectType,
+           enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
+inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
+{
+    external_constructor<value_t::object>::construct(j, obj);
+}
+
+template<typename BasicJsonType>
+inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+{
+    external_constructor<value_t::object>::construct(j, std::move(obj));
+}
+
+template <
+    typename BasicJsonType, typename T, std::size_t N,
+    enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
+                  const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+                  int > = 0 >
+inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+{
+    external_constructor<value_t::array>::construct(j, arr);
+}
+
+template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
+inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
+{
+    j = { p.first, p.second };
+}
+
+// for https://github.com/nlohmann/json/pull/1134
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
+inline void to_json(BasicJsonType& j, const T& b)
+{
+    j = { {b.key(), b.value()} };
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
+{
+    j = { std::get<Idx>(t)... };
+}
+
+template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
+inline void to_json(BasicJsonType& j, const T& t)
+{
+    to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
+}
+
+#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
+template<typename BasicJsonType>
+inline void to_json(BasicJsonType& j, const std_fs::path& p)
+{
+    j = p.string();
+}
+#endif
+
+struct to_json_fn
+{
+    template<typename BasicJsonType, typename T>
+    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
+    -> decltype(to_json(j, std::forward<T>(val)), void())
+    {
+        return to_json(j, std::forward<T>(val));
+    }
+};
+}  // namespace detail
+
+#ifndef JSON_HAS_CPP_17
+/// namespace to hold default `to_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
+{
+#endif
+JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
+    detail::static_const<detail::to_json_fn>::value;
+#ifndef JSON_HAS_CPP_17
+}  // namespace
+#endif
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/// @sa https://json.nlohmann.me/api/adl_serializer/
+template<typename ValueType, typename>
+struct adl_serializer
+{
+    /// @brief convert a JSON value to any value type
+    /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
+    template<typename BasicJsonType, typename TargetType = ValueType>
+    static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
+        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
+    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
+    {
+        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
+    }
+
+    /// @brief convert a JSON value to any value type
+    /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
+    template<typename BasicJsonType, typename TargetType = ValueType>
+    static auto from_json(BasicJsonType && j) noexcept(
+    noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
+    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
+    {
+        return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
+    }
+
+    /// @brief convert any value type to a JSON value
+    /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
+    template<typename BasicJsonType, typename TargetType = ValueType>
+    static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
+        noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
+    -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
+    {
+        ::nlohmann::to_json(j, std::forward<TargetType>(val));
+    }
+};
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/byte_container_with_subtype.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstdint> // uint8_t, uint64_t
+#include <tuple> // tie
+#include <utility> // move
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/// @brief an internal type for a backed binary type
+/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
+template<typename BinaryType>
+class byte_container_with_subtype : public BinaryType
+{
+  public:
+    using container_type = BinaryType;
+    using subtype_type = std::uint64_t;
+
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
+    byte_container_with_subtype() noexcept(noexcept(container_type()))
+        : container_type()
+    {}
+
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
+    byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
+        : container_type(b)
+    {}
+
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
+    byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
+        : container_type(std::move(b))
+    {}
+
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
+    byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
+        : container_type(b)
+        , m_subtype(subtype_)
+        , m_has_subtype(true)
+    {}
+
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
+    byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
+        : container_type(std::move(b))
+        , m_subtype(subtype_)
+        , m_has_subtype(true)
+    {}
+
+    bool operator==(const byte_container_with_subtype& rhs) const
+    {
+        return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
+               std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
+    }
+
+    bool operator!=(const byte_container_with_subtype& rhs) const
+    {
+        return !(rhs == *this);
+    }
+
+    /// @brief sets the binary subtype
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
+    void set_subtype(subtype_type subtype_) noexcept
+    {
+        m_subtype = subtype_;
+        m_has_subtype = true;
+    }
+
+    /// @brief return the binary subtype
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
+    constexpr subtype_type subtype() const noexcept
+    {
+        return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
+    }
+
+    /// @brief return whether the value has a subtype
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
+    constexpr bool has_subtype() const noexcept
+    {
+        return m_has_subtype;
+    }
+
+    /// @brief clears the binary subtype
+    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
+    void clear_subtype() noexcept
+    {
+        m_subtype = 0;
+        m_has_subtype = false;
+    }
+
+  private:
+    subtype_type m_subtype = 0;
+    bool m_has_subtype = false;
+};
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/hash.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstdint> // uint8_t
+#include <cstddef> // size_t
+#include <functional> // hash
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+// boost::hash_combine
+inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
+{
+    seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
+    return seed;
+}
+
+/*!
+@brief hash a JSON value
+
+The hash function tries to rely on std::hash where possible. Furthermore, the
+type of the JSON value is taken into account to have different hash values for
+null, 0, 0U, and false, etc.
+
+@tparam BasicJsonType basic_json specialization
+@param j JSON value to hash
+@return hash value of j
+*/
+template<typename BasicJsonType>
+std::size_t hash(const BasicJsonType& j)
+{
+    using string_t = typename BasicJsonType::string_t;
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+
+    const auto type = static_cast<std::size_t>(j.type());
+    switch (j.type())
+    {
+        case BasicJsonType::value_t::null:
+        case BasicJsonType::value_t::discarded:
+        {
+            return combine(type, 0);
+        }
+
+        case BasicJsonType::value_t::object:
+        {
+            auto seed = combine(type, j.size());
+            for (const auto& element : j.items())
+            {
+                const auto h = std::hash<string_t> {}(element.key());
+                seed = combine(seed, h);
+                seed = combine(seed, hash(element.value()));
+            }
+            return seed;
+        }
+
+        case BasicJsonType::value_t::array:
+        {
+            auto seed = combine(type, j.size());
+            for (const auto& element : j)
+            {
+                seed = combine(seed, hash(element));
+            }
+            return seed;
+        }
+
+        case BasicJsonType::value_t::string:
+        {
+            const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::boolean:
+        {
+            const auto h = std::hash<bool> {}(j.template get<bool>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::number_integer:
+        {
+            const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::number_unsigned:
+        {
+            const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::number_float:
+        {
+            const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::binary:
+        {
+            auto seed = combine(type, j.get_binary().size());
+            const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
+            seed = combine(seed, h);
+            seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
+            for (const auto byte : j.get_binary())
+            {
+                seed = combine(seed, std::hash<std::uint8_t> {}(byte));
+            }
+            return seed;
+        }
+
+        default:                   // LCOV_EXCL_LINE
+            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+            return 0;              // LCOV_EXCL_LINE
+    }
+}
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // generate_n
+#include <array> // array
+#include <cmath> // ldexp
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstdio> // snprintf
+#include <cstring> // memcpy
+#include <iterator> // back_inserter
+#include <limits> // numeric_limits
+#include <string> // char_traits, string
+#include <utility> // make_pair, move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <cstring> // strlen
+#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
+#include <memory> // shared_ptr, make_shared, addressof
+#include <numeric> // accumulate
+#include <string> // string, char_traits
+#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
+#include <utility> // pair, declval
+
+#ifndef JSON_NO_IO
+    #include <cstdio>   // FILE *
+    #include <istream>  // istream
+#endif                  // JSON_NO_IO
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/// the supported input formats
+enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
+
+////////////////////
+// input adapters //
+////////////////////
+
+#ifndef JSON_NO_IO
+/*!
+Input adapter for stdio file access. This adapter read only 1 byte and do not use any
+ buffer. This adapter is a very low level adapter.
+*/
+class file_input_adapter
+{
+  public:
+    using char_type = char;
+
+    JSON_HEDLEY_NON_NULL(2)
+    explicit file_input_adapter(std::FILE* f) noexcept
+        : m_file(f)
+    {
+        JSON_ASSERT(m_file != nullptr);
+    }
+
+    // make class move-only
+    file_input_adapter(const file_input_adapter&) = delete;
+    file_input_adapter(file_input_adapter&&) noexcept = default;
+    file_input_adapter& operator=(const file_input_adapter&) = delete;
+    file_input_adapter& operator=(file_input_adapter&&) = delete;
+    ~file_input_adapter() = default;
+
+    std::char_traits<char>::int_type get_character() noexcept
+    {
+        return std::fgetc(m_file);
+    }
+
+  private:
+    /// the file pointer to read from
+    std::FILE* m_file;
+};
+
+
+/*!
+Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
+beginning of input. Does not support changing the underlying std::streambuf
+in mid-input. Maintains underlying std::istream and std::streambuf to support
+subsequent use of standard std::istream operations to process any input
+characters following those used in parsing the JSON input.  Clears the
+std::istream flags; any input errors (e.g., EOF) will be detected by the first
+subsequent call for input from the std::istream.
+*/
+class input_stream_adapter
+{
+  public:
+    using char_type = char;
+
+    ~input_stream_adapter()
+    {
+        // clear stream flags; we use underlying streambuf I/O, do not
+        // maintain ifstream flags, except eof
+        if (is != nullptr)
+        {
+            is->clear(is->rdstate() & std::ios::eofbit);
+        }
+    }
+
+    explicit input_stream_adapter(std::istream& i)
+        : is(&i), sb(i.rdbuf())
+    {}
+
+    // delete because of pointer members
+    input_stream_adapter(const input_stream_adapter&) = delete;
+    input_stream_adapter& operator=(input_stream_adapter&) = delete;
+    input_stream_adapter& operator=(input_stream_adapter&&) = delete;
+
+    input_stream_adapter(input_stream_adapter&& rhs) noexcept
+        : is(rhs.is), sb(rhs.sb)
+    {
+        rhs.is = nullptr;
+        rhs.sb = nullptr;
+    }
+
+    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
+    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
+    // end up as the same value, e.g. 0xFFFFFFFF.
+    std::char_traits<char>::int_type get_character()
+    {
+        auto res = sb->sbumpc();
+        // set eof manually, as we don't use the istream interface.
+        if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
+        {
+            is->clear(is->rdstate() | std::ios::eofbit);
+        }
+        return res;
+    }
+
+  private:
+    /// the associated input stream
+    std::istream* is = nullptr;
+    std::streambuf* sb = nullptr;
+};
+#endif  // JSON_NO_IO
+
+// General-purpose iterator-based adapter. It might not be as fast as
+// theoretically possible for some containers, but it is extremely versatile.
+template<typename IteratorType>
+class iterator_input_adapter
+{
+  public:
+    using char_type = typename std::iterator_traits<IteratorType>::value_type;
+
+    iterator_input_adapter(IteratorType first, IteratorType last)
+        : current(std::move(first)), end(std::move(last))
+    {}
+
+    typename std::char_traits<char_type>::int_type get_character()
+    {
+        if (JSON_HEDLEY_LIKELY(current != end))
+        {
+            auto result = std::char_traits<char_type>::to_int_type(*current);
+            std::advance(current, 1);
+            return result;
+        }
+
+        return std::char_traits<char_type>::eof();
+    }
+
+  private:
+    IteratorType current;
+    IteratorType end;
+
+    template<typename BaseInputAdapter, size_t T>
+    friend struct wide_string_input_helper;
+
+    bool empty() const
+    {
+        return current == end;
+    }
+};
+
+
+template<typename BaseInputAdapter, size_t T>
+struct wide_string_input_helper;
+
+template<typename BaseInputAdapter>
+struct wide_string_input_helper<BaseInputAdapter, 4>
+{
+    // UTF-32
+    static void fill_buffer(BaseInputAdapter& input,
+                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+                            size_t& utf8_bytes_index,
+                            size_t& utf8_bytes_filled)
+    {
+        utf8_bytes_index = 0;
+
+        if (JSON_HEDLEY_UNLIKELY(input.empty()))
+        {
+            utf8_bytes[0] = std::char_traits<char>::eof();
+            utf8_bytes_filled = 1;
+        }
+        else
+        {
+            // get the current character
+            const auto wc = input.get_character();
+
+            // UTF-32 to UTF-8 encoding
+            if (wc < 0x80)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+            else if (wc <= 0x7FF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 2;
+            }
+            else if (wc <= 0xFFFF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 3;
+            }
+            else if (wc <= 0x10FFFF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 4;
+            }
+            else
+            {
+                // unknown character
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+        }
+    }
+};
+
+template<typename BaseInputAdapter>
+struct wide_string_input_helper<BaseInputAdapter, 2>
+{
+    // UTF-16
+    static void fill_buffer(BaseInputAdapter& input,
+                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+                            size_t& utf8_bytes_index,
+                            size_t& utf8_bytes_filled)
+    {
+        utf8_bytes_index = 0;
+
+        if (JSON_HEDLEY_UNLIKELY(input.empty()))
+        {
+            utf8_bytes[0] = std::char_traits<char>::eof();
+            utf8_bytes_filled = 1;
+        }
+        else
+        {
+            // get the current character
+            const auto wc = input.get_character();
+
+            // UTF-16 to UTF-8 encoding
+            if (wc < 0x80)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+            else if (wc <= 0x7FF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 2;
+            }
+            else if (0xD800 > wc || wc >= 0xE000)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 3;
+            }
+            else
+            {
+                if (JSON_HEDLEY_UNLIKELY(!input.empty()))
+                {
+                    const auto wc2 = static_cast<unsigned int>(input.get_character());
+                    const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
+                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
+                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
+                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
+                    utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
+                    utf8_bytes_filled = 4;
+                }
+                else
+                {
+                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                    utf8_bytes_filled = 1;
+                }
+            }
+        }
+    }
+};
+
+// Wraps another input apdater to convert wide character types into individual bytes.
+template<typename BaseInputAdapter, typename WideCharType>
+class wide_string_input_adapter
+{
+  public:
+    using char_type = char;
+
+    wide_string_input_adapter(BaseInputAdapter base)
+        : base_adapter(base) {}
+
+    typename std::char_traits<char>::int_type get_character() noexcept
+    {
+        // check if buffer needs to be filled
+        if (utf8_bytes_index == utf8_bytes_filled)
+        {
+            fill_buffer<sizeof(WideCharType)>();
+
+            JSON_ASSERT(utf8_bytes_filled > 0);
+            JSON_ASSERT(utf8_bytes_index == 0);
+        }
+
+        // use buffer
+        JSON_ASSERT(utf8_bytes_filled > 0);
+        JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
+        return utf8_bytes[utf8_bytes_index++];
+    }
+
+  private:
+    BaseInputAdapter base_adapter;
+
+    template<size_t T>
+    void fill_buffer()
+    {
+        wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
+    }
+
+    /// a buffer for UTF-8 bytes
+    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
+
+    /// index to the utf8_codes array for the next valid byte
+    std::size_t utf8_bytes_index = 0;
+    /// number of valid bytes in the utf8_codes array
+    std::size_t utf8_bytes_filled = 0;
+};
+
+
+template<typename IteratorType, typename Enable = void>
+struct iterator_input_adapter_factory
+{
+    using iterator_type = IteratorType;
+    using char_type = typename std::iterator_traits<iterator_type>::value_type;
+    using adapter_type = iterator_input_adapter<iterator_type>;
+
+    static adapter_type create(IteratorType first, IteratorType last)
+    {
+        return adapter_type(std::move(first), std::move(last));
+    }
+};
+
+template<typename T>
+struct is_iterator_of_multibyte
+{
+    using value_type = typename std::iterator_traits<T>::value_type;
+    enum
+    {
+        value = sizeof(value_type) > 1
+    };
+};
+
+template<typename IteratorType>
+struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
+{
+    using iterator_type = IteratorType;
+    using char_type = typename std::iterator_traits<iterator_type>::value_type;
+    using base_adapter_type = iterator_input_adapter<iterator_type>;
+    using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
+
+    static adapter_type create(IteratorType first, IteratorType last)
+    {
+        return adapter_type(base_adapter_type(std::move(first), std::move(last)));
+    }
+};
+
+// General purpose iterator-based input
+template<typename IteratorType>
+typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
+{
+    using factory_type = iterator_input_adapter_factory<IteratorType>;
+    return factory_type::create(first, last);
+}
+
+// Convenience shorthand from container to iterator
+// Enables ADL on begin(container) and end(container)
+// Encloses the using declarations in namespace for not to leak them to outside scope
+
+namespace container_input_adapter_factory_impl
+{
+
+using std::begin;
+using std::end;
+
+template<typename ContainerType, typename Enable = void>
+struct container_input_adapter_factory {};
+
+template<typename ContainerType>
+struct container_input_adapter_factory< ContainerType,
+       void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
+       {
+           using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
+
+           static adapter_type create(const ContainerType& container)
+{
+    return input_adapter(begin(container), end(container));
+}
+       };
+
+}  // namespace container_input_adapter_factory_impl
+
+template<typename ContainerType>
+typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
+{
+    return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
+}
+
+#ifndef JSON_NO_IO
+// Special cases with fast paths
+inline file_input_adapter input_adapter(std::FILE* file)
+{
+    return file_input_adapter(file);
+}
+
+inline input_stream_adapter input_adapter(std::istream& stream)
+{
+    return input_stream_adapter(stream);
+}
+
+inline input_stream_adapter input_adapter(std::istream&& stream)
+{
+    return input_stream_adapter(stream);
+}
+#endif  // JSON_NO_IO
+
+using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
+
+// Null-delimited strings, and the like.
+template < typename CharT,
+           typename std::enable_if <
+               std::is_pointer<CharT>::value&&
+               !std::is_array<CharT>::value&&
+               std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
+               sizeof(typename std::remove_pointer<CharT>::type) == 1,
+               int >::type = 0 >
+contiguous_bytes_input_adapter input_adapter(CharT b)
+{
+    auto length = std::strlen(reinterpret_cast<const char*>(b));
+    const auto* ptr = reinterpret_cast<const char*>(b);
+    return input_adapter(ptr, ptr + length);
+}
+
+template<typename T, std::size_t N>
+auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+{
+    return input_adapter(array, array + N);
+}
+
+// This class only handles inputs of input_buffer_adapter type.
+// It's required so that expressions like {ptr, len} can be implicitly cast
+// to the correct adapter.
+class span_input_adapter
+{
+  public:
+    template < typename CharT,
+               typename std::enable_if <
+                   std::is_pointer<CharT>::value&&
+                   std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
+                   sizeof(typename std::remove_pointer<CharT>::type) == 1,
+                   int >::type = 0 >
+    span_input_adapter(CharT b, std::size_t l)
+        : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
+
+    template<class IteratorType,
+             typename std::enable_if<
+                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
+                 int>::type = 0>
+    span_input_adapter(IteratorType first, IteratorType last)
+        : ia(input_adapter(first, last)) {}
+
+    contiguous_bytes_input_adapter&& get()
+    {
+        return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
+    }
+
+  private:
+    contiguous_bytes_input_adapter ia;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstddef>
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/*!
+@brief SAX interface
+
+This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
+Each function is called in different situations while the input is parsed. The
+boolean return value informs the parser whether to continue processing the
+input.
+*/
+template<typename BasicJsonType>
+struct json_sax
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+
+    /*!
+    @brief a null value was read
+    @return whether parsing should proceed
+    */
+    virtual bool null() = 0;
+
+    /*!
+    @brief a boolean value was read
+    @param[in] val  boolean value
+    @return whether parsing should proceed
+    */
+    virtual bool boolean(bool val) = 0;
+
+    /*!
+    @brief an integer number was read
+    @param[in] val  integer value
+    @return whether parsing should proceed
+    */
+    virtual bool number_integer(number_integer_t val) = 0;
+
+    /*!
+    @brief an unsigned integer number was read
+    @param[in] val  unsigned integer value
+    @return whether parsing should proceed
+    */
+    virtual bool number_unsigned(number_unsigned_t val) = 0;
+
+    /*!
+    @brief a floating-point number was read
+    @param[in] val  floating-point value
+    @param[in] s    raw token value
+    @return whether parsing should proceed
+    */
+    virtual bool number_float(number_float_t val, const string_t& s) = 0;
+
+    /*!
+    @brief a string value was read
+    @param[in] val  string value
+    @return whether parsing should proceed
+    @note It is safe to move the passed string value.
+    */
+    virtual bool string(string_t& val) = 0;
+
+    /*!
+    @brief a binary value was read
+    @param[in] val  binary value
+    @return whether parsing should proceed
+    @note It is safe to move the passed binary value.
+    */
+    virtual bool binary(binary_t& val) = 0;
+
+    /*!
+    @brief the beginning of an object was read
+    @param[in] elements  number of object elements or -1 if unknown
+    @return whether parsing should proceed
+    @note binary formats may report the number of elements
+    */
+    virtual bool start_object(std::size_t elements) = 0;
+
+    /*!
+    @brief an object key was read
+    @param[in] val  object key
+    @return whether parsing should proceed
+    @note It is safe to move the passed string.
+    */
+    virtual bool key(string_t& val) = 0;
+
+    /*!
+    @brief the end of an object was read
+    @return whether parsing should proceed
+    */
+    virtual bool end_object() = 0;
+
+    /*!
+    @brief the beginning of an array was read
+    @param[in] elements  number of array elements or -1 if unknown
+    @return whether parsing should proceed
+    @note binary formats may report the number of elements
+    */
+    virtual bool start_array(std::size_t elements) = 0;
+
+    /*!
+    @brief the end of an array was read
+    @return whether parsing should proceed
+    */
+    virtual bool end_array() = 0;
+
+    /*!
+    @brief a parse error occurred
+    @param[in] position    the position in the input where the error occurs
+    @param[in] last_token  the last read token
+    @param[in] ex          an exception object describing the error
+    @return whether parsing should proceed (must return false)
+    */
+    virtual bool parse_error(std::size_t position,
+                             const std::string& last_token,
+                             const detail::exception& ex) = 0;
+
+    json_sax() = default;
+    json_sax(const json_sax&) = default;
+    json_sax(json_sax&&) noexcept = default;
+    json_sax& operator=(const json_sax&) = default;
+    json_sax& operator=(json_sax&&) noexcept = default;
+    virtual ~json_sax() = default;
+};
+
+
+namespace detail
+{
+/*!
+@brief SAX implementation to create a JSON value from SAX events
+
+This class implements the @ref json_sax interface and processes the SAX events
+to create a JSON value which makes it basically a DOM parser. The structure or
+hierarchy of the JSON value is managed by the stack `ref_stack` which contains
+a pointer to the respective array or object for each recursion depth.
+
+After successful parsing, the value that is passed by reference to the
+constructor contains the parsed value.
+
+@tparam BasicJsonType  the JSON type
+*/
+template<typename BasicJsonType>
+class json_sax_dom_parser
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+
+    /*!
+    @param[in,out] r  reference to a JSON value that is manipulated while
+                       parsing
+    @param[in] allow_exceptions_  whether parse errors yield exceptions
+    */
+    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
+        : root(r), allow_exceptions(allow_exceptions_)
+    {}
+
+    // make class move-only
+    json_sax_dom_parser(const json_sax_dom_parser&) = delete;
+    json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
+    json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~json_sax_dom_parser() = default;
+
+    bool null()
+    {
+        handle_value(nullptr);
+        return true;
+    }
+
+    bool boolean(bool val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_integer(number_integer_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_float(number_float_t val, const string_t& /*unused*/)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool string(string_t& val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool binary(binary_t& val)
+    {
+        handle_value(std::move(val));
+        return true;
+    }
+
+    bool start_object(std::size_t len)
+    {
+        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
+
+        if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool key(string_t& val)
+    {
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(ref_stack.back()->is_object());
+
+        // add null at given key and store the reference for later
+        object_element = &(ref_stack.back()->m_value.object->operator[](val));
+        return true;
+    }
+
+    bool end_object()
+    {
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(ref_stack.back()->is_object());
+
+        ref_stack.back()->set_parents();
+        ref_stack.pop_back();
+        return true;
+    }
+
+    bool start_array(std::size_t len)
+    {
+        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
+
+        if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool end_array()
+    {
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(ref_stack.back()->is_array());
+
+        ref_stack.back()->set_parents();
+        ref_stack.pop_back();
+        return true;
+    }
+
+    template<class Exception>
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+                     const Exception& ex)
+    {
+        errored = true;
+        static_cast<void>(ex);
+        if (allow_exceptions)
+        {
+            JSON_THROW(ex);
+        }
+        return false;
+    }
+
+    constexpr bool is_errored() const
+    {
+        return errored;
+    }
+
+  private:
+    /*!
+    @invariant If the ref stack is empty, then the passed value will be the new
+               root.
+    @invariant If the ref stack contains a value, then it is an array or an
+               object to which we can add elements
+    */
+    template<typename Value>
+    JSON_HEDLEY_RETURNS_NON_NULL
+    BasicJsonType* handle_value(Value&& v)
+    {
+        if (ref_stack.empty())
+        {
+            root = BasicJsonType(std::forward<Value>(v));
+            return &root;
+        }
+
+        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
+
+        if (ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
+            return &(ref_stack.back()->m_value.array->back());
+        }
+
+        JSON_ASSERT(ref_stack.back()->is_object());
+        JSON_ASSERT(object_element);
+        *object_element = BasicJsonType(std::forward<Value>(v));
+        return object_element;
+    }
+
+    /// the parsed JSON value
+    BasicJsonType& root;
+    /// stack to model hierarchy of values
+    std::vector<BasicJsonType*> ref_stack {};
+    /// helper to hold the reference for the next object element
+    BasicJsonType* object_element = nullptr;
+    /// whether a syntax error occurred
+    bool errored = false;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+};
+
+template<typename BasicJsonType>
+class json_sax_dom_callback_parser
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using parser_callback_t = typename BasicJsonType::parser_callback_t;
+    using parse_event_t = typename BasicJsonType::parse_event_t;
+
+    json_sax_dom_callback_parser(BasicJsonType& r,
+                                 const parser_callback_t cb,
+                                 const bool allow_exceptions_ = true)
+        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
+    {
+        keep_stack.push_back(true);
+    }
+
+    // make class move-only
+    json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
+    json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
+    json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~json_sax_dom_callback_parser() = default;
+
+    bool null()
+    {
+        handle_value(nullptr);
+        return true;
+    }
+
+    bool boolean(bool val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_integer(number_integer_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_float(number_float_t val, const string_t& /*unused*/)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool string(string_t& val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool binary(binary_t& val)
+    {
+        handle_value(std::move(val));
+        return true;
+    }
+
+    bool start_object(std::size_t len)
+    {
+        // check callback for object start
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
+        keep_stack.push_back(keep);
+
+        auto val = handle_value(BasicJsonType::value_t::object, true);
+        ref_stack.push_back(val.second);
+
+        // check object limit
+        if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool key(string_t& val)
+    {
+        BasicJsonType k = BasicJsonType(val);
+
+        // check callback for key
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
+        key_keep_stack.push_back(keep);
+
+        // add discarded value at given key and store the reference for later
+        if (keep && ref_stack.back())
+        {
+            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
+        }
+
+        return true;
+    }
+
+    bool end_object()
+    {
+        if (ref_stack.back())
+        {
+            if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
+            {
+                // discard object
+                *ref_stack.back() = discarded;
+            }
+            else
+            {
+                ref_stack.back()->set_parents();
+            }
+        }
+
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(!keep_stack.empty());
+        ref_stack.pop_back();
+        keep_stack.pop_back();
+
+        if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
+        {
+            // remove discarded value
+            for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
+            {
+                if (it->is_discarded())
+                {
+                    ref_stack.back()->erase(it);
+                    break;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool start_array(std::size_t len)
+    {
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
+        keep_stack.push_back(keep);
+
+        auto val = handle_value(BasicJsonType::value_t::array, true);
+        ref_stack.push_back(val.second);
+
+        // check array limit
+        if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool end_array()
+    {
+        bool keep = true;
+
+        if (ref_stack.back())
+        {
+            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
+            if (keep)
+            {
+                ref_stack.back()->set_parents();
+            }
+            else
+            {
+                // discard array
+                *ref_stack.back() = discarded;
+            }
+        }
+
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(!keep_stack.empty());
+        ref_stack.pop_back();
+        keep_stack.pop_back();
+
+        // remove discarded value
+        if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->pop_back();
+        }
+
+        return true;
+    }
+
+    template<class Exception>
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+                     const Exception& ex)
+    {
+        errored = true;
+        static_cast<void>(ex);
+        if (allow_exceptions)
+        {
+            JSON_THROW(ex);
+        }
+        return false;
+    }
+
+    constexpr bool is_errored() const
+    {
+        return errored;
+    }
+
+  private:
+    /*!
+    @param[in] v  value to add to the JSON value we build during parsing
+    @param[in] skip_callback  whether we should skip calling the callback
+               function; this is required after start_array() and
+               start_object() SAX events, because otherwise we would call the
+               callback function with an empty array or object, respectively.
+
+    @invariant If the ref stack is empty, then the passed value will be the new
+               root.
+    @invariant If the ref stack contains a value, then it is an array or an
+               object to which we can add elements
+
+    @return pair of boolean (whether value should be kept) and pointer (to the
+            passed value in the ref_stack hierarchy; nullptr if not kept)
+    */
+    template<typename Value>
+    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
+    {
+        JSON_ASSERT(!keep_stack.empty());
+
+        // do not handle this value if we know it would be added to a discarded
+        // container
+        if (!keep_stack.back())
+        {
+            return {false, nullptr};
+        }
+
+        // create value
+        auto value = BasicJsonType(std::forward<Value>(v));
+
+        // check callback
+        const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
+
+        // do not handle this value if we just learnt it shall be discarded
+        if (!keep)
+        {
+            return {false, nullptr};
+        }
+
+        if (ref_stack.empty())
+        {
+            root = std::move(value);
+            return {true, &root};
+        }
+
+        // skip this value if we already decided to skip the parent
+        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
+        if (!ref_stack.back())
+        {
+            return {false, nullptr};
+        }
+
+        // we now only expect arrays and objects
+        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
+
+        // array
+        if (ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->emplace_back(std::move(value));
+            return {true, &(ref_stack.back()->m_value.array->back())};
+        }
+
+        // object
+        JSON_ASSERT(ref_stack.back()->is_object());
+        // check if we should store an element for the current key
+        JSON_ASSERT(!key_keep_stack.empty());
+        const bool store_element = key_keep_stack.back();
+        key_keep_stack.pop_back();
+
+        if (!store_element)
+        {
+            return {false, nullptr};
+        }
+
+        JSON_ASSERT(object_element);
+        *object_element = std::move(value);
+        return {true, object_element};
+    }
+
+    /// the parsed JSON value
+    BasicJsonType& root;
+    /// stack to model hierarchy of values
+    std::vector<BasicJsonType*> ref_stack {};
+    /// stack to manage which values to keep
+    std::vector<bool> keep_stack {};
+    /// stack to manage which object keys to keep
+    std::vector<bool> key_keep_stack {};
+    /// helper to hold the reference for the next object element
+    BasicJsonType* object_element = nullptr;
+    /// whether a syntax error occurred
+    bool errored = false;
+    /// callback function
+    const parser_callback_t callback = nullptr;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+    /// a discarded value for the callback
+    BasicJsonType discarded = BasicJsonType::value_t::discarded;
+};
+
+template<typename BasicJsonType>
+class json_sax_acceptor
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+
+    bool null()
+    {
+        return true;
+    }
+
+    bool boolean(bool /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_integer(number_integer_t /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool string(string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool binary(binary_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
+    {
+        return true;
+    }
+
+    bool key(string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool end_object()
+    {
+        return true;
+    }
+
+    bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
+    {
+        return true;
+    }
+
+    bool end_array()
+    {
+        return true;
+    }
+
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
+    {
+        return false;
+    }
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/input/lexer.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <array> // array
+#include <clocale> // localeconv
+#include <cstddef> // size_t
+#include <cstdio> // snprintf
+#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
+#include <initializer_list> // initializer_list
+#include <string> // char_traits, string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+///////////
+// lexer //
+///////////
+
+template<typename BasicJsonType>
+class lexer_base
+{
+  public:
+    /// token types for the parser
+    enum class token_type
+    {
+        uninitialized,    ///< indicating the scanner is uninitialized
+        literal_true,     ///< the `true` literal
+        literal_false,    ///< the `false` literal
+        literal_null,     ///< the `null` literal
+        value_string,     ///< a string -- use get_string() for actual value
+        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
+        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
+        value_float,      ///< an floating point number -- use get_number_float() for actual value
+        begin_array,      ///< the character for array begin `[`
+        begin_object,     ///< the character for object begin `{`
+        end_array,        ///< the character for array end `]`
+        end_object,       ///< the character for object end `}`
+        name_separator,   ///< the name separator `:`
+        value_separator,  ///< the value separator `,`
+        parse_error,      ///< indicating a parse error
+        end_of_input,     ///< indicating the end of the input buffer
+        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
+    };
+
+    /// return name of values of type token_type (only used for errors)
+    JSON_HEDLEY_RETURNS_NON_NULL
+    JSON_HEDLEY_CONST
+    static const char* token_type_name(const token_type t) noexcept
+    {
+        switch (t)
+        {
+            case token_type::uninitialized:
+                return "<uninitialized>";
+            case token_type::literal_true:
+                return "true literal";
+            case token_type::literal_false:
+                return "false literal";
+            case token_type::literal_null:
+                return "null literal";
+            case token_type::value_string:
+                return "string literal";
+            case token_type::value_unsigned:
+            case token_type::value_integer:
+            case token_type::value_float:
+                return "number literal";
+            case token_type::begin_array:
+                return "'['";
+            case token_type::begin_object:
+                return "'{'";
+            case token_type::end_array:
+                return "']'";
+            case token_type::end_object:
+                return "'}'";
+            case token_type::name_separator:
+                return "':'";
+            case token_type::value_separator:
+                return "','";
+            case token_type::parse_error:
+                return "<parse error>";
+            case token_type::end_of_input:
+                return "end of input";
+            case token_type::literal_or_value:
+                return "'[', '{', or a literal";
+            // LCOV_EXCL_START
+            default: // catch non-enum values
+                return "unknown token";
+                // LCOV_EXCL_STOP
+        }
+    }
+};
+/*!
+@brief lexical analysis
+
+This class organizes the lexical analysis during JSON deserialization.
+*/
+template<typename BasicJsonType, typename InputAdapterType>
+class lexer : public lexer_base<BasicJsonType>
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using char_type = typename InputAdapterType::char_type;
+    using char_int_type = typename std::char_traits<char_type>::int_type;
+
+  public:
+    using token_type = typename lexer_base<BasicJsonType>::token_type;
+
+    explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
+        : ia(std::move(adapter))
+        , ignore_comments(ignore_comments_)
+        , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
+    {}
+
+    // delete because of pointer members
+    lexer(const lexer&) = delete;
+    lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    lexer& operator=(lexer&) = delete;
+    lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~lexer() = default;
+
+  private:
+    /////////////////////
+    // locales
+    /////////////////////
+
+    /// return the locale-dependent decimal point
+    JSON_HEDLEY_PURE
+    static char get_decimal_point() noexcept
+    {
+        const auto* loc = localeconv();
+        JSON_ASSERT(loc != nullptr);
+        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
+    }
+
+    /////////////////////
+    // scan functions
+    /////////////////////
+
+    /*!
+    @brief get codepoint from 4 hex characters following `\u`
+
+    For input "\u c1 c2 c3 c4" the codepoint is:
+      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
+    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
+
+    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
+    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
+    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
+    between the ASCII value of the character and the desired integer value.
+
+    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
+            non-hex character)
+    */
+    int get_codepoint()
+    {
+        // this function only makes sense after reading `\u`
+        JSON_ASSERT(current == 'u');
+        int codepoint = 0;
+
+        const auto factors = { 12u, 8u, 4u, 0u };
+        for (const auto factor : factors)
+        {
+            get();
+
+            if (current >= '0' && current <= '9')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
+            }
+            else if (current >= 'A' && current <= 'F')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
+            }
+            else if (current >= 'a' && current <= 'f')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
+            }
+            else
+            {
+                return -1;
+            }
+        }
+
+        JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
+        return codepoint;
+    }
+
+    /*!
+    @brief check if the next byte(s) are inside a given range
+
+    Adds the current byte and, for each passed range, reads a new byte and
+    checks if it is inside the range. If a violation was detected, set up an
+    error message and return false. Otherwise, return true.
+
+    @param[in] ranges  list of integers; interpreted as list of pairs of
+                       inclusive lower and upper bound, respectively
+
+    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
+         1, 2, or 3 pairs. This precondition is enforced by an assertion.
+
+    @return true if and only if no range violation was detected
+    */
+    bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
+    {
+        JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
+        add(current);
+
+        for (auto range = ranges.begin(); range != ranges.end(); ++range)
+        {
+            get();
+            if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
+            {
+                add(current);
+            }
+            else
+            {
+                error_message = "invalid string: ill-formed UTF-8 byte";
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief scan a string literal
+
+    This function scans a string according to Sect. 7 of RFC 8259. While
+    scanning, bytes are escaped and copied into buffer token_buffer. Then the
+    function returns successfully, token_buffer is *not* null-terminated (as it
+    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
+    string.
+
+    @return token_type::value_string if string could be successfully scanned,
+            token_type::parse_error otherwise
+
+    @note In case of errors, variable error_message contains a textual
+          description.
+    */
+    token_type scan_string()
+    {
+        // reset token_buffer (ignore opening quote)
+        reset();
+
+        // we entered the function by reading an open quote
+        JSON_ASSERT(current == '\"');
+
+        while (true)
+        {
+            // get next character
+            switch (get())
+            {
+                // end of file while parsing string
+                case std::char_traits<char_type>::eof():
+                {
+                    error_message = "invalid string: missing closing quote";
+                    return token_type::parse_error;
+                }
+
+                // closing quote
+                case '\"':
+                {
+                    return token_type::value_string;
+                }
+
+                // escapes
+                case '\\':
+                {
+                    switch (get())
+                    {
+                        // quotation mark
+                        case '\"':
+                            add('\"');
+                            break;
+                        // reverse solidus
+                        case '\\':
+                            add('\\');
+                            break;
+                        // solidus
+                        case '/':
+                            add('/');
+                            break;
+                        // backspace
+                        case 'b':
+                            add('\b');
+                            break;
+                        // form feed
+                        case 'f':
+                            add('\f');
+                            break;
+                        // line feed
+                        case 'n':
+                            add('\n');
+                            break;
+                        // carriage return
+                        case 'r':
+                            add('\r');
+                            break;
+                        // tab
+                        case 't':
+                            add('\t');
+                            break;
+
+                        // unicode escapes
+                        case 'u':
+                        {
+                            const int codepoint1 = get_codepoint();
+                            int codepoint = codepoint1; // start with codepoint1
+
+                            if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
+                            {
+                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+                                return token_type::parse_error;
+                            }
+
+                            // check if code point is a high surrogate
+                            if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
+                            {
+                                // expect next \uxxxx entry
+                                if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
+                                {
+                                    const int codepoint2 = get_codepoint();
+
+                                    if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
+                                    {
+                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+                                        return token_type::parse_error;
+                                    }
+
+                                    // check if codepoint2 is a low surrogate
+                                    if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
+                                    {
+                                        // overwrite codepoint
+                                        codepoint = static_cast<int>(
+                                                        // high surrogate occupies the most significant 22 bits
+                                                        (static_cast<unsigned int>(codepoint1) << 10u)
+                                                        // low surrogate occupies the least significant 15 bits
+                                                        + static_cast<unsigned int>(codepoint2)
+                                                        // there is still the 0xD800, 0xDC00 and 0x10000 noise
+                                                        // in the result, so we have to subtract with:
+                                                        // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
+                                                        - 0x35FDC00u);
+                                    }
+                                    else
+                                    {
+                                        error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
+                                        return token_type::parse_error;
+                                    }
+                                }
+                                else
+                                {
+                                    error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
+                                    return token_type::parse_error;
+                                }
+                            }
+                            else
+                            {
+                                if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
+                                {
+                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
+                                    return token_type::parse_error;
+                                }
+                            }
+
+                            // result of the above calculation yields a proper codepoint
+                            JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
+
+                            // translate codepoint into bytes
+                            if (codepoint < 0x80)
+                            {
+                                // 1-byte characters: 0xxxxxxx (ASCII)
+                                add(static_cast<char_int_type>(codepoint));
+                            }
+                            else if (codepoint <= 0x7FF)
+                            {
+                                // 2-byte characters: 110xxxxx 10xxxxxx
+                                add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
+                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+                            else if (codepoint <= 0xFFFF)
+                            {
+                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
+                                add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
+                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+                            else
+                            {
+                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+                                add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
+                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
+                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+
+                            break;
+                        }
+
+                        // other characters after escape
+                        default:
+                            error_message = "invalid string: forbidden character after backslash";
+                            return token_type::parse_error;
+                    }
+
+                    break;
+                }
+
+                // invalid control characters
+                case 0x00:
+                {
+                    error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
+                    return token_type::parse_error;
+                }
+
+                case 0x01:
+                {
+                    error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
+                    return token_type::parse_error;
+                }
+
+                case 0x02:
+                {
+                    error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
+                    return token_type::parse_error;
+                }
+
+                case 0x03:
+                {
+                    error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
+                    return token_type::parse_error;
+                }
+
+                case 0x04:
+                {
+                    error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
+                    return token_type::parse_error;
+                }
+
+                case 0x05:
+                {
+                    error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
+                    return token_type::parse_error;
+                }
+
+                case 0x06:
+                {
+                    error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
+                    return token_type::parse_error;
+                }
+
+                case 0x07:
+                {
+                    error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
+                    return token_type::parse_error;
+                }
+
+                case 0x08:
+                {
+                    error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
+                    return token_type::parse_error;
+                }
+
+                case 0x09:
+                {
+                    error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
+                    return token_type::parse_error;
+                }
+
+                case 0x0A:
+                {
+                    error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
+                    return token_type::parse_error;
+                }
+
+                case 0x0B:
+                {
+                    error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
+                    return token_type::parse_error;
+                }
+
+                case 0x0C:
+                {
+                    error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
+                    return token_type::parse_error;
+                }
+
+                case 0x0D:
+                {
+                    error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
+                    return token_type::parse_error;
+                }
+
+                case 0x0E:
+                {
+                    error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
+                    return token_type::parse_error;
+                }
+
+                case 0x0F:
+                {
+                    error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
+                    return token_type::parse_error;
+                }
+
+                case 0x10:
+                {
+                    error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
+                    return token_type::parse_error;
+                }
+
+                case 0x11:
+                {
+                    error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
+                    return token_type::parse_error;
+                }
+
+                case 0x12:
+                {
+                    error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
+                    return token_type::parse_error;
+                }
+
+                case 0x13:
+                {
+                    error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
+                    return token_type::parse_error;
+                }
+
+                case 0x14:
+                {
+                    error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
+                    return token_type::parse_error;
+                }
+
+                case 0x15:
+                {
+                    error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
+                    return token_type::parse_error;
+                }
+
+                case 0x16:
+                {
+                    error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
+                    return token_type::parse_error;
+                }
+
+                case 0x17:
+                {
+                    error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
+                    return token_type::parse_error;
+                }
+
+                case 0x18:
+                {
+                    error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
+                    return token_type::parse_error;
+                }
+
+                case 0x19:
+                {
+                    error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
+                    return token_type::parse_error;
+                }
+
+                case 0x1A:
+                {
+                    error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
+                    return token_type::parse_error;
+                }
+
+                case 0x1B:
+                {
+                    error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
+                    return token_type::parse_error;
+                }
+
+                case 0x1C:
+                {
+                    error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
+                    return token_type::parse_error;
+                }
+
+                case 0x1D:
+                {
+                    error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
+                    return token_type::parse_error;
+                }
+
+                case 0x1E:
+                {
+                    error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
+                    return token_type::parse_error;
+                }
+
+                case 0x1F:
+                {
+                    error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
+                    return token_type::parse_error;
+                }
+
+                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
+                case 0x20:
+                case 0x21:
+                case 0x23:
+                case 0x24:
+                case 0x25:
+                case 0x26:
+                case 0x27:
+                case 0x28:
+                case 0x29:
+                case 0x2A:
+                case 0x2B:
+                case 0x2C:
+                case 0x2D:
+                case 0x2E:
+                case 0x2F:
+                case 0x30:
+                case 0x31:
+                case 0x32:
+                case 0x33:
+                case 0x34:
+                case 0x35:
+                case 0x36:
+                case 0x37:
+                case 0x38:
+                case 0x39:
+                case 0x3A:
+                case 0x3B:
+                case 0x3C:
+                case 0x3D:
+                case 0x3E:
+                case 0x3F:
+                case 0x40:
+                case 0x41:
+                case 0x42:
+                case 0x43:
+                case 0x44:
+                case 0x45:
+                case 0x46:
+                case 0x47:
+                case 0x48:
+                case 0x49:
+                case 0x4A:
+                case 0x4B:
+                case 0x4C:
+                case 0x4D:
+                case 0x4E:
+                case 0x4F:
+                case 0x50:
+                case 0x51:
+                case 0x52:
+                case 0x53:
+                case 0x54:
+                case 0x55:
+                case 0x56:
+                case 0x57:
+                case 0x58:
+                case 0x59:
+                case 0x5A:
+                case 0x5B:
+                case 0x5D:
+                case 0x5E:
+                case 0x5F:
+                case 0x60:
+                case 0x61:
+                case 0x62:
+                case 0x63:
+                case 0x64:
+                case 0x65:
+                case 0x66:
+                case 0x67:
+                case 0x68:
+                case 0x69:
+                case 0x6A:
+                case 0x6B:
+                case 0x6C:
+                case 0x6D:
+                case 0x6E:
+                case 0x6F:
+                case 0x70:
+                case 0x71:
+                case 0x72:
+                case 0x73:
+                case 0x74:
+                case 0x75:
+                case 0x76:
+                case 0x77:
+                case 0x78:
+                case 0x79:
+                case 0x7A:
+                case 0x7B:
+                case 0x7C:
+                case 0x7D:
+                case 0x7E:
+                case 0x7F:
+                {
+                    add(current);
+                    break;
+                }
+
+                // U+0080..U+07FF: bytes C2..DF 80..BF
+                case 0xC2:
+                case 0xC3:
+                case 0xC4:
+                case 0xC5:
+                case 0xC6:
+                case 0xC7:
+                case 0xC8:
+                case 0xC9:
+                case 0xCA:
+                case 0xCB:
+                case 0xCC:
+                case 0xCD:
+                case 0xCE:
+                case 0xCF:
+                case 0xD0:
+                case 0xD1:
+                case 0xD2:
+                case 0xD3:
+                case 0xD4:
+                case 0xD5:
+                case 0xD6:
+                case 0xD7:
+                case 0xD8:
+                case 0xD9:
+                case 0xDA:
+                case 0xDB:
+                case 0xDC:
+                case 0xDD:
+                case 0xDE:
+                case 0xDF:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
+                case 0xE0:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
+                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
+                case 0xE1:
+                case 0xE2:
+                case 0xE3:
+                case 0xE4:
+                case 0xE5:
+                case 0xE6:
+                case 0xE7:
+                case 0xE8:
+                case 0xE9:
+                case 0xEA:
+                case 0xEB:
+                case 0xEC:
+                case 0xEE:
+                case 0xEF:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
+                case 0xED:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
+                case 0xF0:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
+                case 0xF1:
+                case 0xF2:
+                case 0xF3:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+                case 0xF4:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // remaining bytes (80..C1 and F5..FF) are ill-formed
+                default:
+                {
+                    error_message = "invalid string: ill-formed UTF-8 byte";
+                    return token_type::parse_error;
+                }
+            }
+        }
+    }
+
+    /*!
+     * @brief scan a comment
+     * @return whether comment could be scanned successfully
+     */
+    bool scan_comment()
+    {
+        switch (get())
+        {
+            // single-line comments skip input until a newline or EOF is read
+            case '/':
+            {
+                while (true)
+                {
+                    switch (get())
+                    {
+                        case '\n':
+                        case '\r':
+                        case std::char_traits<char_type>::eof():
+                        case '\0':
+                            return true;
+
+                        default:
+                            break;
+                    }
+                }
+            }
+
+            // multi-line comments skip input until */ is read
+            case '*':
+            {
+                while (true)
+                {
+                    switch (get())
+                    {
+                        case std::char_traits<char_type>::eof():
+                        case '\0':
+                        {
+                            error_message = "invalid comment; missing closing '*/'";
+                            return false;
+                        }
+
+                        case '*':
+                        {
+                            switch (get())
+                            {
+                                case '/':
+                                    return true;
+
+                                default:
+                                {
+                                    unget();
+                                    continue;
+                                }
+                            }
+                        }
+
+                        default:
+                            continue;
+                    }
+                }
+            }
+
+            // unexpected character after reading '/'
+            default:
+            {
+                error_message = "invalid comment; expecting '/' or '*' after '/'";
+                return false;
+            }
+        }
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(float& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtof(str, endptr);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(double& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtod(str, endptr);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(long double& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtold(str, endptr);
+    }
+
+    /*!
+    @brief scan a number literal
+
+    This function scans a string according to Sect. 6 of RFC 8259.
+
+    The function is realized with a deterministic finite state machine derived
+    from the grammar described in RFC 8259. Starting in state "init", the
+    input is read and used to determined the next state. Only state "done"
+    accepts the number. State "error" is a trap state to model errors. In the
+    table below, "anything" means any character but the ones listed before.
+
+    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
+    ---------|----------|----------|----------|---------|---------|----------|-----------
+    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
+    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
+    zero     | done     | done     | exponent | done    | done    | decimal1 | done
+    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
+    decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error]
+    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
+    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
+    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
+    any2     | any2     | any2     | done     | done    | done    | done     | done
+
+    The state machine is realized with one label per state (prefixed with
+    "scan_number_") and `goto` statements between them. The state machine
+    contains cycles, but any cycle can be left when EOF is read. Therefore,
+    the function is guaranteed to terminate.
+
+    During scanning, the read bytes are stored in token_buffer. This string is
+    then converted to a signed integer, an unsigned integer, or a
+    floating-point number.
+
+    @return token_type::value_unsigned, token_type::value_integer, or
+            token_type::value_float if number could be successfully scanned,
+            token_type::parse_error otherwise
+
+    @note The scanner is independent of the current locale. Internally, the
+          locale's decimal point is used instead of `.` to work with the
+          locale-dependent converters.
+    */
+    token_type scan_number()  // lgtm [cpp/use-of-goto]
+    {
+        // reset token_buffer to store the number's bytes
+        reset();
+
+        // the type of the parsed number; initially set to unsigned; will be
+        // changed if minus sign, decimal point or exponent is read
+        token_type number_type = token_type::value_unsigned;
+
+        // state (init): we just found out we need to scan a number
+        switch (current)
+        {
+            case '-':
+            {
+                add(current);
+                goto scan_number_minus;
+            }
+
+            case '0':
+            {
+                add(current);
+                goto scan_number_zero;
+            }
+
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            // all other characters are rejected outside scan_number()
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+
+scan_number_minus:
+        // state: we just parsed a leading minus sign
+        number_type = token_type::value_integer;
+        switch (get())
+        {
+            case '0':
+            {
+                add(current);
+                goto scan_number_zero;
+            }
+
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after '-'";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_zero:
+        // state: we just parse a zero (maybe with a leading minus sign)
+        switch (get())
+        {
+            case '.':
+            {
+                add(decimal_point_char);
+                goto scan_number_decimal1;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_any1:
+        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            case '.':
+            {
+                add(decimal_point_char);
+                goto scan_number_decimal1;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_decimal1:
+        // state: we just parsed a decimal point
+        number_type = token_type::value_float;
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_decimal2;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after '.'";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_decimal2:
+        // we just parsed at least one number after a decimal point
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_decimal2;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_exponent:
+        // we just parsed an exponent
+        number_type = token_type::value_float;
+        switch (get())
+        {
+            case '+':
+            case '-':
+            {
+                add(current);
+                goto scan_number_sign;
+            }
+
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+            {
+                error_message =
+                    "invalid number; expected '+', '-', or digit after exponent";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_sign:
+        // we just parsed an exponent sign
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after exponent sign";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_any2:
+        // we just parsed a number after the exponent or exponent sign
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_done:
+        // unget the character after the number (we only read it to know that
+        // we are done scanning a number)
+        unget();
+
+        char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+        errno = 0;
+
+        // try to parse integers first and fall back to floats
+        if (number_type == token_type::value_unsigned)
+        {
+            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
+
+            // we checked the number format before
+            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+            if (errno == 0)
+            {
+                value_unsigned = static_cast<number_unsigned_t>(x);
+                if (value_unsigned == x)
+                {
+                    return token_type::value_unsigned;
+                }
+            }
+        }
+        else if (number_type == token_type::value_integer)
+        {
+            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
+
+            // we checked the number format before
+            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+            if (errno == 0)
+            {
+                value_integer = static_cast<number_integer_t>(x);
+                if (value_integer == x)
+                {
+                    return token_type::value_integer;
+                }
+            }
+        }
+
+        // this code is reached if we parse a floating-point number or if an
+        // integer conversion above failed
+        strtof(value_float, token_buffer.data(), &endptr);
+
+        // we checked the number format before
+        JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+        return token_type::value_float;
+    }
+
+    /*!
+    @param[in] literal_text  the literal text to expect
+    @param[in] length        the length of the passed literal text
+    @param[in] return_type   the token type to return on success
+    */
+    JSON_HEDLEY_NON_NULL(2)
+    token_type scan_literal(const char_type* literal_text, const std::size_t length,
+                            token_type return_type)
+    {
+        JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
+        for (std::size_t i = 1; i < length; ++i)
+        {
+            if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
+            {
+                error_message = "invalid literal";
+                return token_type::parse_error;
+            }
+        }
+        return return_type;
+    }
+
+    /////////////////////
+    // input management
+    /////////////////////
+
+    /// reset token_buffer; current character is beginning of token
+    void reset() noexcept
+    {
+        token_buffer.clear();
+        token_string.clear();
+        token_string.push_back(std::char_traits<char_type>::to_char_type(current));
+    }
+
+    /*
+    @brief get next character from the input
+
+    This function provides the interface to the used input adapter. It does
+    not throw in case the input reached EOF, but returns a
+    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
+    for use in error messages.
+
+    @return character read from the input
+    */
+    char_int_type get()
+    {
+        ++position.chars_read_total;
+        ++position.chars_read_current_line;
+
+        if (next_unget)
+        {
+            // just reset the next_unget variable and work with current
+            next_unget = false;
+        }
+        else
+        {
+            current = ia.get_character();
+        }
+
+        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
+        {
+            token_string.push_back(std::char_traits<char_type>::to_char_type(current));
+        }
+
+        if (current == '\n')
+        {
+            ++position.lines_read;
+            position.chars_read_current_line = 0;
+        }
+
+        return current;
+    }
+
+    /*!
+    @brief unget current character (read it again on next get)
+
+    We implement unget by setting variable next_unget to true. The input is not
+    changed - we just simulate ungetting by modifying chars_read_total,
+    chars_read_current_line, and token_string. The next call to get() will
+    behave as if the unget character is read again.
+    */
+    void unget()
+    {
+        next_unget = true;
+
+        --position.chars_read_total;
+
+        // in case we "unget" a newline, we have to also decrement the lines_read
+        if (position.chars_read_current_line == 0)
+        {
+            if (position.lines_read > 0)
+            {
+                --position.lines_read;
+            }
+        }
+        else
+        {
+            --position.chars_read_current_line;
+        }
+
+        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
+        {
+            JSON_ASSERT(!token_string.empty());
+            token_string.pop_back();
+        }
+    }
+
+    /// add a character to token_buffer
+    void add(char_int_type c)
+    {
+        token_buffer.push_back(static_cast<typename string_t::value_type>(c));
+    }
+
+  public:
+    /////////////////////
+    // value getters
+    /////////////////////
+
+    /// return integer value
+    constexpr number_integer_t get_number_integer() const noexcept
+    {
+        return value_integer;
+    }
+
+    /// return unsigned integer value
+    constexpr number_unsigned_t get_number_unsigned() const noexcept
+    {
+        return value_unsigned;
+    }
+
+    /// return floating-point value
+    constexpr number_float_t get_number_float() const noexcept
+    {
+        return value_float;
+    }
+
+    /// return current string value (implicitly resets the token; useful only once)
+    string_t& get_string()
+    {
+        return token_buffer;
+    }
+
+    /////////////////////
+    // diagnostics
+    /////////////////////
+
+    /// return position of last read token
+    constexpr position_t get_position() const noexcept
+    {
+        return position;
+    }
+
+    /// return the last read token (for errors only).  Will never contain EOF
+    /// (an arbitrary value that is not a valid char value, often -1), because
+    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
+    std::string get_token_string() const
+    {
+        // escape control characters
+        std::string result;
+        for (const auto c : token_string)
+        {
+            if (static_cast<unsigned char>(c) <= '\x1F')
+            {
+                // escape control characters
+                std::array<char, 9> cs{{}};
+                static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                result += cs.data();
+            }
+            else
+            {
+                // add character as is
+                result.push_back(static_cast<std::string::value_type>(c));
+            }
+        }
+
+        return result;
+    }
+
+    /// return syntax error message
+    JSON_HEDLEY_RETURNS_NON_NULL
+    constexpr const char* get_error_message() const noexcept
+    {
+        return error_message;
+    }
+
+    /////////////////////
+    // actual scanner
+    /////////////////////
+
+    /*!
+    @brief skip the UTF-8 byte order mark
+    @return true iff there is no BOM or the correct BOM has been skipped
+    */
+    bool skip_bom()
+    {
+        if (get() == 0xEF)
+        {
+            // check if we completely parse the BOM
+            return get() == 0xBB && get() == 0xBF;
+        }
+
+        // the first character is not the beginning of the BOM; unget it to
+        // process is later
+        unget();
+        return true;
+    }
+
+    void skip_whitespace()
+    {
+        do
+        {
+            get();
+        }
+        while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
+    }
+
+    token_type scan()
+    {
+        // initially, skip the BOM
+        if (position.chars_read_total == 0 && !skip_bom())
+        {
+            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
+            return token_type::parse_error;
+        }
+
+        // read next character and ignore whitespace
+        skip_whitespace();
+
+        // ignore comments
+        while (ignore_comments && current == '/')
+        {
+            if (!scan_comment())
+            {
+                return token_type::parse_error;
+            }
+
+            // skip following whitespace
+            skip_whitespace();
+        }
+
+        switch (current)
+        {
+            // structural characters
+            case '[':
+                return token_type::begin_array;
+            case ']':
+                return token_type::end_array;
+            case '{':
+                return token_type::begin_object;
+            case '}':
+                return token_type::end_object;
+            case ':':
+                return token_type::name_separator;
+            case ',':
+                return token_type::value_separator;
+
+            // literals
+            case 't':
+            {
+                std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
+                return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
+            }
+            case 'f':
+            {
+                std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
+                return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
+            }
+            case 'n':
+            {
+                std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
+                return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
+            }
+
+            // string
+            case '\"':
+                return scan_string();
+
+            // number
+            case '-':
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                return scan_number();
+
+            // end of input (the null byte is needed when parsing from
+            // string literals)
+            case '\0':
+            case std::char_traits<char_type>::eof():
+                return token_type::end_of_input;
+
+            // error
+            default:
+                error_message = "invalid literal";
+                return token_type::parse_error;
+        }
+    }
+
+  private:
+    /// input adapter
+    InputAdapterType ia;
+
+    /// whether comments should be ignored (true) or signaled as errors (false)
+    const bool ignore_comments = false;
+
+    /// the current character
+    char_int_type current = std::char_traits<char_type>::eof();
+
+    /// whether the next get() call should just return current
+    bool next_unget = false;
+
+    /// the start position of the current token
+    position_t position {};
+
+    /// raw input token string (for error messages)
+    std::vector<char_type> token_string {};
+
+    /// buffer for variable-length tokens (numbers, strings)
+    string_t token_buffer {};
+
+    /// a description of occurred lexer errors
+    const char* error_message = "";
+
+    // number values
+    number_integer_t value_integer = 0;
+    number_unsigned_t value_unsigned = 0;
+    number_float_t value_float = 0;
+
+    /// the decimal point
+    const char_int_type decimal_point_char = '.';
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstdint> // size_t
+#include <utility> // declval
+#include <string> // string
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename T>
+using null_function_t = decltype(std::declval<T&>().null());
+
+template<typename T>
+using boolean_function_t =
+    decltype(std::declval<T&>().boolean(std::declval<bool>()));
+
+template<typename T, typename Integer>
+using number_integer_function_t =
+    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
+
+template<typename T, typename Unsigned>
+using number_unsigned_function_t =
+    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
+
+template<typename T, typename Float, typename String>
+using number_float_function_t = decltype(std::declval<T&>().number_float(
+                                    std::declval<Float>(), std::declval<const String&>()));
+
+template<typename T, typename String>
+using string_function_t =
+    decltype(std::declval<T&>().string(std::declval<String&>()));
+
+template<typename T, typename Binary>
+using binary_function_t =
+    decltype(std::declval<T&>().binary(std::declval<Binary&>()));
+
+template<typename T>
+using start_object_function_t =
+    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
+
+template<typename T, typename String>
+using key_function_t =
+    decltype(std::declval<T&>().key(std::declval<String&>()));
+
+template<typename T>
+using end_object_function_t = decltype(std::declval<T&>().end_object());
+
+template<typename T>
+using start_array_function_t =
+    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
+
+template<typename T>
+using end_array_function_t = decltype(std::declval<T&>().end_array());
+
+template<typename T, typename Exception>
+using parse_error_function_t = decltype(std::declval<T&>().parse_error(
+        std::declval<std::size_t>(), std::declval<const std::string&>(),
+        std::declval<const Exception&>()));
+
+template<typename SAX, typename BasicJsonType>
+struct is_sax
+{
+  private:
+    static_assert(is_basic_json<BasicJsonType>::value,
+                  "BasicJsonType must be of type basic_json<...>");
+
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using exception_t = typename BasicJsonType::exception;
+
+  public:
+    static constexpr bool value =
+        is_detected_exact<bool, null_function_t, SAX>::value &&
+        is_detected_exact<bool, boolean_function_t, SAX>::value &&
+        is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
+        is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
+        is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
+        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
+        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
+        is_detected_exact<bool, start_object_function_t, SAX>::value &&
+        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
+        is_detected_exact<bool, end_object_function_t, SAX>::value &&
+        is_detected_exact<bool, start_array_function_t, SAX>::value &&
+        is_detected_exact<bool, end_array_function_t, SAX>::value &&
+        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
+};
+
+template<typename SAX, typename BasicJsonType>
+struct is_sax_static_asserts
+{
+  private:
+    static_assert(is_basic_json<BasicJsonType>::value,
+                  "BasicJsonType must be of type basic_json<...>");
+
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using exception_t = typename BasicJsonType::exception;
+
+  public:
+    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
+                  "Missing/invalid function: bool null()");
+    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+                  "Missing/invalid function: bool boolean(bool)");
+    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+                  "Missing/invalid function: bool boolean(bool)");
+    static_assert(
+        is_detected_exact<bool, number_integer_function_t, SAX,
+        number_integer_t>::value,
+        "Missing/invalid function: bool number_integer(number_integer_t)");
+    static_assert(
+        is_detected_exact<bool, number_unsigned_function_t, SAX,
+        number_unsigned_t>::value,
+        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
+    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
+                  number_float_t, string_t>::value,
+                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
+    static_assert(
+        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
+        "Missing/invalid function: bool string(string_t&)");
+    static_assert(
+        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
+        "Missing/invalid function: bool binary(binary_t&)");
+    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
+                  "Missing/invalid function: bool start_object(std::size_t)");
+    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
+                  "Missing/invalid function: bool key(string_t&)");
+    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
+                  "Missing/invalid function: bool end_object()");
+    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
+                  "Missing/invalid function: bool start_array(std::size_t)");
+    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
+                  "Missing/invalid function: bool end_array()");
+    static_assert(
+        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
+        "Missing/invalid function: bool parse_error(std::size_t, const "
+        "std::string&, const exception&)");
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/// how to treat CBOR tags
+enum class cbor_tag_handler_t
+{
+    error,   ///< throw a parse_error exception in case of a tag
+    ignore,  ///< ignore tags
+    store    ///< store tags as binary type
+};
+
+/*!
+@brief determine system byte order
+
+@return true if and only if system's byte order is little endian
+
+@note from https://stackoverflow.com/a/1001328/266378
+*/
+static inline bool little_endianness(int num = 1) noexcept
+{
+    return *reinterpret_cast<char*>(&num) == 1;
+}
+
+
+///////////////////
+// binary reader //
+///////////////////
+
+/*!
+@brief deserialization of CBOR, MessagePack, and UBJSON values
+*/
+template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
+class binary_reader
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using json_sax_t = SAX;
+    using char_type = typename InputAdapterType::char_type;
+    using char_int_type = typename std::char_traits<char_type>::int_type;
+
+  public:
+    /*!
+    @brief create a binary reader
+
+    @param[in] adapter  input adapter to read from
+    */
+    explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
+    {
+        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+    }
+
+    // make class move-only
+    binary_reader(const binary_reader&) = delete;
+    binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    binary_reader& operator=(const binary_reader&) = delete;
+    binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~binary_reader() = default;
+
+    /*!
+    @param[in] format  the binary format to parse
+    @param[in] sax_    a SAX event processor
+    @param[in] strict  whether to expect the input to be consumed completed
+    @param[in] tag_handler  how to treat CBOR tags
+
+    @return whether parsing was successful
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    bool sax_parse(const input_format_t format,
+                   json_sax_t* sax_,
+                   const bool strict = true,
+                   const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        sax = sax_;
+        bool result = false;
+
+        switch (format)
+        {
+            case input_format_t::bson:
+                result = parse_bson_internal();
+                break;
+
+            case input_format_t::cbor:
+                result = parse_cbor_internal(true, tag_handler);
+                break;
+
+            case input_format_t::msgpack:
+                result = parse_msgpack_internal();
+                break;
+
+            case input_format_t::ubjson:
+            case input_format_t::bjdata:
+                result = parse_ubjson_internal();
+                break;
+
+            case input_format_t::json: // LCOV_EXCL_LINE
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+
+        // strict mode: next byte must be EOF
+        if (result && strict)
+        {
+            if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
+            {
+                get_ignore_noop();
+            }
+            else
+            {
+                get();
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
+            {
+                return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
+                                        exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
+            }
+        }
+
+        return result;
+    }
+
+  private:
+    //////////
+    // BSON //
+    //////////
+
+    /*!
+    @brief Reads in a BSON-object and passes it to the SAX-parser.
+    @return whether a valid BSON-value was passed to the SAX parser
+    */
+    bool parse_bson_internal()
+    {
+        std::int32_t document_size{};
+        get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
+        {
+            return false;
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
+        {
+            return false;
+        }
+
+        return sax->end_object();
+    }
+
+    /*!
+    @brief Parses a C-style string from the BSON input.
+    @param[in,out] result  A reference to the string variable where the read
+                            string is to be stored.
+    @return `true` if the \x00-byte indicating the end of the string was
+             encountered before the EOF; false` indicates an unexpected EOF.
+    */
+    bool get_bson_cstr(string_t& result)
+    {
+        auto out = std::back_inserter(result);
+        while (true)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
+            {
+                return false;
+            }
+            if (current == 0x00)
+            {
+                return true;
+            }
+            *out++ = static_cast<typename string_t::value_type>(current);
+        }
+    }
+
+    /*!
+    @brief Parses a zero-terminated string of length @a len from the BSON
+           input.
+    @param[in] len  The length (including the zero-byte at the end) of the
+                    string to be read.
+    @param[in,out] result  A reference to the string variable where the read
+                            string is to be stored.
+    @tparam NumberType The type of the length @a len
+    @pre len >= 1
+    @return `true` if the string was successfully parsed
+    */
+    template<typename NumberType>
+    bool get_bson_string(const NumberType len, string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(len < 1))
+        {
+            auto last_token = get_token_string();
+            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                    exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
+        }
+
+        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
+    }
+
+    /*!
+    @brief Parses a byte array input of length @a len from the BSON input.
+    @param[in] len  The length of the byte array to be read.
+    @param[in,out] result  A reference to the binary variable where the read
+                            array is to be stored.
+    @tparam NumberType The type of the length @a len
+    @pre len >= 0
+    @return `true` if the byte array was successfully parsed
+    */
+    template<typename NumberType>
+    bool get_bson_binary(const NumberType len, binary_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(len < 0))
+        {
+            auto last_token = get_token_string();
+            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                    exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
+        }
+
+        // All BSON binary values have a subtype
+        std::uint8_t subtype{};
+        get_number<std::uint8_t>(input_format_t::bson, subtype);
+        result.set_subtype(subtype);
+
+        return get_binary(input_format_t::bson, len, result);
+    }
+
+    /*!
+    @brief Read a BSON document element of the given @a element_type.
+    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
+    @param[in] element_type_parse_position The position in the input stream,
+               where the `element_type` was read.
+    @warning Not all BSON element types are supported yet. An unsupported
+             @a element_type will give rise to a parse_error.114:
+             Unsupported BSON record type 0x...
+    @return whether a valid BSON-object/array was passed to the SAX parser
+    */
+    bool parse_bson_element_internal(const char_int_type element_type,
+                                     const std::size_t element_type_parse_position)
+    {
+        switch (element_type)
+        {
+            case 0x01: // double
+            {
+                double number{};
+                return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0x02: // string
+            {
+                std::int32_t len{};
+                string_t value;
+                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
+            }
+
+            case 0x03: // object
+            {
+                return parse_bson_internal();
+            }
+
+            case 0x04: // array
+            {
+                return parse_bson_array();
+            }
+
+            case 0x05: // binary
+            {
+                std::int32_t len{};
+                binary_t value;
+                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
+            }
+
+            case 0x08: // boolean
+            {
+                return sax->boolean(get() != 0);
+            }
+
+            case 0x0A: // null
+            {
+                return sax->null();
+            }
+
+            case 0x10: // int32
+            {
+                std::int32_t value{};
+                return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
+            }
+
+            case 0x12: // int64
+            {
+                std::int64_t value{};
+                return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
+            }
+
+            default: // anything else not supported (yet)
+            {
+                std::array<char, 3> cr{{}};
+                static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                std::string cr_str{cr.data()};
+                return sax->parse_error(element_type_parse_position, cr_str,
+                                        parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
+            }
+        }
+    }
+
+    /*!
+    @brief Read a BSON element list (as specified in the BSON-spec)
+
+    The same binary layout is used for objects and arrays, hence it must be
+    indicated with the argument @a is_array which one is expected
+    (true --> array, false --> object).
+
+    @param[in] is_array Determines if the element list being read is to be
+                        treated as an object (@a is_array == false), or as an
+                        array (@a is_array == true).
+    @return whether a valid BSON-object/array was passed to the SAX parser
+    */
+    bool parse_bson_element_list(const bool is_array)
+    {
+        string_t key;
+
+        while (auto element_type = get())
+        {
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
+            {
+                return false;
+            }
+
+            const std::size_t element_type_parse_position = chars_read;
+            if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
+            {
+                return false;
+            }
+
+            if (!is_array && !sax->key(key))
+            {
+                return false;
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
+            {
+                return false;
+            }
+
+            // get_bson_cstr only appends
+            key.clear();
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief Reads an array from the BSON input and passes it to the SAX-parser.
+    @return whether a valid BSON-array was passed to the SAX parser
+    */
+    bool parse_bson_array()
+    {
+        std::int32_t document_size{};
+        get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
+        {
+            return false;
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
+        {
+            return false;
+        }
+
+        return sax->end_array();
+    }
+
+    //////////
+    // CBOR //
+    //////////
+
+    /*!
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true) or whether the last read character should
+                         be considered instead (false)
+    @param[in] tag_handler how CBOR tags should be treated
+
+    @return whether a valid CBOR value was passed to the SAX parser
+    */
+    bool parse_cbor_internal(const bool get_char,
+                             const cbor_tag_handler_t tag_handler)
+    {
+        switch (get_char ? get() : current)
+        {
+            // EOF
+            case std::char_traits<char_type>::eof():
+                return unexpect_eof(input_format_t::cbor, "value");
+
+            // Integer 0x00..0x17 (0..23)
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0A:
+            case 0x0B:
+            case 0x0C:
+            case 0x0D:
+            case 0x0E:
+            case 0x0F:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+            case 0x18: // Unsigned integer (one-byte uint8_t follows)
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            case 0x19: // Unsigned integer (two-byte uint16_t follows)
+            {
+                std::uint16_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
+            {
+                std::uint32_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
+            {
+                std::uint64_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            // Negative integer -1-0x00..-1-0x17 (-1..-24)
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2A:
+            case 0x2B:
+            case 0x2C:
+            case 0x2D:
+            case 0x2E:
+            case 0x2F:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+                return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
+
+            case 0x38: // Negative integer (one-byte uint8_t follows)
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+            {
+                std::uint16_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
+            {
+                std::uint32_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
+            {
+                std::uint64_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
+                        - static_cast<number_integer_t>(number));
+            }
+
+            // Binary data (0x00..0x17 bytes follow)
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            case 0x58: // Binary data (one-byte uint8_t for n follows)
+            case 0x59: // Binary data (two-byte uint16_t for n follow)
+            case 0x5A: // Binary data (four-byte uint32_t for n follow)
+            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
+            case 0x5F: // Binary data (indefinite length)
+            {
+                binary_t b;
+                return get_cbor_binary(b) && sax->binary(b);
+            }
+
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+            case 0x7F: // UTF-8 string (indefinite length)
+            {
+                string_t s;
+                return get_cbor_string(s) && sax->string(s);
+            }
+
+            // array (0x00..0x17 data items follow)
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8A:
+            case 0x8B:
+            case 0x8C:
+            case 0x8D:
+            case 0x8E:
+            case 0x8F:
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+                return get_cbor_array(
+                           conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+
+            case 0x98: // array (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x99: // array (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x9A: // array (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x9B: // array (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x9F: // array (indefinite length)
+                return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
+
+            // map (0x00..0x17 pairs of data items follow)
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+                return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+
+            case 0xB8: // map (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xB9: // map (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xBA: // map (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xBB: // map (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xBF: // map (indefinite length)
+                return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
+
+            case 0xC6: // tagged item
+            case 0xC7:
+            case 0xC8:
+            case 0xC9:
+            case 0xCA:
+            case 0xCB:
+            case 0xCC:
+            case 0xCD:
+            case 0xCE:
+            case 0xCF:
+            case 0xD0:
+            case 0xD1:
+            case 0xD2:
+            case 0xD3:
+            case 0xD4:
+            case 0xD8: // tagged item (1 bytes follow)
+            case 0xD9: // tagged item (2 bytes follow)
+            case 0xDA: // tagged item (4 bytes follow)
+            case 0xDB: // tagged item (8 bytes follow)
+            {
+                switch (tag_handler)
+                {
+                    case cbor_tag_handler_t::error:
+                    {
+                        auto last_token = get_token_string();
+                        return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                                exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
+                    }
+
+                    case cbor_tag_handler_t::ignore:
+                    {
+                        // ignore binary subtype
+                        switch (current)
+                        {
+                            case 0xD8:
+                            {
+                                std::uint8_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            case 0xD9:
+                            {
+                                std::uint16_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            case 0xDA:
+                            {
+                                std::uint32_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            case 0xDB:
+                            {
+                                std::uint64_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            default:
+                                break;
+                        }
+                        return parse_cbor_internal(true, tag_handler);
+                    }
+
+                    case cbor_tag_handler_t::store:
+                    {
+                        binary_t b;
+                        // use binary subtype and store in binary container
+                        switch (current)
+                        {
+                            case 0xD8:
+                            {
+                                std::uint8_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            case 0xD9:
+                            {
+                                std::uint16_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            case 0xDA:
+                            {
+                                std::uint32_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            case 0xDB:
+                            {
+                                std::uint64_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            default:
+                                return parse_cbor_internal(true, tag_handler);
+                        }
+                        get();
+                        return get_cbor_binary(b) && sax->binary(b);
+                    }
+
+                    default:                 // LCOV_EXCL_LINE
+                        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+                        return false;        // LCOV_EXCL_LINE
+                }
+            }
+
+            case 0xF4: // false
+                return sax->boolean(false);
+
+            case 0xF5: // true
+                return sax->boolean(true);
+
+            case 0xF6: // null
+                return sax->null();
+
+            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
+            {
+                const auto byte1_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
+                {
+                    return false;
+                }
+                const auto byte2_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
+                {
+                    return false;
+                }
+
+                const auto byte1 = static_cast<unsigned char>(byte1_raw);
+                const auto byte2 = static_cast<unsigned char>(byte2_raw);
+
+                // code from RFC 7049, Appendix D, Figure 3:
+                // As half-precision floating-point numbers were only added
+                // to IEEE 754 in 2008, today's programming platforms often
+                // still only have limited support for them. It is very
+                // easy to include at least decoding support for them even
+                // without such support. An example of a small decoder for
+                // half-precision floating-point numbers in the C language
+                // is shown in Fig. 3.
+                const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
+                const double val = [&half]
+                {
+                    const int exp = (half >> 10u) & 0x1Fu;
+                    const unsigned int mant = half & 0x3FFu;
+                    JSON_ASSERT(0 <= exp&& exp <= 32);
+                    JSON_ASSERT(mant <= 1024);
+                    switch (exp)
+                    {
+                        case 0:
+                            return std::ldexp(mant, -24);
+                        case 31:
+                            return (mant == 0)
+                            ? std::numeric_limits<double>::infinity()
+                            : std::numeric_limits<double>::quiet_NaN();
+                        default:
+                            return std::ldexp(mant + 1024, exp - 25);
+                    }
+                }();
+                return sax->number_float((half & 0x8000u) != 0
+                                         ? static_cast<number_float_t>(-val)
+                                         : static_cast<number_float_t>(val), "");
+            }
+
+            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
+            {
+                float number{};
+                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
+            {
+                double number{};
+                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            default: // anything else (0xFF is handled inside the other types)
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                        exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a CBOR string
+
+    This function first reads starting bytes to determine the expected
+    string length and then copies this number of bytes into a string.
+    Additionally, CBOR's strings with indefinite lengths are supported.
+
+    @param[out] result  created string
+
+    @return whether string creation completed
+    */
+    bool get_cbor_string(string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            {
+                return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7F: // UTF-8 string (indefinite length)
+            {
+                while (get() != 0xFF)
+                {
+                    string_t chunk;
+                    if (!get_cbor_string(chunk))
+                    {
+                        return false;
+                    }
+                    result.append(chunk);
+                }
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+                                        exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a CBOR byte array
+
+    This function first reads starting bytes to determine the expected
+    byte array length and then copies this number of bytes into the byte array.
+    Additionally, CBOR's byte arrays with indefinite lengths are supported.
+
+    @param[out] result  created byte array
+
+    @return whether byte array creation completed
+    */
+    bool get_cbor_binary(binary_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // Binary data (0x00..0x17 bytes follow)
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            {
+                return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0x58: // Binary data (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x59: // Binary data (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x5A: // Binary data (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x5F: // Binary data (indefinite length)
+            {
+                while (get() != 0xFF)
+                {
+                    binary_t chunk;
+                    if (!get_cbor_binary(chunk))
+                    {
+                        return false;
+                    }
+                    result.insert(result.end(), chunk.begin(), chunk.end());
+                }
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+                                        exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
+            }
+        }
+    }
+
+    /*!
+    @param[in] len  the length of the array or static_cast<std::size_t>(-1) for an
+                    array of indefinite size
+    @param[in] tag_handler how CBOR tags should be treated
+    @return whether array creation completed
+    */
+    bool get_cbor_array(const std::size_t len,
+                        const cbor_tag_handler_t tag_handler)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
+        {
+            return false;
+        }
+
+        if (len != static_cast<std::size_t>(-1))
+        {
+            for (std::size_t i = 0; i < len; ++i)
+            {
+                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+                {
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            while (get() != 0xFF)
+            {
+                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
+                {
+                    return false;
+                }
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @param[in] len  the length of the object or static_cast<std::size_t>(-1) for an
+                    object of indefinite size
+    @param[in] tag_handler how CBOR tags should be treated
+    @return whether object creation completed
+    */
+    bool get_cbor_object(const std::size_t len,
+                         const cbor_tag_handler_t tag_handler)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
+        {
+            return false;
+        }
+
+        if (len != 0)
+        {
+            string_t key;
+            if (len != static_cast<std::size_t>(-1))
+            {
+                for (std::size_t i = 0; i < len; ++i)
+                {
+                    get();
+                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+
+                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+            else
+            {
+                while (get() != 0xFF)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+
+                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+        }
+
+        return sax->end_object();
+    }
+
+    /////////////
+    // MsgPack //
+    /////////////
+
+    /*!
+    @return whether a valid MessagePack value was passed to the SAX parser
+    */
+    bool parse_msgpack_internal()
+    {
+        switch (get())
+        {
+            // EOF
+            case std::char_traits<char_type>::eof():
+                return unexpect_eof(input_format_t::msgpack, "value");
+
+            // positive fixint
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0A:
+            case 0x0B:
+            case 0x0C:
+            case 0x0D:
+            case 0x0E:
+            case 0x0F:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+            case 0x18:
+            case 0x19:
+            case 0x1A:
+            case 0x1B:
+            case 0x1C:
+            case 0x1D:
+            case 0x1E:
+            case 0x1F:
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2A:
+            case 0x2B:
+            case 0x2C:
+            case 0x2D:
+            case 0x2E:
+            case 0x2F:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+            case 0x38:
+            case 0x39:
+            case 0x3A:
+            case 0x3B:
+            case 0x3C:
+            case 0x3D:
+            case 0x3E:
+            case 0x3F:
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            case 0x58:
+            case 0x59:
+            case 0x5A:
+            case 0x5B:
+            case 0x5C:
+            case 0x5D:
+            case 0x5E:
+            case 0x5F:
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            case 0x78:
+            case 0x79:
+            case 0x7A:
+            case 0x7B:
+            case 0x7C:
+            case 0x7D:
+            case 0x7E:
+            case 0x7F:
+                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+            // fixmap
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8A:
+            case 0x8B:
+            case 0x8C:
+            case 0x8D:
+            case 0x8E:
+            case 0x8F:
+                return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+            // fixarray
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+            case 0x98:
+            case 0x99:
+            case 0x9A:
+            case 0x9B:
+            case 0x9C:
+            case 0x9D:
+            case 0x9E:
+            case 0x9F:
+                return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+            // fixstr
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+            case 0xB8:
+            case 0xB9:
+            case 0xBA:
+            case 0xBB:
+            case 0xBC:
+            case 0xBD:
+            case 0xBE:
+            case 0xBF:
+            case 0xD9: // str 8
+            case 0xDA: // str 16
+            case 0xDB: // str 32
+            {
+                string_t s;
+                return get_msgpack_string(s) && sax->string(s);
+            }
+
+            case 0xC0: // nil
+                return sax->null();
+
+            case 0xC2: // false
+                return sax->boolean(false);
+
+            case 0xC3: // true
+                return sax->boolean(true);
+
+            case 0xC4: // bin 8
+            case 0xC5: // bin 16
+            case 0xC6: // bin 32
+            case 0xC7: // ext 8
+            case 0xC8: // ext 16
+            case 0xC9: // ext 32
+            case 0xD4: // fixext 1
+            case 0xD5: // fixext 2
+            case 0xD6: // fixext 4
+            case 0xD7: // fixext 8
+            case 0xD8: // fixext 16
+            {
+                binary_t b;
+                return get_msgpack_binary(b) && sax->binary(b);
+            }
+
+            case 0xCA: // float 32
+            {
+                float number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xCB: // float 64
+            {
+                double number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xCC: // uint 8
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xCD: // uint 16
+            {
+                std::uint16_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xCE: // uint 32
+            {
+                std::uint32_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xCF: // uint 64
+            {
+                std::uint64_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xD0: // int 8
+            {
+                std::int8_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xD1: // int 16
+            {
+                std::int16_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xD2: // int 32
+            {
+                std::int32_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xD3: // int 64
+            {
+                std::int64_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xDC: // array 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
+            }
+
+            case 0xDD: // array 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
+            }
+
+            case 0xDE: // map 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xDF: // map 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
+            }
+
+            // negative fixint
+            case 0xE0:
+            case 0xE1:
+            case 0xE2:
+            case 0xE3:
+            case 0xE4:
+            case 0xE5:
+            case 0xE6:
+            case 0xE7:
+            case 0xE8:
+            case 0xE9:
+            case 0xEA:
+            case 0xEB:
+            case 0xEC:
+            case 0xED:
+            case 0xEE:
+            case 0xEF:
+            case 0xF0:
+            case 0xF1:
+            case 0xF2:
+            case 0xF3:
+            case 0xF4:
+            case 0xF5:
+            case 0xF6:
+            case 0xF7:
+            case 0xF8:
+            case 0xF9:
+            case 0xFA:
+            case 0xFB:
+            case 0xFC:
+            case 0xFD:
+            case 0xFE:
+            case 0xFF:
+                return sax->number_integer(static_cast<std::int8_t>(current));
+
+            default: // anything else
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                        exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a MessagePack string
+
+    This function first reads starting bytes to determine the expected
+    string length and then copies this number of bytes into a string.
+
+    @param[out] result  created string
+
+    @return whether string creation completed
+    */
+    bool get_msgpack_string(string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // fixstr
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+            case 0xB8:
+            case 0xB9:
+            case 0xBA:
+            case 0xBB:
+            case 0xBC:
+            case 0xBD:
+            case 0xBE:
+            case 0xBF:
+            {
+                return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0xD9: // str 8
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+            }
+
+            case 0xDA: // str 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+            }
+
+            case 0xDB: // str 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+                                        exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a MessagePack byte array
+
+    This function first reads starting bytes to determine the expected
+    byte array length and then copies this number of bytes into a byte array.
+
+    @param[out] result  created byte array
+
+    @return whether byte array creation completed
+    */
+    bool get_msgpack_binary(binary_t& result)
+    {
+        // helper function to set the subtype
+        auto assign_and_return_true = [&result](std::int8_t subtype)
+        {
+            result.set_subtype(static_cast<std::uint8_t>(subtype));
+            return true;
+        };
+
+        switch (current)
+        {
+            case 0xC4: // bin 8
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_binary(input_format_t::msgpack, len, result);
+            }
+
+            case 0xC5: // bin 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_binary(input_format_t::msgpack, len, result);
+            }
+
+            case 0xC6: // bin 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_binary(input_format_t::msgpack, len, result);
+            }
+
+            case 0xC7: // ext 8
+            {
+                std::uint8_t len{};
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, len, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xC8: // ext 16
+            {
+                std::uint16_t len{};
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, len, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xC9: // ext 32
+            {
+                std::uint32_t len{};
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, len, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD4: // fixext 1
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 1, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD5: // fixext 2
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 2, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD6: // fixext 4
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 4, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD7: // fixext 8
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 8, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD8: // fixext 16
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 16, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            default:           // LCOV_EXCL_LINE
+                return false;  // LCOV_EXCL_LINE
+        }
+    }
+
+    /*!
+    @param[in] len  the length of the array
+    @return whether array creation completed
+    */
+    bool get_msgpack_array(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
+        {
+            return false;
+        }
+
+        for (std::size_t i = 0; i < len; ++i)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
+            {
+                return false;
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @param[in] len  the length of the object
+    @return whether object creation completed
+    */
+    bool get_msgpack_object(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
+        {
+            return false;
+        }
+
+        string_t key;
+        for (std::size_t i = 0; i < len; ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
+            {
+                return false;
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
+            {
+                return false;
+            }
+            key.clear();
+        }
+
+        return sax->end_object();
+    }
+
+    ////////////
+    // UBJSON //
+    ////////////
+
+    /*!
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether a valid UBJSON value was passed to the SAX parser
+    */
+    bool parse_ubjson_internal(const bool get_char = true)
+    {
+        return get_ubjson_value(get_char ? get_ignore_noop() : current);
+    }
+
+    /*!
+    @brief reads a UBJSON string
+
+    This function is either called after reading the 'S' byte explicitly
+    indicating a string, or in case of an object key where the 'S' byte can be
+    left out.
+
+    @param[out] result   created string
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether string creation completed
+    */
+    bool get_ubjson_string(string_t& result, const bool get_char = true)
+    {
+        if (get_char)
+        {
+            get();  // TODO(niels): may we ignore N here?
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            case 'U':
+            {
+                std::uint8_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'i':
+            {
+                std::int8_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'I':
+            {
+                std::int16_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'l':
+            {
+                std::int32_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'L':
+            {
+                std::int64_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'u':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint16_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'm':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint32_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            case 'M':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint64_t len{};
+                return get_number(input_format, len) && get_string(input_format, len, result);
+            }
+
+            default:
+                break;
+        }
+        auto last_token = get_token_string();
+        std::string message;
+
+        if (input_format != input_format_t::bjdata)
+        {
+            message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
+        }
+        else
+        {
+            message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
+        }
+        return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
+    }
+
+    /*!
+    @param[out] dim  an integer vector storing the ND array dimensions
+    @return whether reading ND array size vector is successful
+    */
+    bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
+    {
+        std::pair<std::size_t, char_int_type> size_and_type;
+        size_t dimlen = 0;
+        bool no_ndarray = true;
+
+        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
+        {
+            return false;
+        }
+
+        if (size_and_type.first != npos)
+        {
+            if (size_and_type.second != 0)
+            {
+                if (size_and_type.second != 'N')
+                {
+                    for (std::size_t i = 0; i < size_and_type.first; ++i)
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
+                        {
+                            return false;
+                        }
+                        dim.push_back(dimlen);
+                    }
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
+                    {
+                        return false;
+                    }
+                    dim.push_back(dimlen);
+                }
+            }
+        }
+        else
+        {
+            while (current != ']')
+            {
+                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
+                {
+                    return false;
+                }
+                dim.push_back(dimlen);
+                get_ignore_noop();
+            }
+        }
+        return true;
+    }
+
+    /*!
+    @param[out] result  determined size
+    @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector
+                               or ndarray dimension is not allowed; `false` means ndarray
+                               is allowed; for output, `true` means an ndarray is found;
+                               is_ndarray can only return `true` when its initial value
+                               is `false`
+    @param[in] prefix  type marker if already read, otherwise set to 0
+
+    @return whether size determination completed
+    */
+    bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
+    {
+        if (prefix == 0)
+        {
+            prefix = get_ignore_noop();
+        }
+
+        switch (prefix)
+        {
+            case 'U':
+            {
+                std::uint8_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'i':
+            {
+                std::int8_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                if (number < 0)
+                {
+                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+                }
+                result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
+                return true;
+            }
+
+            case 'I':
+            {
+                std::int16_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                if (number < 0)
+                {
+                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'l':
+            {
+                std::int32_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                if (number < 0)
+                {
+                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'L':
+            {
+                std::int64_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                if (number < 0)
+                {
+                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+                }
+                if (!value_in_range_of<std::size_t>(number))
+                {
+                    return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
+                                            exception_message(input_format, "integer value overflow", "size"), nullptr));
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'u':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint16_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'm':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint32_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                result = conditional_static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'M':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint64_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+                {
+                    return false;
+                }
+                if (!value_in_range_of<std::size_t>(number))
+                {
+                    return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
+                                            exception_message(input_format, "integer value overflow", "size"), nullptr));
+                }
+                result = detail::conditional_static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case '[':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
+                {
+                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr));
+                }
+                std::vector<size_t> dim;
+                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
+                {
+                    return false;
+                }
+                if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
+                {
+                    result = dim.at(dim.size() - 1);
+                    return true;
+                }
+                if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
+                {
+                    for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
+                    {
+                        if ( i == 0 )
+                        {
+                            result = 0;
+                            return true;
+                        }
+                    }
+
+                    string_t key = "_ArraySize_";
+                    if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
+                    {
+                        return false;
+                    }
+                    result = 1;
+                    for (auto i : dim)
+                    {
+                        result *= i;
+                        if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
+                        {
+                            return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
+                        }
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
+                        {
+                            return false;
+                        }
+                    }
+                    is_ndarray = true;
+                    return sax->end_array();
+                }
+                result = 0;
+                return true;
+            }
+
+            default:
+                break;
+        }
+        auto last_token = get_token_string();
+        std::string message;
+
+        if (input_format != input_format_t::bjdata)
+        {
+            message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
+        }
+        else
+        {
+            message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
+        }
+        return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
+    }
+
+    /*!
+    @brief determine the type and size for a container
+
+    In the optimized UBJSON format, a type and a size can be provided to allow
+    for a more compact representation.
+
+    @param[out] result  pair of the size and the type
+    @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector
+
+    @return whether pair creation completed
+    */
+    bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
+    {
+        result.first = npos; // size
+        result.second = 0; // type
+        bool is_ndarray = false;
+
+        get_ignore_noop();
+
+        if (current == '$')
+        {
+            result.second = get();  // must not ignore 'N', because 'N' maybe the type
+            if (input_format == input_format_t::bjdata
+                    && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                        exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
+            {
+                return false;
+            }
+
+            get_ignore_noop();
+            if (JSON_HEDLEY_UNLIKELY(current != '#'))
+            {
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
+                {
+                    return false;
+                }
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                        exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
+            }
+
+            bool is_error = get_ubjson_size_value(result.first, is_ndarray);
+            if (input_format == input_format_t::bjdata && is_ndarray)
+            {
+                if (inside_ndarray)
+                {
+                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
+                                            exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
+                }
+                result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
+            }
+            return is_error;
+        }
+
+        if (current == '#')
+        {
+            bool is_error = get_ubjson_size_value(result.first, is_ndarray);
+            if (input_format == input_format_t::bjdata && is_ndarray)
+            {
+                return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
+                                        exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
+            }
+            return is_error;
+        }
+
+        return true;
+    }
+
+    /*!
+    @param prefix  the previously read or set type prefix
+    @return whether value creation completed
+    */
+    bool get_ubjson_value(const char_int_type prefix)
+    {
+        switch (prefix)
+        {
+            case std::char_traits<char_type>::eof():  // EOF
+                return unexpect_eof(input_format, "value");
+
+            case 'T':  // true
+                return sax->boolean(true);
+            case 'F':  // false
+                return sax->boolean(false);
+
+            case 'Z':  // null
+                return sax->null();
+
+            case 'U':
+            {
+                std::uint8_t number{};
+                return get_number(input_format, number) && sax->number_unsigned(number);
+            }
+
+            case 'i':
+            {
+                std::int8_t number{};
+                return get_number(input_format, number) && sax->number_integer(number);
+            }
+
+            case 'I':
+            {
+                std::int16_t number{};
+                return get_number(input_format, number) && sax->number_integer(number);
+            }
+
+            case 'l':
+            {
+                std::int32_t number{};
+                return get_number(input_format, number) && sax->number_integer(number);
+            }
+
+            case 'L':
+            {
+                std::int64_t number{};
+                return get_number(input_format, number) && sax->number_integer(number);
+            }
+
+            case 'u':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint16_t number{};
+                return get_number(input_format, number) && sax->number_unsigned(number);
+            }
+
+            case 'm':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint32_t number{};
+                return get_number(input_format, number) && sax->number_unsigned(number);
+            }
+
+            case 'M':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                std::uint64_t number{};
+                return get_number(input_format, number) && sax->number_unsigned(number);
+            }
+
+            case 'h':
+            {
+                if (input_format != input_format_t::bjdata)
+                {
+                    break;
+                }
+                const auto byte1_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
+                {
+                    return false;
+                }
+                const auto byte2_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
+                {
+                    return false;
+                }
+
+                const auto byte1 = static_cast<unsigned char>(byte1_raw);
+                const auto byte2 = static_cast<unsigned char>(byte2_raw);
+
+                // code from RFC 7049, Appendix D, Figure 3:
+                // As half-precision floating-point numbers were only added
+                // to IEEE 754 in 2008, today's programming platforms often
+                // still only have limited support for them. It is very
+                // easy to include at least decoding support for them even
+                // without such support. An example of a small decoder for
+                // half-precision floating-point numbers in the C language
+                // is shown in Fig. 3.
+                const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
+                const double val = [&half]
+                {
+                    const int exp = (half >> 10u) & 0x1Fu;
+                    const unsigned int mant = half & 0x3FFu;
+                    JSON_ASSERT(0 <= exp&& exp <= 32);
+                    JSON_ASSERT(mant <= 1024);
+                    switch (exp)
+                    {
+                        case 0:
+                            return std::ldexp(mant, -24);
+                        case 31:
+                            return (mant == 0)
+                            ? std::numeric_limits<double>::infinity()
+                            : std::numeric_limits<double>::quiet_NaN();
+                        default:
+                            return std::ldexp(mant + 1024, exp - 25);
+                    }
+                }();
+                return sax->number_float((half & 0x8000u) != 0
+                                         ? static_cast<number_float_t>(-val)
+                                         : static_cast<number_float_t>(val), "");
+            }
+
+            case 'd':
+            {
+                float number{};
+                return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 'D':
+            {
+                double number{};
+                return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 'H':
+            {
+                return get_ubjson_high_precision_number();
+            }
+
+            case 'C':  // char
+            {
+                get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
+                {
+                    return false;
+                }
+                if (JSON_HEDLEY_UNLIKELY(current > 127))
+                {
+                    auto last_token = get_token_string();
+                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+                                            exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
+                }
+                string_t s(1, static_cast<typename string_t::value_type>(current));
+                return sax->string(s);
+            }
+
+            case 'S':  // string
+            {
+                string_t s;
+                return get_ubjson_string(s) && sax->string(s);
+            }
+
+            case '[':  // array
+                return get_ubjson_array();
+
+            case '{':  // object
+                return get_ubjson_object();
+
+            default: // anything else
+                break;
+        }
+        auto last_token = get_token_string();
+        return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
+    }
+
+    /*!
+    @return whether array creation completed
+    */
+    bool get_ubjson_array()
+    {
+        std::pair<std::size_t, char_int_type> size_and_type;
+        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
+        {
+            return false;
+        }
+
+        // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
+        // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
+
+        if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
+        {
+            size_and_type.second &= ~(static_cast<char_int_type>(1) << 8);  // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
+            auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
+            {
+                return p.first < t;
+            });
+            string_t key = "_ArrayType_";
+            if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                        exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
+            }
+
+            string_t type = it->second; // sax->string() takes a reference
+            if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second == 'C')
+            {
+                size_and_type.second = 'U';
+            }
+
+            key = "_ArrayData_";
+            if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
+            {
+                return false;
+            }
+
+            for (std::size_t i = 0; i < size_and_type.first; ++i)
+            {
+                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+                {
+                    return false;
+                }
+            }
+
+            return (sax->end_array() && sax->end_object());
+        }
+
+        if (size_and_type.first != npos)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second != 0)
+            {
+                if (size_and_type.second != 'N')
+                {
+                    for (std::size_t i = 0; i < size_and_type.first; ++i)
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+                        {
+                            return false;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+                    {
+                        return false;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
+            {
+                return false;
+            }
+
+            while (current != ']')
+            {
+                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
+                {
+                    return false;
+                }
+                get_ignore_noop();
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @return whether object creation completed
+    */
+    bool get_ubjson_object()
+    {
+        std::pair<std::size_t, char_int_type> size_and_type;
+        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
+        {
+            return false;
+        }
+
+        // do not accept ND-array size in objects in BJData
+        if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
+        {
+            auto last_token = get_token_string();
+            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+                                    exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
+        }
+
+        string_t key;
+        if (size_and_type.first != npos)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second != 0)
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+        }
+        else
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
+            {
+                return false;
+            }
+
+            while (current != '}')
+            {
+                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
+                {
+                    return false;
+                }
+                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+                {
+                    return false;
+                }
+                get_ignore_noop();
+                key.clear();
+            }
+        }
+
+        return sax->end_object();
+    }
+
+    // Note, no reader for UBJSON binary types is implemented because they do
+    // not exist
+
+    bool get_ubjson_high_precision_number()
+    {
+        // get size of following number string
+        std::size_t size{};
+        bool no_ndarray = true;
+        auto res = get_ubjson_size_value(size, no_ndarray);
+        if (JSON_HEDLEY_UNLIKELY(!res))
+        {
+            return res;
+        }
+
+        // get number string
+        std::vector<char> number_vector;
+        for (std::size_t i = 0; i < size; ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
+            {
+                return false;
+            }
+            number_vector.push_back(static_cast<char>(current));
+        }
+
+        // parse number string
+        using ia_type = decltype(detail::input_adapter(number_vector));
+        auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
+        const auto result_number = number_lexer.scan();
+        const auto number_string = number_lexer.get_token_string();
+        const auto result_remainder = number_lexer.scan();
+
+        using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
+
+        if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
+        {
+            return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
+                                    exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
+        }
+
+        switch (result_number)
+        {
+            case token_type::value_integer:
+                return sax->number_integer(number_lexer.get_number_integer());
+            case token_type::value_unsigned:
+                return sax->number_unsigned(number_lexer.get_number_unsigned());
+            case token_type::value_float:
+                return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
+            case token_type::uninitialized:
+            case token_type::literal_true:
+            case token_type::literal_false:
+            case token_type::literal_null:
+            case token_type::value_string:
+            case token_type::begin_array:
+            case token_type::begin_object:
+            case token_type::end_array:
+            case token_type::end_object:
+            case token_type::name_separator:
+            case token_type::value_separator:
+            case token_type::parse_error:
+            case token_type::end_of_input:
+            case token_type::literal_or_value:
+            default:
+                return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
+                                        exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
+        }
+    }
+
+    ///////////////////////
+    // Utility functions //
+    ///////////////////////
+
+    /*!
+    @brief get next character from the input
+
+    This function provides the interface to the used input adapter. It does
+    not throw in case the input reached EOF, but returns a -'ve valued
+    `std::char_traits<char_type>::eof()` in that case.
+
+    @return character read from the input
+    */
+    char_int_type get()
+    {
+        ++chars_read;
+        return current = ia.get_character();
+    }
+
+    /*!
+    @return character read from the input after ignoring all 'N' entries
+    */
+    char_int_type get_ignore_noop()
+    {
+        do
+        {
+            get();
+        }
+        while (current == 'N');
+
+        return current;
+    }
+
+    /*
+    @brief read a number from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format   the current format (for diagnostics)
+    @param[out] result  number of type @a NumberType
+
+    @return whether conversion completed
+
+    @note This function needs to respect the system's endianness, because
+          bytes in CBOR, MessagePack, and UBJSON are stored in network order
+          (big endian) and therefore need reordering on little endian systems.
+          On the other hand, BSON and BJData use little endian and should reorder
+          on big endian systems.
+    */
+    template<typename NumberType, bool InputIsLittleEndian = false>
+    bool get_number(const input_format_t format, NumberType& result)
+    {
+        // step 1: read input into array with system's byte order
+        std::array<std::uint8_t, sizeof(NumberType)> vec{};
+        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
+            {
+                return false;
+            }
+
+            // reverse byte order prior to conversion if necessary
+            if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
+            {
+                vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
+            }
+            else
+            {
+                vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
+            }
+        }
+
+        // step 2: convert array into number of type T and return
+        std::memcpy(&result, vec.data(), sizeof(NumberType));
+        return true;
+    }
+
+    /*!
+    @brief create a string by reading characters from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format the current format (for diagnostics)
+    @param[in] len number of characters to read
+    @param[out] result string created by reading @a len bytes
+
+    @return whether string creation completed
+
+    @note We can not reserve @a len bytes for the result, because @a len
+          may be too large. Usually, @ref unexpect_eof() detects the end of
+          the input before we run out of string memory.
+    */
+    template<typename NumberType>
+    bool get_string(const input_format_t format,
+                    const NumberType len,
+                    string_t& result)
+    {
+        bool success = true;
+        for (NumberType i = 0; i < len; i++)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
+            {
+                success = false;
+                break;
+            }
+            result.push_back(static_cast<typename string_t::value_type>(current));
+        }
+        return success;
+    }
+
+    /*!
+    @brief create a byte array by reading bytes from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format the current format (for diagnostics)
+    @param[in] len number of bytes to read
+    @param[out] result byte array created by reading @a len bytes
+
+    @return whether byte array creation completed
+
+    @note We can not reserve @a len bytes for the result, because @a len
+          may be too large. Usually, @ref unexpect_eof() detects the end of
+          the input before we run out of memory.
+    */
+    template<typename NumberType>
+    bool get_binary(const input_format_t format,
+                    const NumberType len,
+                    binary_t& result)
+    {
+        bool success = true;
+        for (NumberType i = 0; i < len; i++)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
+            {
+                success = false;
+                break;
+            }
+            result.push_back(static_cast<std::uint8_t>(current));
+        }
+        return success;
+    }
+
+    /*!
+    @param[in] format   the current format (for diagnostics)
+    @param[in] context  further context information (for diagnostics)
+    @return whether the last read character is not EOF
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    bool unexpect_eof(const input_format_t format, const char* context) const
+    {
+        if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
+        {
+            return sax->parse_error(chars_read, "<end of file>",
+                                    parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
+        }
+        return true;
+    }
+
+    /*!
+    @return a string representation of the last read byte
+    */
+    std::string get_token_string() const
+    {
+        std::array<char, 3> cr{{}};
+        static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+        return std::string{cr.data()};
+    }
+
+    /*!
+    @param[in] format   the current format
+    @param[in] detail   a detailed error message
+    @param[in] context  further context information
+    @return a message string to use in the parse_error exceptions
+    */
+    std::string exception_message(const input_format_t format,
+                                  const std::string& detail,
+                                  const std::string& context) const
+    {
+        std::string error_msg = "syntax error while parsing ";
+
+        switch (format)
+        {
+            case input_format_t::cbor:
+                error_msg += "CBOR";
+                break;
+
+            case input_format_t::msgpack:
+                error_msg += "MessagePack";
+                break;
+
+            case input_format_t::ubjson:
+                error_msg += "UBJSON";
+                break;
+
+            case input_format_t::bson:
+                error_msg += "BSON";
+                break;
+
+            case input_format_t::bjdata:
+                error_msg += "BJData";
+                break;
+
+            case input_format_t::json: // LCOV_EXCL_LINE
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+
+        return concat(error_msg, ' ', context, ": ", detail);
+    }
+
+  private:
+    static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
+
+    /// input adapter
+    InputAdapterType ia;
+
+    /// the current character
+    char_int_type current = std::char_traits<char_type>::eof();
+
+    /// the number of characters read
+    std::size_t chars_read = 0;
+
+    /// whether we can assume little endianness
+    const bool is_little_endian = little_endianness();
+
+    /// input format
+    const input_format_t input_format = input_format_t::json;
+
+    /// the SAX parser
+    json_sax_t* sax = nullptr;
+
+    // excluded markers in bjdata optimized type
+#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
+    make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
+
+#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
+    make_array<bjd_type>(                      \
+    bjd_type{'C', "char"},                     \
+    bjd_type{'D', "double"},                   \
+    bjd_type{'I', "int16"},                    \
+    bjd_type{'L', "int64"},                    \
+    bjd_type{'M', "uint64"},                   \
+    bjd_type{'U', "uint8"},                    \
+    bjd_type{'d', "single"},                   \
+    bjd_type{'i', "int8"},                     \
+    bjd_type{'l', "int32"},                    \
+    bjd_type{'m', "uint32"},                   \
+    bjd_type{'u', "uint16"})
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    // lookup tables
+    // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
+    const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
+        JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
+
+    using bjd_type = std::pair<char_int_type, string_t>;
+    // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
+    const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
+        JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
+
+#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
+#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
+};
+
+#ifndef JSON_HAS_CPP_17
+    template<typename BasicJsonType, typename InputAdapterType, typename SAX>
+    constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
+#endif
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/input/parser.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cmath> // isfinite
+#include <cstdint> // uint8_t
+#include <functional> // function
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+////////////
+// parser //
+////////////
+
+enum class parse_event_t : std::uint8_t
+{
+    /// the parser read `{` and started to process a JSON object
+    object_start,
+    /// the parser read `}` and finished processing a JSON object
+    object_end,
+    /// the parser read `[` and started to process a JSON array
+    array_start,
+    /// the parser read `]` and finished processing a JSON array
+    array_end,
+    /// the parser read a key of a value in an object
+    key,
+    /// the parser finished reading a JSON value
+    value
+};
+
+template<typename BasicJsonType>
+using parser_callback_t =
+    std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
+
+/*!
+@brief syntax analysis
+
+This class implements a recursive descent parser.
+*/
+template<typename BasicJsonType, typename InputAdapterType>
+class parser
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
+    using token_type = typename lexer_t::token_type;
+
+  public:
+    /// a parser reading from an input adapter
+    explicit parser(InputAdapterType&& adapter,
+                    const parser_callback_t<BasicJsonType> cb = nullptr,
+                    const bool allow_exceptions_ = true,
+                    const bool skip_comments = false)
+        : callback(cb)
+        , m_lexer(std::move(adapter), skip_comments)
+        , allow_exceptions(allow_exceptions_)
+    {
+        // read first token
+        get_token();
+    }
+
+    /*!
+    @brief public parser interface
+
+    @param[in] strict      whether to expect the last token to be EOF
+    @param[in,out] result  parsed JSON value
+
+    @throw parse_error.101 in case of an unexpected token
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+    */
+    void parse(const bool strict, BasicJsonType& result)
+    {
+        if (callback)
+        {
+            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
+            sax_parse_internal(&sdp);
+
+            // in strict mode, input must be completely read
+            if (strict && (get_token() != token_type::end_of_input))
+            {
+                sdp.parse_error(m_lexer.get_position(),
+                                m_lexer.get_token_string(),
+                                parse_error::create(101, m_lexer.get_position(),
+                                                    exception_message(token_type::end_of_input, "value"), nullptr));
+            }
+
+            // in case of an error, return discarded value
+            if (sdp.is_errored())
+            {
+                result = value_t::discarded;
+                return;
+            }
+
+            // set top-level value to null if it was discarded by the callback
+            // function
+            if (result.is_discarded())
+            {
+                result = nullptr;
+            }
+        }
+        else
+        {
+            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
+            sax_parse_internal(&sdp);
+
+            // in strict mode, input must be completely read
+            if (strict && (get_token() != token_type::end_of_input))
+            {
+                sdp.parse_error(m_lexer.get_position(),
+                                m_lexer.get_token_string(),
+                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
+            }
+
+            // in case of an error, return discarded value
+            if (sdp.is_errored())
+            {
+                result = value_t::discarded;
+                return;
+            }
+        }
+
+        result.assert_invariant();
+    }
+
+    /*!
+    @brief public accept interface
+
+    @param[in] strict  whether to expect the last token to be EOF
+    @return whether the input is a proper JSON text
+    */
+    bool accept(const bool strict = true)
+    {
+        json_sax_acceptor<BasicJsonType> sax_acceptor;
+        return sax_parse(&sax_acceptor, strict);
+    }
+
+    template<typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    bool sax_parse(SAX* sax, const bool strict = true)
+    {
+        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+        const bool result = sax_parse_internal(sax);
+
+        // strict mode: next byte must be EOF
+        if (result && strict && (get_token() != token_type::end_of_input))
+        {
+            return sax->parse_error(m_lexer.get_position(),
+                                    m_lexer.get_token_string(),
+                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
+        }
+
+        return result;
+    }
+
+  private:
+    template<typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    bool sax_parse_internal(SAX* sax)
+    {
+        // stack to remember the hierarchy of structured values we are parsing
+        // true = array; false = object
+        std::vector<bool> states;
+        // value to avoid a goto (see comment where set to true)
+        bool skip_to_state_evaluation = false;
+
+        while (true)
+        {
+            if (!skip_to_state_evaluation)
+            {
+                // invariant: get_token() was called before each iteration
+                switch (last_token)
+                {
+                    case token_type::begin_object:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
+                        {
+                            return false;
+                        }
+
+                        // closing } -> we are done
+                        if (get_token() == token_type::end_object)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
+                            {
+                                return false;
+                            }
+                            break;
+                        }
+
+                        // parse key
+                        if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
+                        }
+                        if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+
+                        // parse separator (:)
+                        if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
+                        }
+
+                        // remember we are now inside an object
+                        states.push_back(false);
+
+                        // parse values
+                        get_token();
+                        continue;
+                    }
+
+                    case token_type::begin_array:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
+                        {
+                            return false;
+                        }
+
+                        // closing ] -> we are done
+                        if (get_token() == token_type::end_array)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
+                            {
+                                return false;
+                            }
+                            break;
+                        }
+
+                        // remember we are now inside an array
+                        states.push_back(true);
+
+                        // parse values (no need to call get_token)
+                        continue;
+                    }
+
+                    case token_type::value_float:
+                    {
+                        const auto res = m_lexer.get_number_float();
+
+                        if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
+                        }
+
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+
+                        break;
+                    }
+
+                    case token_type::literal_false:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::literal_null:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->null()))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::literal_true:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_integer:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_string:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_unsigned:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::parse_error:
+                    {
+                        // using "uninitialized" to avoid "expected" message
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
+                    }
+
+                    case token_type::uninitialized:
+                    case token_type::end_array:
+                    case token_type::end_object:
+                    case token_type::name_separator:
+                    case token_type::value_separator:
+                    case token_type::end_of_input:
+                    case token_type::literal_or_value:
+                    default: // the last token was unexpected
+                    {
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
+                    }
+                }
+            }
+            else
+            {
+                skip_to_state_evaluation = false;
+            }
+
+            // we reached this line after we successfully parsed a value
+            if (states.empty())
+            {
+                // empty stack: we reached the end of the hierarchy: done
+                return true;
+            }
+
+            if (states.back())  // array
+            {
+                // comma -> next value
+                if (get_token() == token_type::value_separator)
+                {
+                    // parse a new value
+                    get_token();
+                    continue;
+                }
+
+                // closing ]
+                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
+                    {
+                        return false;
+                    }
+
+                    // We are done with this array. Before we can parse a
+                    // new value, we need to evaluate the new state first.
+                    // By setting skip_to_state_evaluation to false, we
+                    // are effectively jumping to the beginning of this if.
+                    JSON_ASSERT(!states.empty());
+                    states.pop_back();
+                    skip_to_state_evaluation = true;
+                    continue;
+                }
+
+                return sax->parse_error(m_lexer.get_position(),
+                                        m_lexer.get_token_string(),
+                                        parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
+            }
+
+            // states.back() is false -> object
+
+            // comma -> next value
+            if (get_token() == token_type::value_separator)
+            {
+                // parse key
+                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
+                {
+                    return sax->parse_error(m_lexer.get_position(),
+                                            m_lexer.get_token_string(),
+                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
+                }
+
+                if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
+                {
+                    return false;
+                }
+
+                // parse separator (:)
+                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+                {
+                    return sax->parse_error(m_lexer.get_position(),
+                                            m_lexer.get_token_string(),
+                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
+                }
+
+                // parse values
+                get_token();
+                continue;
+            }
+
+            // closing }
+            if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
+            {
+                if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
+                {
+                    return false;
+                }
+
+                // We are done with this object. Before we can parse a
+                // new value, we need to evaluate the new state first.
+                // By setting skip_to_state_evaluation to false, we
+                // are effectively jumping to the beginning of this if.
+                JSON_ASSERT(!states.empty());
+                states.pop_back();
+                skip_to_state_evaluation = true;
+                continue;
+            }
+
+            return sax->parse_error(m_lexer.get_position(),
+                                    m_lexer.get_token_string(),
+                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
+        }
+    }
+
+    /// get next token from lexer
+    token_type get_token()
+    {
+        return last_token = m_lexer.scan();
+    }
+
+    std::string exception_message(const token_type expected, const std::string& context)
+    {
+        std::string error_msg = "syntax error ";
+
+        if (!context.empty())
+        {
+            error_msg += concat("while parsing ", context, ' ');
+        }
+
+        error_msg += "- ";
+
+        if (last_token == token_type::parse_error)
+        {
+            error_msg += concat(m_lexer.get_error_message(), "; last read: '",
+                                m_lexer.get_token_string(), '\'');
+        }
+        else
+        {
+            error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
+        }
+
+        if (expected != token_type::uninitialized)
+        {
+            error_msg += concat("; expected ", lexer_t::token_type_name(expected));
+        }
+
+        return error_msg;
+    }
+
+  private:
+    /// callback function
+    const parser_callback_t<BasicJsonType> callback = nullptr;
+    /// the type of the last read token
+    token_type last_token = token_type::uninitialized;
+    /// the lexer
+    lexer_t m_lexer;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstddef> // ptrdiff_t
+#include <limits>  // numeric_limits
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/*
+@brief an iterator for primitive JSON types
+
+This class models an iterator for primitive JSON types (boolean, number,
+string). It's only purpose is to allow the iterator/const_iterator classes
+to "iterate" over primitive values. Internally, the iterator is modeled by
+a `difference_type` variable. Value begin_value (`0`) models the begin,
+end_value (`1`) models past the end.
+*/
+class primitive_iterator_t
+{
+  private:
+    using difference_type = std::ptrdiff_t;
+    static constexpr difference_type begin_value = 0;
+    static constexpr difference_type end_value = begin_value + 1;
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /// iterator as signed integer type
+    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
+
+  public:
+    constexpr difference_type get_value() const noexcept
+    {
+        return m_it;
+    }
+
+    /// set iterator to a defined beginning
+    void set_begin() noexcept
+    {
+        m_it = begin_value;
+    }
+
+    /// set iterator to a defined past the end
+    void set_end() noexcept
+    {
+        m_it = end_value;
+    }
+
+    /// return whether the iterator can be dereferenced
+    constexpr bool is_begin() const noexcept
+    {
+        return m_it == begin_value;
+    }
+
+    /// return whether the iterator is at end
+    constexpr bool is_end() const noexcept
+    {
+        return m_it == end_value;
+    }
+
+    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it == rhs.m_it;
+    }
+
+    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it < rhs.m_it;
+    }
+
+    primitive_iterator_t operator+(difference_type n) noexcept
+    {
+        auto result = *this;
+        result += n;
+        return result;
+    }
+
+    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it - rhs.m_it;
+    }
+
+    primitive_iterator_t& operator++() noexcept
+    {
+        ++m_it;
+        return *this;
+    }
+
+    primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
+    {
+        auto result = *this;
+        ++m_it;
+        return result;
+    }
+
+    primitive_iterator_t& operator--() noexcept
+    {
+        --m_it;
+        return *this;
+    }
+
+    primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
+    {
+        auto result = *this;
+        --m_it;
+        return result;
+    }
+
+    primitive_iterator_t& operator+=(difference_type n) noexcept
+    {
+        m_it += n;
+        return *this;
+    }
+
+    primitive_iterator_t& operator-=(difference_type n) noexcept
+    {
+        m_it -= n;
+        return *this;
+    }
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/*!
+@brief an iterator value
+
+@note This structure could easily be a union, but MSVC currently does not allow
+unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
+*/
+template<typename BasicJsonType> struct internal_iterator
+{
+    /// iterator for JSON objects
+    typename BasicJsonType::object_t::iterator object_iterator {};
+    /// iterator for JSON arrays
+    typename BasicJsonType::array_t::iterator array_iterator {};
+    /// generic iterator for all other types
+    primitive_iterator_t primitive_iterator {};
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/iterators/iter_impl.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
+#include <type_traits> // conditional, is_const, remove_const
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+// forward declare, to be able to friend it later on
+template<typename IteratorType> class iteration_proxy;
+template<typename IteratorType> class iteration_proxy_value;
+
+/*!
+@brief a template for a bidirectional iterator for the @ref basic_json class
+This class implements a both iterators (iterator and const_iterator) for the
+@ref basic_json class.
+@note An iterator is called *initialized* when a pointer to a JSON value has
+      been set (e.g., by a constructor or a copy assignment). If the iterator is
+      default-constructed, it is *uninitialized* and most methods are undefined.
+      **The library uses assertions to detect calls on uninitialized iterators.**
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+  The iterator that can be moved can be moved in both directions (i.e.
+  incremented and decremented).
+@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
+       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
+*/
+template<typename BasicJsonType>
+class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+{
+    /// the iterator with BasicJsonType of different const-ness
+    using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
+    /// allow basic_json to access private members
+    friend other_iter_impl;
+    friend BasicJsonType;
+    friend iteration_proxy<iter_impl>;
+    friend iteration_proxy_value<iter_impl>;
+
+    using object_t = typename BasicJsonType::object_t;
+    using array_t = typename BasicJsonType::array_t;
+    // make sure BasicJsonType is basic_json or const basic_json
+    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
+                  "iter_impl only accepts (const) basic_json");
+    // superficial check for the LegacyBidirectionalIterator named requirement
+    static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
+                  &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
+                  "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
+
+  public:
+    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
+    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
+    /// A user-defined iterator should provide publicly accessible typedefs named
+    /// iterator_category, value_type, difference_type, pointer, and reference.
+    /// Note that value_type is required to be non-const, even for constant iterators.
+    using iterator_category = std::bidirectional_iterator_tag;
+
+    /// the type of the values when the iterator is dereferenced
+    using value_type = typename BasicJsonType::value_type;
+    /// a type to represent differences between iterators
+    using difference_type = typename BasicJsonType::difference_type;
+    /// defines a pointer to the type iterated over (value_type)
+    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
+          typename BasicJsonType::const_pointer,
+          typename BasicJsonType::pointer>::type;
+    /// defines a reference to the type iterated over (value_type)
+    using reference =
+        typename std::conditional<std::is_const<BasicJsonType>::value,
+        typename BasicJsonType::const_reference,
+        typename BasicJsonType::reference>::type;
+
+    iter_impl() = default;
+    ~iter_impl() = default;
+    iter_impl(iter_impl&&) noexcept = default;
+    iter_impl& operator=(iter_impl&&) noexcept = default;
+
+    /*!
+    @brief constructor for a given JSON instance
+    @param[in] object  pointer to a JSON object for this iterator
+    @pre object != nullptr
+    @post The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    explicit iter_impl(pointer object) noexcept : m_object(object)
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = typename object_t::iterator();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = typename array_t::iterator();
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator = primitive_iterator_t();
+                break;
+            }
+        }
+    }
+
+    /*!
+    @note The conventional copy constructor and copy assignment are implicitly
+          defined. Combined with the following converting constructor and
+          assignment, they support: (1) copy from iterator to iterator, (2)
+          copy from const iterator to const iterator, and (3) conversion from
+          iterator to const iterator. However conversion from const iterator
+          to iterator is not defined.
+    */
+
+    /*!
+    @brief const copy constructor
+    @param[in] other const iterator to copy from
+    @note This copy constructor had to be defined explicitly to circumvent a bug
+          occurring on msvc v19.0 compiler (VS 2015) debug build. For more
+          information refer to: https://github.com/nlohmann/json/issues/1608
+    */
+    iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
+        : m_object(other.m_object), m_it(other.m_it)
+    {}
+
+    /*!
+    @brief converting assignment
+    @param[in] other const iterator to copy from
+    @return const/non-const iterator
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
+    {
+        if (&other != this)
+        {
+            m_object = other.m_object;
+            m_it = other.m_it;
+        }
+        return *this;
+    }
+
+    /*!
+    @brief converting constructor
+    @param[in] other  non-const iterator to copy from
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+        : m_object(other.m_object), m_it(other.m_it)
+    {}
+
+    /*!
+    @brief converting assignment
+    @param[in] other  non-const iterator to copy from
+    @return const/non-const iterator
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
+    {
+        m_object = other.m_object;
+        m_it = other.m_it;
+        return *this;
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /*!
+    @brief set the iterator to the first value
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    void set_begin() noexcept
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = m_object->m_value.object->begin();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = m_object->m_value.array->begin();
+                break;
+            }
+
+            case value_t::null:
+            {
+                // set to end so begin()==end() is true: null is empty
+                m_it.primitive_iterator.set_end();
+                break;
+            }
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator.set_begin();
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief set the iterator past the last value
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    void set_end() noexcept
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = m_object->m_value.object->end();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = m_object->m_value.array->end();
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator.set_end();
+                break;
+            }
+        }
+    }
+
+  public:
+    /*!
+    @brief return a reference to the value pointed to by the iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference operator*() const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
+                return m_it.object_iterator->second;
+            }
+
+            case value_t::array:
+            {
+                JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
+                return *m_it.array_iterator;
+            }
+
+            case value_t::null:
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+                {
+                    return *m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
+            }
+        }
+    }
+
+    /*!
+    @brief dereference the iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    pointer operator->() const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
+                return &(m_it.object_iterator->second);
+            }
+
+            case value_t::array:
+            {
+                JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
+                return &*m_it.array_iterator;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+                {
+                    return m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
+            }
+        }
+    }
+
+    /*!
+    @brief post-increment (it++)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
+    {
+        auto result = *this;
+        ++(*this);
+        return result;
+    }
+
+    /*!
+    @brief pre-increment (++it)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator++()
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                std::advance(m_it.object_iterator, 1);
+                break;
+            }
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, 1);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                ++m_it.primitive_iterator;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief post-decrement (it--)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
+    {
+        auto result = *this;
+        --(*this);
+        return result;
+    }
+
+    /*!
+    @brief pre-decrement (--it)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator--()
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                std::advance(m_it.object_iterator, -1);
+                break;
+            }
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, -1);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                --m_it.primitive_iterator;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief comparison: equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
+    bool operator==(const IterImpl& other) const
+    {
+        // if objects are not the same, the comparison is undefined
+        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
+        }
+
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                return (m_it.object_iterator == other.m_it.object_iterator);
+
+            case value_t::array:
+                return (m_it.array_iterator == other.m_it.array_iterator);
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
+        }
+    }
+
+    /*!
+    @brief comparison: not equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
+    bool operator!=(const IterImpl& other) const
+    {
+        return !operator==(other);
+    }
+
+    /*!
+    @brief comparison: smaller
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator<(const iter_impl& other) const
+    {
+        // if objects are not the same, the comparison is undefined
+        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
+        }
+
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
+
+            case value_t::array:
+                return (m_it.array_iterator < other.m_it.array_iterator);
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
+        }
+    }
+
+    /*!
+    @brief comparison: less than or equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator<=(const iter_impl& other) const
+    {
+        return !other.operator < (*this);
+    }
+
+    /*!
+    @brief comparison: greater than
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator>(const iter_impl& other) const
+    {
+        return !operator<=(other);
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator>=(const iter_impl& other) const
+    {
+        return !operator<(other);
+    }
+
+    /*!
+    @brief add to iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator+=(difference_type i)
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, i);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator += i;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief subtract from iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator-=(difference_type i)
+    {
+        return operator+=(-i);
+    }
+
+    /*!
+    @brief add to iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator+(difference_type i) const
+    {
+        auto result = *this;
+        result += i;
+        return result;
+    }
+
+    /*!
+    @brief addition of distance and iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    friend iter_impl operator+(difference_type i, const iter_impl& it)
+    {
+        auto result = it;
+        result += i;
+        return result;
+    }
+
+    /*!
+    @brief subtract from iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator-(difference_type i) const
+    {
+        auto result = *this;
+        result -= i;
+        return result;
+    }
+
+    /*!
+    @brief return difference
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    difference_type operator-(const iter_impl& other) const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
+
+            case value_t::array:
+                return m_it.array_iterator - other.m_it.array_iterator;
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return m_it.primitive_iterator - other.m_it.primitive_iterator;
+        }
+    }
+
+    /*!
+    @brief access to successor
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference operator[](difference_type n) const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
+
+            case value_t::array:
+                return *std::next(m_it.array_iterator, n);
+
+            case value_t::null:
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
+                {
+                    return *m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
+            }
+        }
+    }
+
+    /*!
+    @brief return the key of an object iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    const typename object_t::key_type& key() const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        if (JSON_HEDLEY_LIKELY(m_object->is_object()))
+        {
+            return m_it.object_iterator->first;
+        }
+
+        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
+    }
+
+    /*!
+    @brief return the value of an iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference value() const
+    {
+        return operator*();
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /// associated JSON instance
+    pointer m_object = nullptr;
+    /// the actual iterator of the associated instance
+    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstddef> // ptrdiff_t
+#include <iterator> // reverse_iterator
+#include <utility> // declval
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+//////////////////////
+// reverse_iterator //
+//////////////////////
+
+/*!
+@brief a template for a reverse iterator class
+
+@tparam Base the base iterator type to reverse. Valid types are @ref
+iterator (to create @ref reverse_iterator) and @ref const_iterator (to
+create @ref const_reverse_iterator).
+
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+  The iterator that can be moved can be moved in both directions (i.e.
+  incremented and decremented).
+- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
+  It is possible to write to the pointed-to element (only if @a Base is
+  @ref iterator).
+
+@since version 1.0.0
+*/
+template<typename Base>
+class json_reverse_iterator : public std::reverse_iterator<Base>
+{
+  public:
+    using difference_type = std::ptrdiff_t;
+    /// shortcut to the reverse iterator adapter
+    using base_iterator = std::reverse_iterator<Base>;
+    /// the reference type for the pointed-to element
+    using reference = typename Base::reference;
+
+    /// create reverse iterator from iterator
+    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+        : base_iterator(it) {}
+
+    /// create reverse iterator from base class
+    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+
+    /// post-increment (it++)
+    json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
+    }
+
+    /// pre-increment (++it)
+    json_reverse_iterator& operator++()
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
+    }
+
+    /// post-decrement (it--)
+    json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
+    }
+
+    /// pre-decrement (--it)
+    json_reverse_iterator& operator--()
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
+    }
+
+    /// add to iterator
+    json_reverse_iterator& operator+=(difference_type i)
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
+    }
+
+    /// add to iterator
+    json_reverse_iterator operator+(difference_type i) const
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
+    }
+
+    /// subtract from iterator
+    json_reverse_iterator operator-(difference_type i) const
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
+    }
+
+    /// return difference
+    difference_type operator-(const json_reverse_iterator& other) const
+    {
+        return base_iterator(*this) - base_iterator(other);
+    }
+
+    /// access to successor
+    reference operator[](difference_type n) const
+    {
+        return *(this->operator+(n));
+    }
+
+    /// return the key of an object iterator
+    auto key() const -> decltype(std::declval<Base>().key())
+    {
+        auto it = --this->base();
+        return it.key();
+    }
+
+    /// return the value of an iterator
+    reference value() const
+    {
+        auto it = --this->base();
+        return it.operator * ();
+    }
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/json_pointer.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // all_of
+#include <cctype> // isdigit
+#include <cerrno> // errno, ERANGE
+#include <cstdlib> // strtoull
+#ifndef JSON_NO_IO
+    #include <iosfwd> // ostream
+#endif  // JSON_NO_IO
+#include <limits> // max
+#include <numeric> // accumulate
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
+/// @sa https://json.nlohmann.me/api/json_pointer/
+template<typename RefStringType>
+class json_pointer
+{
+    // allow basic_json to access private members
+    NLOHMANN_BASIC_JSON_TPL_DECLARATION
+    friend class basic_json;
+
+    template<typename>
+    friend class json_pointer;
+
+    template<typename T>
+    struct string_t_helper
+    {
+        using type = T;
+    };
+
+    NLOHMANN_BASIC_JSON_TPL_DECLARATION
+    struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
+    {
+        using type = StringType;
+    };
+
+  public:
+    // for backwards compatibility accept BasicJsonType
+    using string_t = typename string_t_helper<RefStringType>::type;
+
+    /// @brief create JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
+    explicit json_pointer(const string_t& s = "")
+        : reference_tokens(split(s))
+    {}
+
+    /// @brief return a string representation of the JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
+    string_t to_string() const
+    {
+        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
+                               string_t{},
+                               [](const string_t& a, const string_t& b)
+        {
+            return detail::concat(a, '/', detail::escape(b));
+        });
+    }
+
+    /// @brief return a string representation of the JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
+    operator string_t() const
+    {
+        return to_string();
+    }
+
+#ifndef JSON_NO_IO
+    /// @brief write string representation of the JSON pointer to stream
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
+    friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
+    {
+        o << ptr.to_string();
+        return o;
+    }
+#endif
+
+    /// @brief append another JSON pointer at the end of this JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
+    json_pointer& operator/=(const json_pointer& ptr)
+    {
+        reference_tokens.insert(reference_tokens.end(),
+                                ptr.reference_tokens.begin(),
+                                ptr.reference_tokens.end());
+        return *this;
+    }
+
+    /// @brief append an unescaped reference token at the end of this JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
+    json_pointer& operator/=(string_t token)
+    {
+        push_back(std::move(token));
+        return *this;
+    }
+
+    /// @brief append an array index at the end of this JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
+    json_pointer& operator/=(std::size_t array_idx)
+    {
+        return *this /= std::to_string(array_idx);
+    }
+
+    /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
+    friend json_pointer operator/(const json_pointer& lhs,
+                                  const json_pointer& rhs)
+    {
+        return json_pointer(lhs) /= rhs;
+    }
+
+    /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
+    friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
+    {
+        return json_pointer(lhs) /= std::move(token);
+    }
+
+    /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
+    friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
+    {
+        return json_pointer(lhs) /= array_idx;
+    }
+
+    /// @brief returns the parent of this JSON pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
+    json_pointer parent_pointer() const
+    {
+        if (empty())
+        {
+            return *this;
+        }
+
+        json_pointer res = *this;
+        res.pop_back();
+        return res;
+    }
+
+    /// @brief remove last reference token
+    /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
+    void pop_back()
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
+        }
+
+        reference_tokens.pop_back();
+    }
+
+    /// @brief return last reference token
+    /// @sa https://json.nlohmann.me/api/json_pointer/back/
+    const string_t& back() const
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
+        }
+
+        return reference_tokens.back();
+    }
+
+    /// @brief append an unescaped token at the end of the reference pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
+    void push_back(const string_t& token)
+    {
+        reference_tokens.push_back(token);
+    }
+
+    /// @brief append an unescaped token at the end of the reference pointer
+    /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
+    void push_back(string_t&& token)
+    {
+        reference_tokens.push_back(std::move(token));
+    }
+
+    /// @brief return whether pointer points to the root document
+    /// @sa https://json.nlohmann.me/api/json_pointer/empty/
+    bool empty() const noexcept
+    {
+        return reference_tokens.empty();
+    }
+
+  private:
+    /*!
+    @param[in] s  reference token to be converted into an array index
+
+    @return integer representation of @a s
+
+    @throw parse_error.106  if an array index begins with '0'
+    @throw parse_error.109  if an array index begins not with a digit
+    @throw out_of_range.404 if string @a s could not be converted to an integer
+    @throw out_of_range.410 if an array index exceeds size_type
+    */
+    template<typename BasicJsonType>
+    static typename BasicJsonType::size_type array_index(const string_t& s)
+    {
+        using size_type = typename BasicJsonType::size_type;
+
+        // error condition (cf. RFC 6901, Sect. 4)
+        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
+        {
+            JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
+        }
+
+        // error condition (cf. RFC 6901, Sect. 4)
+        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
+        {
+            JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
+        }
+
+        const char* p = s.c_str();
+        char* p_end = nullptr;
+        errno = 0; // strtoull doesn't reset errno
+        unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
+        if (p == p_end // invalid input or empty string
+                || errno == ERANGE // out of range
+                || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
+        {
+            JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
+        }
+
+        // only triggered on special platforms (like 32bit), see also
+        // https://github.com/nlohmann/json/pull/2203
+        if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
+        {
+            JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
+        }
+
+        return static_cast<size_type>(res);
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    json_pointer top() const
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
+        }
+
+        json_pointer result = *this;
+        result.reference_tokens = {reference_tokens[0]};
+        return result;
+    }
+
+  private:
+    /*!
+    @brief create and return a reference to the pointed to value
+
+    @complexity Linear in the number of reference tokens.
+
+    @throw parse_error.109 if array index is not a number
+    @throw type_error.313 if value cannot be unflattened
+    */
+    template<typename BasicJsonType>
+    BasicJsonType& get_and_create(BasicJsonType& j) const
+    {
+        auto* result = &j;
+
+        // in case no reference tokens exist, return a reference to the JSON value
+        // j which will be overwritten by a primitive value
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (result->type())
+            {
+                case detail::value_t::null:
+                {
+                    if (reference_token == "0")
+                    {
+                        // start a new array if reference token is 0
+                        result = &result->operator[](0);
+                    }
+                    else
+                    {
+                        // start a new object otherwise
+                        result = &result->operator[](reference_token);
+                    }
+                    break;
+                }
+
+                case detail::value_t::object:
+                {
+                    // create an entry in the object
+                    result = &result->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    // create an entry in the array
+                    result = &result->operator[](array_index<BasicJsonType>(reference_token));
+                    break;
+                }
+
+                /*
+                The following code is only reached if there exists a reference
+                token _and_ the current value is primitive. In this case, we have
+                an error situation, because primitive values may only occur as
+                single value; that is, with an empty list of reference tokens.
+                */
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
+            }
+        }
+
+        return *result;
+    }
+
+    /*!
+    @brief return a reference to the pointed to value
+
+    @note This version does not throw if a value is not present, but tries to
+          create nested values instead. For instance, calling this function
+          with pointer `"/this/that"` on a null value is equivalent to calling
+          `operator[]("this").operator[]("that")` on that value, effectively
+          changing the null value to an object.
+
+    @param[in] ptr  a JSON value
+
+    @return reference to the JSON value pointed to by the JSON pointer
+
+    @complexity Linear in the length of the JSON pointer.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    template<typename BasicJsonType>
+    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            // convert null values to arrays or objects before continuing
+            if (ptr->is_null())
+            {
+                // check if reference token is a number
+                const bool nums =
+                    std::all_of(reference_token.begin(), reference_token.end(),
+                                [](const unsigned char x)
+                {
+                    return std::isdigit(x);
+                });
+
+                // change value to array for numbers or "-" or to object otherwise
+                *ptr = (nums || reference_token == "-")
+                       ? detail::value_t::array
+                       : detail::value_t::object;
+            }
+
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // use unchecked object access
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (reference_token == "-")
+                    {
+                        // explicitly treat "-" as index beyond the end
+                        ptr = &ptr->operator[](ptr->m_value.array->size());
+                    }
+                    else
+                    {
+                        // convert array index to number; unchecked access
+                        ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
+                    }
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    template<typename BasicJsonType>
+    BasicJsonType& get_checked(BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // note: at performs range check
+                    ptr = &ptr->at(reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        JSON_THROW(detail::out_of_range::create(402, detail::concat(
+                                "array index '-' (", std::to_string(ptr->m_value.array->size()),
+                                ") is out of range"), ptr));
+                    }
+
+                    // note: at performs range check
+                    ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @brief return a const reference to the pointed to value
+
+    @param[in] ptr  a JSON value
+
+    @return const reference to the JSON value pointed to by the JSON
+    pointer
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    template<typename BasicJsonType>
+    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // use unchecked object access
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" cannot be used for const access
+                        JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
+                    }
+
+                    // use unchecked array access
+                    ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    template<typename BasicJsonType>
+    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // note: at performs range check
+                    ptr = &ptr->at(reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        JSON_THROW(detail::out_of_range::create(402, detail::concat(
+                                "array index '-' (", std::to_string(ptr->m_value.array->size()),
+                                ") is out of range"), ptr));
+                    }
+
+                    // note: at performs range check
+                    ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    */
+    template<typename BasicJsonType>
+    bool contains(const BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    if (!ptr->contains(reference_token))
+                    {
+                        // we did not find the key in the object
+                        return false;
+                    }
+
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
+                    {
+                        // invalid char
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
+                        {
+                            // first char should be between '1' and '9'
+                            return false;
+                        }
+                        for (std::size_t i = 1; i < reference_token.size(); i++)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
+                            {
+                                // other char should be between '0' and '9'
+                                return false;
+                            }
+                        }
+                    }
+
+                    const auto idx = array_index<BasicJsonType>(reference_token);
+                    if (idx >= ptr->size())
+                    {
+                        // index out of range
+                        return false;
+                    }
+
+                    ptr = &ptr->operator[](idx);
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                {
+                    // we do not expect primitive values if there is still a
+                    // reference token to process
+                    return false;
+                }
+            }
+        }
+
+        // no reference token left means we found a primitive value
+        return true;
+    }
+
+    /*!
+    @brief split the string input to reference tokens
+
+    @note This function is only called by the json_pointer constructor.
+          All exceptions below are documented there.
+
+    @throw parse_error.107  if the pointer is not empty or begins with '/'
+    @throw parse_error.108  if character '~' is not followed by '0' or '1'
+    */
+    static std::vector<string_t> split(const string_t& reference_string)
+    {
+        std::vector<string_t> result;
+
+        // special case: empty reference string -> no reference tokens
+        if (reference_string.empty())
+        {
+            return result;
+        }
+
+        // check if nonempty reference string begins with slash
+        if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
+        {
+            JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
+        }
+
+        // extract the reference tokens:
+        // - slash: position of the last read slash (or end of string)
+        // - start: position after the previous slash
+        for (
+            // search for the first slash after the first character
+            std::size_t slash = reference_string.find_first_of('/', 1),
+            // set the beginning of the first reference token
+            start = 1;
+            // we can stop if start == 0 (if slash == string_t::npos)
+            start != 0;
+            // set the beginning of the next reference token
+            // (will eventually be 0 if slash == string_t::npos)
+            start = (slash == string_t::npos) ? 0 : slash + 1,
+            // find next slash
+            slash = reference_string.find_first_of('/', start))
+        {
+            // use the text between the beginning of the reference token
+            // (start) and the last slash (slash).
+            auto reference_token = reference_string.substr(start, slash - start);
+
+            // check reference tokens are properly escaped
+            for (std::size_t pos = reference_token.find_first_of('~');
+                    pos != string_t::npos;
+                    pos = reference_token.find_first_of('~', pos + 1))
+            {
+                JSON_ASSERT(reference_token[pos] == '~');
+
+                // ~ must be followed by 0 or 1
+                if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
+                                         (reference_token[pos + 1] != '0' &&
+                                          reference_token[pos + 1] != '1')))
+                {
+                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
+                }
+            }
+
+            // finally, store the reference token
+            detail::unescape(reference_token);
+            result.push_back(reference_token);
+        }
+
+        return result;
+    }
+
+  private:
+    /*!
+    @param[in] reference_string  the reference string to the current value
+    @param[in] value             the value to consider
+    @param[in,out] result        the result object to insert values to
+
+    @note Empty objects or arrays are flattened to `null`.
+    */
+    template<typename BasicJsonType>
+    static void flatten(const string_t& reference_string,
+                        const BasicJsonType& value,
+                        BasicJsonType& result)
+    {
+        switch (value.type())
+        {
+            case detail::value_t::array:
+            {
+                if (value.m_value.array->empty())
+                {
+                    // flatten empty array as null
+                    result[reference_string] = nullptr;
+                }
+                else
+                {
+                    // iterate array and use index as reference string
+                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
+                    {
+                        flatten(detail::concat(reference_string, '/', std::to_string(i)),
+                                value.m_value.array->operator[](i), result);
+                    }
+                }
+                break;
+            }
+
+            case detail::value_t::object:
+            {
+                if (value.m_value.object->empty())
+                {
+                    // flatten empty object as null
+                    result[reference_string] = nullptr;
+                }
+                else
+                {
+                    // iterate object and use keys as reference string
+                    for (const auto& element : *value.m_value.object)
+                    {
+                        flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
+                    }
+                }
+                break;
+            }
+
+            case detail::value_t::null:
+            case detail::value_t::string:
+            case detail::value_t::boolean:
+            case detail::value_t::number_integer:
+            case detail::value_t::number_unsigned:
+            case detail::value_t::number_float:
+            case detail::value_t::binary:
+            case detail::value_t::discarded:
+            default:
+            {
+                // add primitive value with its reference string
+                result[reference_string] = value;
+                break;
+            }
+        }
+    }
+
+    /*!
+    @param[in] value  flattened JSON
+
+    @return unflattened JSON
+
+    @throw parse_error.109 if array index is not a number
+    @throw type_error.314  if value is not an object
+    @throw type_error.315  if object values are not primitive
+    @throw type_error.313  if value cannot be unflattened
+    */
+    template<typename BasicJsonType>
+    static BasicJsonType
+    unflatten(const BasicJsonType& value)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
+        {
+            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
+        }
+
+        BasicJsonType result;
+
+        // iterate the JSON object values
+        for (const auto& element : *value.m_value.object)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
+            {
+                JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
+            }
+
+            // assign value to reference pointed to by JSON pointer; Note that if
+            // the JSON pointer is "" (i.e., points to the whole value), function
+            // get_and_create returns a reference to result itself. An assignment
+            // will then create a primitive value.
+            json_pointer(element.first).get_and_create(result) = element.second;
+        }
+
+        return result;
+    }
+
+    // can't use conversion operator because of ambiguity
+    json_pointer<string_t> convert() const&
+    {
+        json_pointer<string_t> result;
+        result.reference_tokens = reference_tokens;
+        return result;
+    }
+
+    json_pointer<string_t> convert()&&
+    {
+        json_pointer<string_t> result;
+        result.reference_tokens = std::move(reference_tokens);
+        return result;
+    }
+
+  public:
+#if JSON_HAS_THREE_WAY_COMPARISON
+    /// @brief compares two JSON pointers for equality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
+    template<typename RefStringTypeRhs>
+    bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
+    {
+        return reference_tokens == rhs.reference_tokens;
+    }
+
+    /// @brief compares JSON pointer and string for equality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
+    bool operator==(const string_t& rhs) const
+    {
+        return *this == json_pointer(rhs);
+    }
+
+    /// @brief 3-way compares two JSON pointers
+    template<typename RefStringTypeRhs>
+    std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
+    {
+        return  reference_tokens <=> rhs.reference_tokens; // *NOPAD*
+    }
+#else
+    /// @brief compares two JSON pointers for equality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
+    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
+                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
+
+    /// @brief compares JSON pointer and string for equality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
+    template<typename RefStringTypeLhs, typename StringType>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
+                           const StringType& rhs);
+
+    /// @brief compares string and JSON pointer for equality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
+    template<typename RefStringTypeRhs, typename StringType>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator==(const StringType& lhs,
+                           const json_pointer<RefStringTypeRhs>& rhs);
+
+    /// @brief compares two JSON pointers for inequality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
+    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
+                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
+
+    /// @brief compares JSON pointer and string for inequality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
+    template<typename RefStringTypeLhs, typename StringType>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
+                           const StringType& rhs);
+
+    /// @brief compares string and JSON pointer for inequality
+    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
+    template<typename RefStringTypeRhs, typename StringType>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator!=(const StringType& lhs,
+                           const json_pointer<RefStringTypeRhs>& rhs);
+
+    /// @brief compares two JSON pointer for less-than
+    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+    // NOLINTNEXTLINE(readability-redundant-declaration)
+    friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
+                          const json_pointer<RefStringTypeRhs>& rhs) noexcept;
+#endif
+
+  private:
+    /// the reference tokens
+    std::vector<string_t> reference_tokens;
+};
+
+#if !JSON_HAS_THREE_WAY_COMPARISON
+// functions cannot be defined inside class due to ODR violations
+template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
+                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
+{
+    return lhs.reference_tokens == rhs.reference_tokens;
+}
+
+template<typename RefStringTypeLhs,
+         typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
+JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
+inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
+                       const StringType& rhs)
+{
+    return lhs == json_pointer<RefStringTypeLhs>(rhs);
+}
+
+template<typename RefStringTypeRhs,
+         typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
+JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
+inline bool operator==(const StringType& lhs,
+                       const json_pointer<RefStringTypeRhs>& rhs)
+{
+    return json_pointer<RefStringTypeRhs>(lhs) == rhs;
+}
+
+template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
+                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
+{
+    return !(lhs == rhs);
+}
+
+template<typename RefStringTypeLhs,
+         typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
+JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
+inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
+                       const StringType& rhs)
+{
+    return !(lhs == rhs);
+}
+
+template<typename RefStringTypeRhs,
+         typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
+JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
+inline bool operator!=(const StringType& lhs,
+                       const json_pointer<RefStringTypeRhs>& rhs)
+{
+    return !(lhs == rhs);
+}
+
+template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
+                      const json_pointer<RefStringTypeRhs>& rhs) noexcept
+{
+    return lhs.reference_tokens < rhs.reference_tokens;
+}
+#endif
+
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/json_ref.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <initializer_list>
+#include <utility>
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+template<typename BasicJsonType>
+class json_ref
+{
+  public:
+    using value_type = BasicJsonType;
+
+    json_ref(value_type&& value)
+        : owned_value(std::move(value))
+    {}
+
+    json_ref(const value_type& value)
+        : value_ref(&value)
+    {}
+
+    json_ref(std::initializer_list<json_ref> init)
+        : owned_value(init)
+    {}
+
+    template <
+        class... Args,
+        enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
+    json_ref(Args && ... args)
+        : owned_value(std::forward<Args>(args)...)
+    {}
+
+    // class should be movable only
+    json_ref(json_ref&&) noexcept = default;
+    json_ref(const json_ref&) = delete;
+    json_ref& operator=(const json_ref&) = delete;
+    json_ref& operator=(json_ref&&) = delete;
+    ~json_ref() = default;
+
+    value_type moved_or_copied() const
+    {
+        if (value_ref == nullptr)
+        {
+            return std::move(owned_value);
+        }
+        return *value_ref;
+    }
+
+    value_type const& operator*() const
+    {
+        return value_ref ? *value_ref : owned_value;
+    }
+
+    value_type const* operator->() const
+    {
+        return &** this;
+    }
+
+  private:
+    mutable value_type owned_value = nullptr;
+    value_type const* value_ref = nullptr;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // reverse
+#include <array> // array
+#include <map> // map
+#include <cmath> // isnan, isinf
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstring> // memcpy
+#include <limits> // numeric_limits
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // copy
+#include <cstddef> // size_t
+#include <iterator> // back_inserter
+#include <memory> // shared_ptr, make_shared
+#include <string> // basic_string
+#include <vector> // vector
+
+#ifndef JSON_NO_IO
+    #include <ios>      // streamsize
+    #include <ostream>  // basic_ostream
+#endif  // JSON_NO_IO
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/// abstract output adapter interface
+template<typename CharType> struct output_adapter_protocol
+{
+    virtual void write_character(CharType c) = 0;
+    virtual void write_characters(const CharType* s, std::size_t length) = 0;
+    virtual ~output_adapter_protocol() = default;
+
+    output_adapter_protocol() = default;
+    output_adapter_protocol(const output_adapter_protocol&) = default;
+    output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
+    output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
+    output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
+};
+
+/// a type to simplify interfaces
+template<typename CharType>
+using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
+
+/// output adapter for byte vectors
+template<typename CharType, typename AllocatorType = std::allocator<CharType>>
+class output_vector_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
+        : v(vec)
+    {}
+
+    void write_character(CharType c) override
+    {
+        v.push_back(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        v.insert(v.end(), s, s + length);
+    }
+
+  private:
+    std::vector<CharType, AllocatorType>& v;
+};
+
+#ifndef JSON_NO_IO
+/// output adapter for output streams
+template<typename CharType>
+class output_stream_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
+        : stream(s)
+    {}
+
+    void write_character(CharType c) override
+    {
+        stream.put(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        stream.write(s, static_cast<std::streamsize>(length));
+    }
+
+  private:
+    std::basic_ostream<CharType>& stream;
+};
+#endif  // JSON_NO_IO
+
+/// output adapter for basic_string
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_string_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_string_adapter(StringType& s) noexcept
+        : str(s)
+    {}
+
+    void write_character(CharType c) override
+    {
+        str.push_back(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        str.append(s, length);
+    }
+
+  private:
+    StringType& str;
+};
+
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_adapter
+{
+  public:
+    template<typename AllocatorType = std::allocator<CharType>>
+    output_adapter(std::vector<CharType, AllocatorType>& vec)
+        : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
+
+#ifndef JSON_NO_IO
+    output_adapter(std::basic_ostream<CharType>& s)
+        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
+#endif  // JSON_NO_IO
+
+    output_adapter(StringType& s)
+        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
+
+    operator output_adapter_t<CharType>()
+    {
+        return oa;
+    }
+
+  private:
+    output_adapter_t<CharType> oa = nullptr;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+///////////////////
+// binary writer //
+///////////////////
+
+/*!
+@brief serialization to CBOR and MessagePack values
+*/
+template<typename BasicJsonType, typename CharType>
+class binary_writer
+{
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+
+  public:
+    /*!
+    @brief create a binary writer
+
+    @param[in] adapter  output adapter to write to
+    */
+    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
+    {
+        JSON_ASSERT(oa);
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @pre       j.type() == value_t::object
+    */
+    void write_bson(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::object:
+            {
+                write_bson_object(*j.m_value.object);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::array:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
+            }
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    */
+    void write_cbor(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                oa->write_character(to_char_type(0xF6));
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                oa->write_character(j.m_value.boolean
+                                    ? to_char_type(0xF5)
+                                    : to_char_type(0xF4));
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // CBOR does not differentiate between positive signed
+                    // integers and unsigned integers. Therefore, we used the
+                    // code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_integer <= 0x17)
+                    {
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x18));
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x19));
+                        write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x1A));
+                        write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                    }
+                    else
+                    {
+                        oa->write_character(to_char_type(0x1B));
+                        write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                    }
+                }
+                else
+                {
+                    // The conversions below encode the sign in the first
+                    // byte, and the value is converted to a positive number.
+                    const auto positive_number = -1 - j.m_value.number_integer;
+                    if (j.m_value.number_integer >= -24)
+                    {
+                        write_number(static_cast<std::uint8_t>(0x20 + positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x38));
+                        write_number(static_cast<std::uint8_t>(positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x39));
+                        write_number(static_cast<std::uint16_t>(positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x3A));
+                        write_number(static_cast<std::uint32_t>(positive_number));
+                    }
+                    else
+                    {
+                        oa->write_character(to_char_type(0x3B));
+                        write_number(static_cast<std::uint64_t>(positive_number));
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x18));
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x19));
+                    write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x1A));
+                    write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
+                }
+                else
+                {
+                    oa->write_character(to_char_type(0x1B));
+                    write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                if (std::isnan(j.m_value.number_float))
+                {
+                    // NaN is 0xf97e00 in CBOR
+                    oa->write_character(to_char_type(0xF9));
+                    oa->write_character(to_char_type(0x7E));
+                    oa->write_character(to_char_type(0x00));
+                }
+                else if (std::isinf(j.m_value.number_float))
+                {
+                    // Infinity is 0xf97c00, -Infinity is 0xf9fc00
+                    oa->write_character(to_char_type(0xf9));
+                    oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
+                    oa->write_character(to_char_type(0x00));
+                }
+                else
+                {
+                    write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
+                }
+                break;
+            }
+
+            case value_t::string:
+            {
+                // step 1: write control byte and the string length
+                const auto N = j.m_value.string->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x60 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x78));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x79));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x7A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x7B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write the string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                // step 1: write control byte and the array size
+                const auto N = j.m_value.array->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x80 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x98));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x99));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x9A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x9B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_cbor(el);
+                }
+                break;
+            }
+
+            case value_t::binary:
+            {
+                if (j.m_value.binary->has_subtype())
+                {
+                    if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xd8));
+                        write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
+                    }
+                    else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xd9));
+                        write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
+                    }
+                    else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xda));
+                        write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
+                    }
+                    else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xdb));
+                        write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
+                    }
+                }
+
+                // step 1: write control byte and the binary array size
+                const auto N = j.m_value.binary->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x40 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x58));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x59));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x5A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x5B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+                    N);
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // step 1: write control byte and the object size
+                const auto N = j.m_value.object->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0xA0 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xB8));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xB9));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xBA));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xBB));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_cbor(el.first);
+                    write_cbor(el.second);
+                }
+                break;
+            }
+
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    */
+    void write_msgpack(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::null: // nil
+            {
+                oa->write_character(to_char_type(0xC0));
+                break;
+            }
+
+            case value_t::boolean: // true and false
+            {
+                oa->write_character(j.m_value.boolean
+                                    ? to_char_type(0xC3)
+                                    : to_char_type(0xC2));
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // MessagePack does not differentiate between positive
+                    // signed integers and unsigned integers. Therefore, we used
+                    // the code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_unsigned < 128)
+                    {
+                        // positive fixnum
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        // uint 8
+                        oa->write_character(to_char_type(0xCC));
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        // uint 16
+                        oa->write_character(to_char_type(0xCD));
+                        write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        // uint 32
+                        oa->write_character(to_char_type(0xCE));
+                        write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                    {
+                        // uint 64
+                        oa->write_character(to_char_type(0xCF));
+                        write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                    }
+                }
+                else
+                {
+                    if (j.m_value.number_integer >= -32)
+                    {
+                        // negative fixnum
+                        write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+                    {
+                        // int 8
+                        oa->write_character(to_char_type(0xD0));
+                        write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+                    {
+                        // int 16
+                        oa->write_character(to_char_type(0xD1));
+                        write_number(static_cast<std::int16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+                    {
+                        // int 32
+                        oa->write_character(to_char_type(0xD2));
+                        write_number(static_cast<std::int32_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+                    {
+                        // int 64
+                        oa->write_character(to_char_type(0xD3));
+                        write_number(static_cast<std::int64_t>(j.m_value.number_integer));
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned < 128)
+                {
+                    // positive fixnum
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    // uint 8
+                    oa->write_character(to_char_type(0xCC));
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // uint 16
+                    oa->write_character(to_char_type(0xCD));
+                    write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // uint 32
+                    oa->write_character(to_char_type(0xCE));
+                    write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    // uint 64
+                    oa->write_character(to_char_type(0xCF));
+                    write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
+                break;
+            }
+
+            case value_t::string:
+            {
+                // step 1: write control byte and the string length
+                const auto N = j.m_value.string->size();
+                if (N <= 31)
+                {
+                    // fixstr
+                    write_number(static_cast<std::uint8_t>(0xA0 | N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    // str 8
+                    oa->write_character(to_char_type(0xD9));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // str 16
+                    oa->write_character(to_char_type(0xDA));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // str 32
+                    oa->write_character(to_char_type(0xDB));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write the string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                // step 1: write control byte and the array size
+                const auto N = j.m_value.array->size();
+                if (N <= 15)
+                {
+                    // fixarray
+                    write_number(static_cast<std::uint8_t>(0x90 | N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // array 16
+                    oa->write_character(to_char_type(0xDC));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // array 32
+                    oa->write_character(to_char_type(0xDD));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_msgpack(el);
+                }
+                break;
+            }
+
+            case value_t::binary:
+            {
+                // step 0: determine if the binary type has a set subtype to
+                // determine whether or not to use the ext or fixext types
+                const bool use_ext = j.m_value.binary->has_subtype();
+
+                // step 1: write control byte and the byte string length
+                const auto N = j.m_value.binary->size();
+                if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    std::uint8_t output_type{};
+                    bool fixed = true;
+                    if (use_ext)
+                    {
+                        switch (N)
+                        {
+                            case 1:
+                                output_type = 0xD4; // fixext 1
+                                break;
+                            case 2:
+                                output_type = 0xD5; // fixext 2
+                                break;
+                            case 4:
+                                output_type = 0xD6; // fixext 4
+                                break;
+                            case 8:
+                                output_type = 0xD7; // fixext 8
+                                break;
+                            case 16:
+                                output_type = 0xD8; // fixext 16
+                                break;
+                            default:
+                                output_type = 0xC7; // ext 8
+                                fixed = false;
+                                break;
+                        }
+
+                    }
+                    else
+                    {
+                        output_type = 0xC4; // bin 8
+                        fixed = false;
+                    }
+
+                    oa->write_character(to_char_type(output_type));
+                    if (!fixed)
+                    {
+                        write_number(static_cast<std::uint8_t>(N));
+                    }
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    std::uint8_t output_type = use_ext
+                                               ? 0xC8 // ext 16
+                                               : 0xC5; // bin 16
+
+                    oa->write_character(to_char_type(output_type));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    std::uint8_t output_type = use_ext
+                                               ? 0xC9 // ext 32
+                                               : 0xC6; // bin 32
+
+                    oa->write_character(to_char_type(output_type));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 1.5: if this is an ext type, write the subtype
+                if (use_ext)
+                {
+                    write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
+                }
+
+                // step 2: write the byte string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+                    N);
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // step 1: write control byte and the object size
+                const auto N = j.m_value.object->size();
+                if (N <= 15)
+                {
+                    // fixmap
+                    write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // map 16
+                    oa->write_character(to_char_type(0xDE));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // map 32
+                    oa->write_character(to_char_type(0xDF));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_msgpack(el.first);
+                    write_msgpack(el.second);
+                }
+                break;
+            }
+
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @param[in] use_count   whether to use '#' prefixes (optimized format)
+    @param[in] use_type    whether to use '$' prefixes (optimized format)
+    @param[in] add_prefix  whether prefixes need to be used for this value
+    @param[in] use_bjdata  whether write in BJData format, default is false
+    */
+    void write_ubjson(const BasicJsonType& j, const bool use_count,
+                      const bool use_type, const bool add_prefix = true,
+                      const bool use_bjdata = false)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('Z'));
+                }
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(j.m_value.boolean
+                                        ? to_char_type('T')
+                                        : to_char_type('F'));
+                }
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
+                break;
+            }
+
+            case value_t::string:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('S'));
+                }
+                write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('['));
+                }
+
+                bool prefix_required = true;
+                if (use_type && !j.m_value.array->empty())
+                {
+                    JSON_ASSERT(use_count);
+                    const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
+                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
+                                                         [this, first_prefix, use_bjdata](const BasicJsonType & v)
+                    {
+                        return ubjson_prefix(v, use_bjdata) == first_prefix;
+                    });
+
+                    std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
+
+                    if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
+                    {
+                        prefix_required = false;
+                        oa->write_character(to_char_type('$'));
+                        oa->write_character(first_prefix);
+                    }
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
+                }
+
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
+                }
+
+                if (!use_count)
+                {
+                    oa->write_character(to_char_type(']'));
+                }
+
+                break;
+            }
+
+            case value_t::binary:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('['));
+                }
+
+                if (use_type && !j.m_value.binary->empty())
+                {
+                    JSON_ASSERT(use_count);
+                    oa->write_character(to_char_type('$'));
+                    oa->write_character('U');
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
+                }
+
+                if (use_type)
+                {
+                    oa->write_characters(
+                        reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+                        j.m_value.binary->size());
+                }
+                else
+                {
+                    for (size_t i = 0; i < j.m_value.binary->size(); ++i)
+                    {
+                        oa->write_character(to_char_type('U'));
+                        oa->write_character(j.m_value.binary->data()[i]);
+                    }
+                }
+
+                if (!use_count)
+                {
+                    oa->write_character(to_char_type(']'));
+                }
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
+                {
+                    if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
+                    {
+                        break;
+                    }
+                }
+
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('{'));
+                }
+
+                bool prefix_required = true;
+                if (use_type && !j.m_value.object->empty())
+                {
+                    JSON_ASSERT(use_count);
+                    const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
+                    const bool same_prefix = std::all_of(j.begin(), j.end(),
+                                                         [this, first_prefix, use_bjdata](const BasicJsonType & v)
+                    {
+                        return ubjson_prefix(v, use_bjdata) == first_prefix;
+                    });
+
+                    std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
+
+                    if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
+                    {
+                        prefix_required = false;
+                        oa->write_character(to_char_type('$'));
+                        oa->write_character(first_prefix);
+                    }
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
+                }
+
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
+                    oa->write_characters(
+                        reinterpret_cast<const CharType*>(el.first.c_str()),
+                        el.first.size());
+                    write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
+                }
+
+                if (!use_count)
+                {
+                    oa->write_character(to_char_type('}'));
+                }
+
+                break;
+            }
+
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+  private:
+    //////////
+    // BSON //
+    //////////
+
+    /*!
+    @return The size of a BSON document entry header, including the id marker
+            and the entry name size (and its null-terminator).
+    */
+    static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
+    {
+        const auto it = name.find(static_cast<typename string_t::value_type>(0));
+        if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
+        {
+            JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
+            static_cast<void>(j);
+        }
+
+        return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
+    }
+
+    /*!
+    @brief Writes the given @a element_type and @a name to the output adapter
+    */
+    void write_bson_entry_header(const string_t& name,
+                                 const std::uint8_t element_type)
+    {
+        oa->write_character(to_char_type(element_type)); // boolean
+        oa->write_characters(
+            reinterpret_cast<const CharType*>(name.c_str()),
+            name.size() + 1u);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and boolean value @a value
+    */
+    void write_bson_boolean(const string_t& name,
+                            const bool value)
+    {
+        write_bson_entry_header(name, 0x08);
+        oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and double value @a value
+    */
+    void write_bson_double(const string_t& name,
+                           const double value)
+    {
+        write_bson_entry_header(name, 0x01);
+        write_number<double>(value, true);
+    }
+
+    /*!
+    @return The size of the BSON-encoded string in @a value
+    */
+    static std::size_t calc_bson_string_size(const string_t& value)
+    {
+        return sizeof(std::int32_t) + value.size() + 1ul;
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and string value @a value
+    */
+    void write_bson_string(const string_t& name,
+                           const string_t& value)
+    {
+        write_bson_entry_header(name, 0x02);
+
+        write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
+        oa->write_characters(
+            reinterpret_cast<const CharType*>(value.c_str()),
+            value.size() + 1);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and null value
+    */
+    void write_bson_null(const string_t& name)
+    {
+        write_bson_entry_header(name, 0x0A);
+    }
+
+    /*!
+    @return The size of the BSON-encoded integer @a value
+    */
+    static std::size_t calc_bson_integer_size(const std::int64_t value)
+    {
+        return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
+               ? sizeof(std::int32_t)
+               : sizeof(std::int64_t);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and integer @a value
+    */
+    void write_bson_integer(const string_t& name,
+                            const std::int64_t value)
+    {
+        if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
+        {
+            write_bson_entry_header(name, 0x10); // int32
+            write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
+        }
+        else
+        {
+            write_bson_entry_header(name, 0x12); // int64
+            write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
+        }
+    }
+
+    /*!
+    @return The size of the BSON-encoded unsigned integer in @a j
+    */
+    static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
+    {
+        return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+               ? sizeof(std::int32_t)
+               : sizeof(std::int64_t);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and unsigned @a value
+    */
+    void write_bson_unsigned(const string_t& name,
+                             const BasicJsonType& j)
+    {
+        if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+        {
+            write_bson_entry_header(name, 0x10 /* int32 */);
+            write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
+        }
+        else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+        {
+            write_bson_entry_header(name, 0x12 /* int64 */);
+            write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
+        }
+        else
+        {
+            JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
+        }
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and object @a value
+    */
+    void write_bson_object_entry(const string_t& name,
+                                 const typename BasicJsonType::object_t& value)
+    {
+        write_bson_entry_header(name, 0x03); // object
+        write_bson_object(value);
+    }
+
+    /*!
+    @return The size of the BSON-encoded array @a value
+    */
+    static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
+    {
+        std::size_t array_index = 0ul;
+
+        const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
+        {
+            return result + calc_bson_element_size(std::to_string(array_index++), el);
+        });
+
+        return sizeof(std::int32_t) + embedded_document_size + 1ul;
+    }
+
+    /*!
+    @return The size of the BSON-encoded binary array @a value
+    */
+    static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
+    {
+        return sizeof(std::int32_t) + value.size() + 1ul;
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and array @a value
+    */
+    void write_bson_array(const string_t& name,
+                          const typename BasicJsonType::array_t& value)
+    {
+        write_bson_entry_header(name, 0x04); // array
+        write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
+
+        std::size_t array_index = 0ul;
+
+        for (const auto& el : value)
+        {
+            write_bson_element(std::to_string(array_index++), el);
+        }
+
+        oa->write_character(to_char_type(0x00));
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and binary value @a value
+    */
+    void write_bson_binary(const string_t& name,
+                           const binary_t& value)
+    {
+        write_bson_entry_header(name, 0x05);
+
+        write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
+        write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
+
+        oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
+    }
+
+    /*!
+    @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
+    @return The calculated size for the BSON document entry for @a j with the given @a name.
+    */
+    static std::size_t calc_bson_element_size(const string_t& name,
+            const BasicJsonType& j)
+    {
+        const auto header_size = calc_bson_entry_header_size(name, j);
+        switch (j.type())
+        {
+            case value_t::object:
+                return header_size + calc_bson_object_size(*j.m_value.object);
+
+            case value_t::array:
+                return header_size + calc_bson_array_size(*j.m_value.array);
+
+            case value_t::binary:
+                return header_size + calc_bson_binary_size(*j.m_value.binary);
+
+            case value_t::boolean:
+                return header_size + 1ul;
+
+            case value_t::number_float:
+                return header_size + 8ul;
+
+            case value_t::number_integer:
+                return header_size + calc_bson_integer_size(j.m_value.number_integer);
+
+            case value_t::number_unsigned:
+                return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
+
+            case value_t::string:
+                return header_size + calc_bson_string_size(*j.m_value.string);
+
+            case value_t::null:
+                return header_size + 0ul;
+
+            // LCOV_EXCL_START
+            case value_t::discarded:
+            default:
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
+                return 0ul;
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    /*!
+    @brief Serializes the JSON value @a j to BSON and associates it with the
+           key @a name.
+    @param name The name to associate with the JSON entity @a j within the
+                current BSON document
+    */
+    void write_bson_element(const string_t& name,
+                            const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::object:
+                return write_bson_object_entry(name, *j.m_value.object);
+
+            case value_t::array:
+                return write_bson_array(name, *j.m_value.array);
+
+            case value_t::binary:
+                return write_bson_binary(name, *j.m_value.binary);
+
+            case value_t::boolean:
+                return write_bson_boolean(name, j.m_value.boolean);
+
+            case value_t::number_float:
+                return write_bson_double(name, j.m_value.number_float);
+
+            case value_t::number_integer:
+                return write_bson_integer(name, j.m_value.number_integer);
+
+            case value_t::number_unsigned:
+                return write_bson_unsigned(name, j);
+
+            case value_t::string:
+                return write_bson_string(name, *j.m_value.string);
+
+            case value_t::null:
+                return write_bson_null(name);
+
+            // LCOV_EXCL_START
+            case value_t::discarded:
+            default:
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
+                return;
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    /*!
+    @brief Calculates the size of the BSON serialization of the given
+           JSON-object @a j.
+    @param[in] value  JSON value to serialize
+    @pre       value.type() == value_t::object
+    */
+    static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
+    {
+        std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
+                                    [](size_t result, const typename BasicJsonType::object_t::value_type & el)
+        {
+            return result += calc_bson_element_size(el.first, el.second);
+        });
+
+        return sizeof(std::int32_t) + document_size + 1ul;
+    }
+
+    /*!
+    @param[in] value  JSON value to serialize
+    @pre       value.type() == value_t::object
+    */
+    void write_bson_object(const typename BasicJsonType::object_t& value)
+    {
+        write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
+
+        for (const auto& el : value)
+        {
+            write_bson_element(el.first, el.second);
+        }
+
+        oa->write_character(to_char_type(0x00));
+    }
+
+    //////////
+    // CBOR //
+    //////////
+
+    static constexpr CharType get_cbor_float_prefix(float /*unused*/)
+    {
+        return to_char_type(0xFA);  // Single-Precision Float
+    }
+
+    static constexpr CharType get_cbor_float_prefix(double /*unused*/)
+    {
+        return to_char_type(0xFB);  // Double-Precision Float
+    }
+
+    /////////////
+    // MsgPack //
+    /////////////
+
+    static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
+    {
+        return to_char_type(0xCA);  // float 32
+    }
+
+    static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
+    {
+        return to_char_type(0xCB);  // float 64
+    }
+
+    ////////////
+    // UBJSON //
+    ////////////
+
+    // UBJSON: write number (floating point)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_floating_point<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix,
+                                         const bool use_bjdata)
+    {
+        if (add_prefix)
+        {
+            oa->write_character(get_ubjson_float_prefix(n));
+        }
+        write_number(n, use_bjdata);
+    }
+
+    // UBJSON: write number (unsigned integer)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_unsigned<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix,
+                                         const bool use_bjdata)
+    {
+        if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('i'));  // int8
+            }
+            write_number(static_cast<std::uint8_t>(n), use_bjdata);
+        }
+        else if (n <= (std::numeric_limits<std::uint8_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('U'));  // uint8
+            }
+            write_number(static_cast<std::uint8_t>(n), use_bjdata);
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('I'));  // int16
+            }
+            write_number(static_cast<std::int16_t>(n), use_bjdata);
+        }
+        else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('u'));  // uint16 - bjdata only
+            }
+            write_number(static_cast<std::uint16_t>(n), use_bjdata);
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('l'));  // int32
+            }
+            write_number(static_cast<std::int32_t>(n), use_bjdata);
+        }
+        else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('m'));  // uint32 - bjdata only
+            }
+            write_number(static_cast<std::uint32_t>(n), use_bjdata);
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('L'));  // int64
+            }
+            write_number(static_cast<std::int64_t>(n), use_bjdata);
+        }
+        else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('M'));  // uint64 - bjdata only
+            }
+            write_number(static_cast<std::uint64_t>(n), use_bjdata);
+        }
+        else
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('H'));  // high-precision number
+            }
+
+            const auto number = BasicJsonType(n).dump();
+            write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
+            for (std::size_t i = 0; i < number.size(); ++i)
+            {
+                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
+            }
+        }
+    }
+
+    // UBJSON: write number (signed integer)
+    template < typename NumberType, typename std::enable_if <
+                   std::is_signed<NumberType>::value&&
+                   !std::is_floating_point<NumberType>::value, int >::type = 0 >
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix,
+                                         const bool use_bjdata)
+    {
+        if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('i'));  // int8
+            }
+            write_number(static_cast<std::int8_t>(n), use_bjdata);
+        }
+        else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('U'));  // uint8
+            }
+            write_number(static_cast<std::uint8_t>(n), use_bjdata);
+        }
+        else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('I'));  // int16
+            }
+            write_number(static_cast<std::int16_t>(n), use_bjdata);
+        }
+        else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('u'));  // uint16 - bjdata only
+            }
+            write_number(static_cast<uint16_t>(n), use_bjdata);
+        }
+        else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('l'));  // int32
+            }
+            write_number(static_cast<std::int32_t>(n), use_bjdata);
+        }
+        else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('m'));  // uint32 - bjdata only
+            }
+            write_number(static_cast<uint32_t>(n), use_bjdata);
+        }
+        else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('L'));  // int64
+            }
+            write_number(static_cast<std::int64_t>(n), use_bjdata);
+        }
+        // LCOV_EXCL_START
+        else
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('H'));  // high-precision number
+            }
+
+            const auto number = BasicJsonType(n).dump();
+            write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
+            for (std::size_t i = 0; i < number.size(); ++i)
+            {
+                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
+            }
+        }
+        // LCOV_EXCL_STOP
+    }
+
+    /*!
+    @brief determine the type prefix of container values
+    */
+    CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+                return 'Z';
+
+            case value_t::boolean:
+                return j.m_value.boolean ? 'T' : 'F';
+
+            case value_t::number_integer:
+            {
+                if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+                {
+                    return 'i';
+                }
+                if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    return 'U';
+                }
+                if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+                {
+                    return 'I';
+                }
+                if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
+                {
+                    return 'u';
+                }
+                if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+                {
+                    return 'l';
+                }
+                if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
+                {
+                    return 'm';
+                }
+                if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+                {
+                    return 'L';
+                }
+                // anything else is treated as high-precision number
+                return 'H'; // LCOV_EXCL_LINE
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+                {
+                    return 'i';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
+                {
+                    return 'U';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+                {
+                    return 'I';
+                }
+                if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
+                {
+                    return 'u';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+                {
+                    return 'l';
+                }
+                if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
+                {
+                    return 'm';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+                {
+                    return 'L';
+                }
+                if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    return 'M';
+                }
+                // anything else is treated as high-precision number
+                return 'H'; // LCOV_EXCL_LINE
+            }
+
+            case value_t::number_float:
+                return get_ubjson_float_prefix(j.m_value.number_float);
+
+            case value_t::string:
+                return 'S';
+
+            case value_t::array: // fallthrough
+            case value_t::binary:
+                return '[';
+
+            case value_t::object:
+                return '{';
+
+            case value_t::discarded:
+            default:  // discarded values
+                return 'N';
+        }
+    }
+
+    static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
+    {
+        return 'd';  // float 32
+    }
+
+    static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
+    {
+        return 'D';  // float 64
+    }
+
+    /*!
+    @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
+    */
+    bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
+    {
+        std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
+            {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
+        };
+
+        string_t key = "_ArrayType_";
+        auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
+        if (it == bjdtype.end())
+        {
+            return true;
+        }
+        CharType dtype = it->second;
+
+        key = "_ArraySize_";
+        std::size_t len = (value.at(key).empty() ? 0 : 1);
+        for (const auto& el : value.at(key))
+        {
+            len *= static_cast<std::size_t>(el.m_value.number_unsigned);
+        }
+
+        key = "_ArrayData_";
+        if (value.at(key).size() != len)
+        {
+            return true;
+        }
+
+        oa->write_character('[');
+        oa->write_character('$');
+        oa->write_character(dtype);
+        oa->write_character('#');
+
+        key = "_ArraySize_";
+        write_ubjson(value.at(key), use_count, use_type, true,  true);
+
+        key = "_ArrayData_";
+        if (dtype == 'U' || dtype == 'C')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
+            }
+        }
+        else if (dtype == 'i')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
+            }
+        }
+        else if (dtype == 'u')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
+            }
+        }
+        else if (dtype == 'I')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
+            }
+        }
+        else if (dtype == 'm')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
+            }
+        }
+        else if (dtype == 'l')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
+            }
+        }
+        else if (dtype == 'M')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
+            }
+        }
+        else if (dtype == 'L')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
+            }
+        }
+        else if (dtype == 'd')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<float>(el.m_value.number_float), true);
+            }
+        }
+        else if (dtype == 'D')
+        {
+            for (const auto& el : value.at(key))
+            {
+                write_number(static_cast<double>(el.m_value.number_float), true);
+            }
+        }
+        return false;
+    }
+
+    ///////////////////////
+    // Utility functions //
+    ///////////////////////
+
+    /*
+    @brief write a number to output input
+    @param[in] n number of type @a NumberType
+    @param[in] OutputIsLittleEndian Set to true if output data is
+                                 required to be little endian
+    @tparam NumberType the type of the number
+
+    @note This function needs to respect the system's endianness, because bytes
+          in CBOR, MessagePack, and UBJSON are stored in network order (big
+          endian) and therefore need reordering on little endian systems.
+          On the other hand, BSON and BJData use little endian and should reorder
+          on big endian systems.
+    */
+    template<typename NumberType>
+    void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
+    {
+        // step 1: write number to array of length NumberType
+        std::array<CharType, sizeof(NumberType)> vec{};
+        std::memcpy(vec.data(), &n, sizeof(NumberType));
+
+        // step 2: write array to output (with possible reordering)
+        if (is_little_endian != OutputIsLittleEndian)
+        {
+            // reverse byte order prior to conversion if necessary
+            std::reverse(vec.begin(), vec.end());
+        }
+
+        oa->write_characters(vec.data(), sizeof(NumberType));
+    }
+
+    void write_compact_float(const number_float_t n, detail::input_format_t format)
+    {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+        if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
+                static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
+                static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
+        {
+            oa->write_character(format == detail::input_format_t::cbor
+                                ? get_cbor_float_prefix(static_cast<float>(n))
+                                : get_msgpack_float_prefix(static_cast<float>(n)));
+            write_number(static_cast<float>(n));
+        }
+        else
+        {
+            oa->write_character(format == detail::input_format_t::cbor
+                                ? get_cbor_float_prefix(n)
+                                : get_msgpack_float_prefix(n));
+            write_number(n);
+        }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+    }
+
+  public:
+    // The following to_char_type functions are implement the conversion
+    // between uint8_t and CharType. In case CharType is not unsigned,
+    // such a conversion is required to allow values greater than 128.
+    // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
+    template < typename C = CharType,
+               enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
+    static constexpr CharType to_char_type(std::uint8_t x) noexcept
+    {
+        return *reinterpret_cast<char*>(&x);
+    }
+
+    template < typename C = CharType,
+               enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
+    static CharType to_char_type(std::uint8_t x) noexcept
+    {
+        static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
+        static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
+        CharType result;
+        std::memcpy(&result, &x, sizeof(x));
+        return result;
+    }
+
+    template<typename C = CharType,
+             enable_if_t<std::is_unsigned<C>::value>* = nullptr>
+    static constexpr CharType to_char_type(std::uint8_t x) noexcept
+    {
+        return x;
+    }
+
+    template < typename InputCharType, typename C = CharType,
+               enable_if_t <
+                   std::is_signed<C>::value &&
+                   std::is_signed<char>::value &&
+                   std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
+                   > * = nullptr >
+    static constexpr CharType to_char_type(InputCharType x) noexcept
+    {
+        return x;
+    }
+
+  private:
+    /// whether we can assume little endianness
+    const bool is_little_endian = little_endianness();
+
+    /// the output
+    output_adapter_t<CharType> oa = nullptr;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/output/serializer.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <algorithm> // reverse, remove, fill, find, none_of
+#include <array> // array
+#include <clocale> // localeconv, lconv
+#include <cmath> // labs, isfinite, isnan, signbit
+#include <cstddef> // size_t, ptrdiff_t
+#include <cstdint> // uint8_t
+#include <cstdio> // snprintf
+#include <limits> // numeric_limits
+#include <string> // string, char_traits
+#include <iomanip> // setfill, setw
+#include <type_traits> // is_same
+#include <utility> // move
+
+// #include <nlohmann/detail/conversions/to_chars.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <array> // array
+#include <cmath>   // signbit, isfinite
+#include <cstdint> // intN_t, uintN_t
+#include <cstring> // memcpy, memmove
+#include <limits> // numeric_limits
+#include <type_traits> // conditional
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+/*!
+@brief implements the Grisu2 algorithm for binary to decimal floating-point
+conversion.
+
+This implementation is a slightly modified version of the reference
+implementation which may be obtained from
+http://florian.loitsch.com/publications (bench.tar.gz).
+
+The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
+
+For a detailed description of the algorithm see:
+
+[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
+    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
+    Language Design and Implementation, PLDI 2010
+[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
+    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
+    Design and Implementation, PLDI 1996
+*/
+namespace dtoa_impl
+{
+
+template<typename Target, typename Source>
+Target reinterpret_bits(const Source source)
+{
+    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
+
+    Target target;
+    std::memcpy(&target, &source, sizeof(Source));
+    return target;
+}
+
+struct diyfp // f * 2^e
+{
+    static constexpr int kPrecision = 64; // = q
+
+    std::uint64_t f = 0;
+    int e = 0;
+
+    constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
+
+    /*!
+    @brief returns x - y
+    @pre x.e == y.e and x.f >= y.f
+    */
+    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
+    {
+        JSON_ASSERT(x.e == y.e);
+        JSON_ASSERT(x.f >= y.f);
+
+        return {x.f - y.f, x.e};
+    }
+
+    /*!
+    @brief returns x * y
+    @note The result is rounded. (Only the upper q bits are returned.)
+    */
+    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
+    {
+        static_assert(kPrecision == 64, "internal error");
+
+        // Computes:
+        //  f = round((x.f * y.f) / 2^q)
+        //  e = x.e + y.e + q
+
+        // Emulate the 64-bit * 64-bit multiplication:
+        //
+        // p = u * v
+        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
+        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
+        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
+        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
+        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
+        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
+        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
+        //
+        // (Since Q might be larger than 2^32 - 1)
+        //
+        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
+        //
+        // (Q_hi + H does not overflow a 64-bit int)
+        //
+        //   = p_lo + 2^64 p_hi
+
+        const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
+        const std::uint64_t u_hi = x.f >> 32u;
+        const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
+        const std::uint64_t v_hi = y.f >> 32u;
+
+        const std::uint64_t p0 = u_lo * v_lo;
+        const std::uint64_t p1 = u_lo * v_hi;
+        const std::uint64_t p2 = u_hi * v_lo;
+        const std::uint64_t p3 = u_hi * v_hi;
+
+        const std::uint64_t p0_hi = p0 >> 32u;
+        const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
+        const std::uint64_t p1_hi = p1 >> 32u;
+        const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
+        const std::uint64_t p2_hi = p2 >> 32u;
+
+        std::uint64_t Q = p0_hi + p1_lo + p2_lo;
+
+        // The full product might now be computed as
+        //
+        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
+        // p_lo = p0_lo + (Q << 32)
+        //
+        // But in this particular case here, the full p_lo is not required.
+        // Effectively we only need to add the highest bit in p_lo to p_hi (and
+        // Q_hi + 1 does not overflow).
+
+        Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
+
+        const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
+
+        return {h, x.e + y.e + 64};
+    }
+
+    /*!
+    @brief normalize x such that the significand is >= 2^(q-1)
+    @pre x.f != 0
+    */
+    static diyfp normalize(diyfp x) noexcept
+    {
+        JSON_ASSERT(x.f != 0);
+
+        while ((x.f >> 63u) == 0)
+        {
+            x.f <<= 1u;
+            x.e--;
+        }
+
+        return x;
+    }
+
+    /*!
+    @brief normalize x such that the result has the exponent E
+    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
+    */
+    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
+    {
+        const int delta = x.e - target_exponent;
+
+        JSON_ASSERT(delta >= 0);
+        JSON_ASSERT(((x.f << delta) >> delta) == x.f);
+
+        return {x.f << delta, target_exponent};
+    }
+};
+
+struct boundaries
+{
+    diyfp w;
+    diyfp minus;
+    diyfp plus;
+};
+
+/*!
+Compute the (normalized) diyfp representing the input number 'value' and its
+boundaries.
+
+@pre value must be finite and positive
+*/
+template<typename FloatType>
+boundaries compute_boundaries(FloatType value)
+{
+    JSON_ASSERT(std::isfinite(value));
+    JSON_ASSERT(value > 0);
+
+    // Convert the IEEE representation into a diyfp.
+    //
+    // If v is denormal:
+    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
+    // If v is normalized:
+    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
+
+    static_assert(std::numeric_limits<FloatType>::is_iec559,
+                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
+
+    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
+    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
+    constexpr int      kMinExp    = 1 - kBias;
+    constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
+
+    using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
+
+    const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
+    const std::uint64_t E = bits >> (kPrecision - 1);
+    const std::uint64_t F = bits & (kHiddenBit - 1);
+
+    const bool is_denormal = E == 0;
+    const diyfp v = is_denormal
+                    ? diyfp(F, kMinExp)
+                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
+
+    // Compute the boundaries m- and m+ of the floating-point value
+    // v = f * 2^e.
+    //
+    // Determine v- and v+, the floating-point predecessor and successor if v,
+    // respectively.
+    //
+    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
+    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
+    //
+    //      v+ = v + 2^e
+    //
+    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
+    // between m- and m+ round to v, regardless of how the input rounding
+    // algorithm breaks ties.
+    //
+    //      ---+-------------+-------------+-------------+-------------+---  (A)
+    //         v-            m-            v             m+            v+
+    //
+    //      -----------------+------+------+-------------+-------------+---  (B)
+    //                       v-     m-     v             m+            v+
+
+    const bool lower_boundary_is_closer = F == 0 && E > 1;
+    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
+    const diyfp m_minus = lower_boundary_is_closer
+                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
+                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
+
+    // Determine the normalized w+ = m+.
+    const diyfp w_plus = diyfp::normalize(m_plus);
+
+    // Determine w- = m- such that e_(w-) = e_(w+).
+    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
+
+    return {diyfp::normalize(v), w_minus, w_plus};
+}
+
+// Given normalized diyfp w, Grisu needs to find a (normalized) cached
+// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
+// within a certain range [alpha, gamma] (Definition 3.2 from [1])
+//
+//      alpha <= e = e_c + e_w + q <= gamma
+//
+// or
+//
+//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
+//                          <= f_c * f_w * 2^gamma
+//
+// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
+//
+//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
+//
+// or
+//
+//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
+//
+// The choice of (alpha,gamma) determines the size of the table and the form of
+// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
+// in practice:
+//
+// The idea is to cut the number c * w = f * 2^e into two parts, which can be
+// processed independently: An integral part p1, and a fractional part p2:
+//
+//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
+//              = (f div 2^-e) + (f mod 2^-e) * 2^e
+//              = p1 + p2 * 2^e
+//
+// The conversion of p1 into decimal form requires a series of divisions and
+// modulos by (a power of) 10. These operations are faster for 32-bit than for
+// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
+// achieved by choosing
+//
+//      -e >= 32   or   e <= -32 := gamma
+//
+// In order to convert the fractional part
+//
+//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
+//
+// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
+// d[-i] are extracted in order:
+//
+//      (10 * p2) div 2^-e = d[-1]
+//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
+//
+// The multiplication by 10 must not overflow. It is sufficient to choose
+//
+//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
+//
+// Since p2 = f mod 2^-e < 2^-e,
+//
+//      -e <= 60   or   e >= -60 := alpha
+
+constexpr int kAlpha = -60;
+constexpr int kGamma = -32;
+
+struct cached_power // c = f * 2^e ~= 10^k
+{
+    std::uint64_t f;
+    int e;
+    int k;
+};
+
+/*!
+For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
+power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
+satisfies (Definition 3.2 from [1])
+
+     alpha <= e_c + e + q <= gamma.
+*/
+inline cached_power get_cached_power_for_binary_exponent(int e)
+{
+    // Now
+    //
+    //      alpha <= e_c + e + q <= gamma                                    (1)
+    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
+    //
+    // and since the c's are normalized, 2^(q-1) <= f_c,
+    //
+    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
+    //      ==> 2^(alpha - e - 1) <= c
+    //
+    // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
+    //
+    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
+    //        = ceil( (alpha - e - 1) * log_10(2) )
+    //
+    // From the paper:
+    // "In theory the result of the procedure could be wrong since c is rounded,
+    //  and the computation itself is approximated [...]. In practice, however,
+    //  this simple function is sufficient."
+    //
+    // For IEEE double precision floating-point numbers converted into
+    // normalized diyfp's w = f * 2^e, with q = 64,
+    //
+    //      e >= -1022      (min IEEE exponent)
+    //           -52        (p - 1)
+    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
+    //           -11        (normalize the diyfp)
+    //         = -1137
+    //
+    // and
+    //
+    //      e <= +1023      (max IEEE exponent)
+    //           -52        (p - 1)
+    //           -11        (normalize the diyfp)
+    //         = 960
+    //
+    // This binary exponent range [-1137,960] results in a decimal exponent
+    // range [-307,324]. One does not need to store a cached power for each
+    // k in this range. For each such k it suffices to find a cached power
+    // such that the exponent of the product lies in [alpha,gamma].
+    // This implies that the difference of the decimal exponents of adjacent
+    // table entries must be less than or equal to
+    //
+    //      floor( (gamma - alpha) * log_10(2) ) = 8.
+    //
+    // (A smaller distance gamma-alpha would require a larger table.)
+
+    // NB:
+    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
+
+    constexpr int kCachedPowersMinDecExp = -300;
+    constexpr int kCachedPowersDecStep = 8;
+
+    static constexpr std::array<cached_power, 79> kCachedPowers =
+    {
+        {
+            { 0xAB70FE17C79AC6CA, -1060, -300 },
+            { 0xFF77B1FCBEBCDC4F, -1034, -292 },
+            { 0xBE5691EF416BD60C, -1007, -284 },
+            { 0x8DD01FAD907FFC3C,  -980, -276 },
+            { 0xD3515C2831559A83,  -954, -268 },
+            { 0x9D71AC8FADA6C9B5,  -927, -260 },
+            { 0xEA9C227723EE8BCB,  -901, -252 },
+            { 0xAECC49914078536D,  -874, -244 },
+            { 0x823C12795DB6CE57,  -847, -236 },
+            { 0xC21094364DFB5637,  -821, -228 },
+            { 0x9096EA6F3848984F,  -794, -220 },
+            { 0xD77485CB25823AC7,  -768, -212 },
+            { 0xA086CFCD97BF97F4,  -741, -204 },
+            { 0xEF340A98172AACE5,  -715, -196 },
+            { 0xB23867FB2A35B28E,  -688, -188 },
+            { 0x84C8D4DFD2C63F3B,  -661, -180 },
+            { 0xC5DD44271AD3CDBA,  -635, -172 },
+            { 0x936B9FCEBB25C996,  -608, -164 },
+            { 0xDBAC6C247D62A584,  -582, -156 },
+            { 0xA3AB66580D5FDAF6,  -555, -148 },
+            { 0xF3E2F893DEC3F126,  -529, -140 },
+            { 0xB5B5ADA8AAFF80B8,  -502, -132 },
+            { 0x87625F056C7C4A8B,  -475, -124 },
+            { 0xC9BCFF6034C13053,  -449, -116 },
+            { 0x964E858C91BA2655,  -422, -108 },
+            { 0xDFF9772470297EBD,  -396, -100 },
+            { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
+            { 0xF8A95FCF88747D94,  -343,  -84 },
+            { 0xB94470938FA89BCF,  -316,  -76 },
+            { 0x8A08F0F8BF0F156B,  -289,  -68 },
+            { 0xCDB02555653131B6,  -263,  -60 },
+            { 0x993FE2C6D07B7FAC,  -236,  -52 },
+            { 0xE45C10C42A2B3B06,  -210,  -44 },
+            { 0xAA242499697392D3,  -183,  -36 },
+            { 0xFD87B5F28300CA0E,  -157,  -28 },
+            { 0xBCE5086492111AEB,  -130,  -20 },
+            { 0x8CBCCC096F5088CC,  -103,  -12 },
+            { 0xD1B71758E219652C,   -77,   -4 },
+            { 0x9C40000000000000,   -50,    4 },
+            { 0xE8D4A51000000000,   -24,   12 },
+            { 0xAD78EBC5AC620000,     3,   20 },
+            { 0x813F3978F8940984,    30,   28 },
+            { 0xC097CE7BC90715B3,    56,   36 },
+            { 0x8F7E32CE7BEA5C70,    83,   44 },
+            { 0xD5D238A4ABE98068,   109,   52 },
+            { 0x9F4F2726179A2245,   136,   60 },
+            { 0xED63A231D4C4FB27,   162,   68 },
+            { 0xB0DE65388CC8ADA8,   189,   76 },
+            { 0x83C7088E1AAB65DB,   216,   84 },
+            { 0xC45D1DF942711D9A,   242,   92 },
+            { 0x924D692CA61BE758,   269,  100 },
+            { 0xDA01EE641A708DEA,   295,  108 },
+            { 0xA26DA3999AEF774A,   322,  116 },
+            { 0xF209787BB47D6B85,   348,  124 },
+            { 0xB454E4A179DD1877,   375,  132 },
+            { 0x865B86925B9BC5C2,   402,  140 },
+            { 0xC83553C5C8965D3D,   428,  148 },
+            { 0x952AB45CFA97A0B3,   455,  156 },
+            { 0xDE469FBD99A05FE3,   481,  164 },
+            { 0xA59BC234DB398C25,   508,  172 },
+            { 0xF6C69A72A3989F5C,   534,  180 },
+            { 0xB7DCBF5354E9BECE,   561,  188 },
+            { 0x88FCF317F22241E2,   588,  196 },
+            { 0xCC20CE9BD35C78A5,   614,  204 },
+            { 0x98165AF37B2153DF,   641,  212 },
+            { 0xE2A0B5DC971F303A,   667,  220 },
+            { 0xA8D9D1535CE3B396,   694,  228 },
+            { 0xFB9B7CD9A4A7443C,   720,  236 },
+            { 0xBB764C4CA7A44410,   747,  244 },
+            { 0x8BAB8EEFB6409C1A,   774,  252 },
+            { 0xD01FEF10A657842C,   800,  260 },
+            { 0x9B10A4E5E9913129,   827,  268 },
+            { 0xE7109BFBA19C0C9D,   853,  276 },
+            { 0xAC2820D9623BF429,   880,  284 },
+            { 0x80444B5E7AA7CF85,   907,  292 },
+            { 0xBF21E44003ACDD2D,   933,  300 },
+            { 0x8E679C2F5E44FF8F,   960,  308 },
+            { 0xD433179D9C8CB841,   986,  316 },
+            { 0x9E19DB92B4E31BA9,  1013,  324 },
+        }
+    };
+
+    // This computation gives exactly the same results for k as
+    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
+    // for |e| <= 1500, but doesn't require floating-point operations.
+    // NB: log_10(2) ~= 78913 / 2^18
+    JSON_ASSERT(e >= -1500);
+    JSON_ASSERT(e <=  1500);
+    const int f = kAlpha - e - 1;
+    const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
+
+    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
+    JSON_ASSERT(index >= 0);
+    JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
+
+    const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
+    JSON_ASSERT(kAlpha <= cached.e + e + 64);
+    JSON_ASSERT(kGamma >= cached.e + e + 64);
+
+    return cached;
+}
+
+/*!
+For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
+For n == 0, returns 1 and sets pow10 := 1.
+*/
+inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
+{
+    // LCOV_EXCL_START
+    if (n >= 1000000000)
+    {
+        pow10 = 1000000000;
+        return 10;
+    }
+    // LCOV_EXCL_STOP
+    if (n >= 100000000)
+    {
+        pow10 = 100000000;
+        return  9;
+    }
+    if (n >= 10000000)
+    {
+        pow10 = 10000000;
+        return  8;
+    }
+    if (n >= 1000000)
+    {
+        pow10 = 1000000;
+        return  7;
+    }
+    if (n >= 100000)
+    {
+        pow10 = 100000;
+        return  6;
+    }
+    if (n >= 10000)
+    {
+        pow10 = 10000;
+        return  5;
+    }
+    if (n >= 1000)
+    {
+        pow10 = 1000;
+        return  4;
+    }
+    if (n >= 100)
+    {
+        pow10 = 100;
+        return  3;
+    }
+    if (n >= 10)
+    {
+        pow10 = 10;
+        return  2;
+    }
+
+    pow10 = 1;
+    return 1;
+}
+
+inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
+                         std::uint64_t rest, std::uint64_t ten_k)
+{
+    JSON_ASSERT(len >= 1);
+    JSON_ASSERT(dist <= delta);
+    JSON_ASSERT(rest <= delta);
+    JSON_ASSERT(ten_k > 0);
+
+    //               <--------------------------- delta ---->
+    //                                  <---- dist --------->
+    // --------------[------------------+-------------------]--------------
+    //               M-                 w                   M+
+    //
+    //                                  ten_k
+    //                                <------>
+    //                                       <---- rest ---->
+    // --------------[------------------+----+--------------]--------------
+    //                                  w    V
+    //                                       = buf * 10^k
+    //
+    // ten_k represents a unit-in-the-last-place in the decimal representation
+    // stored in buf.
+    // Decrement buf by ten_k while this takes buf closer to w.
+
+    // The tests are written in this order to avoid overflow in unsigned
+    // integer arithmetic.
+
+    while (rest < dist
+            && delta - rest >= ten_k
+            && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
+    {
+        JSON_ASSERT(buf[len - 1] != '0');
+        buf[len - 1]--;
+        rest += ten_k;
+    }
+}
+
+/*!
+Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
+M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
+*/
+inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
+                             diyfp M_minus, diyfp w, diyfp M_plus)
+{
+    static_assert(kAlpha >= -60, "internal error");
+    static_assert(kGamma <= -32, "internal error");
+
+    // Generates the digits (and the exponent) of a decimal floating-point
+    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
+    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
+    //
+    //               <--------------------------- delta ---->
+    //                                  <---- dist --------->
+    // --------------[------------------+-------------------]--------------
+    //               M-                 w                   M+
+    //
+    // Grisu2 generates the digits of M+ from left to right and stops as soon as
+    // V is in [M-,M+].
+
+    JSON_ASSERT(M_plus.e >= kAlpha);
+    JSON_ASSERT(M_plus.e <= kGamma);
+
+    std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
+    std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
+
+    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
+    //
+    //      M+ = f * 2^e
+    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
+    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
+    //         = p1 + p2 * 2^e
+
+    const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
+
+    auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
+    std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
+
+    // 1)
+    //
+    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
+
+    JSON_ASSERT(p1 > 0);
+
+    std::uint32_t pow10{};
+    const int k = find_largest_pow10(p1, pow10);
+
+    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
+    //
+    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
+    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
+    //
+    //      M+ = p1                                             + p2 * 2^e
+    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
+    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
+    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
+    //
+    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
+    //
+    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
+    //
+    // but stop as soon as
+    //
+    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
+
+    int n = k;
+    while (n > 0)
+    {
+        // Invariants:
+        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
+        //      pow10 = 10^(n-1) <= p1 < 10^n
+        //
+        const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
+        const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
+        //
+        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
+        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
+        //
+        JSON_ASSERT(d <= 9);
+        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+        //
+        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
+        //
+        p1 = r;
+        n--;
+        //
+        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
+        //      pow10 = 10^n
+        //
+
+        // Now check if enough digits have been generated.
+        // Compute
+        //
+        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
+        //
+        // Note:
+        // Since rest and delta share the same exponent e, it suffices to
+        // compare the significands.
+        const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
+        if (rest <= delta)
+        {
+            // V = buffer * 10^n, with M- <= V <= M+.
+
+            decimal_exponent += n;
+
+            // We may now just stop. But instead look if the buffer could be
+            // decremented to bring V closer to w.
+            //
+            // pow10 = 10^n is now 1 ulp in the decimal representation V.
+            // The rounding procedure works with diyfp's with an implicit
+            // exponent of e.
+            //
+            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
+            //
+            const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
+            grisu2_round(buffer, length, dist, delta, rest, ten_n);
+
+            return;
+        }
+
+        pow10 /= 10;
+        //
+        //      pow10 = 10^(n-1) <= p1 < 10^n
+        // Invariants restored.
+    }
+
+    // 2)
+    //
+    // The digits of the integral part have been generated:
+    //
+    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
+    //         = buffer            + p2 * 2^e
+    //
+    // Now generate the digits of the fractional part p2 * 2^e.
+    //
+    // Note:
+    // No decimal point is generated: the exponent is adjusted instead.
+    //
+    // p2 actually represents the fraction
+    //
+    //      p2 * 2^e
+    //          = p2 / 2^-e
+    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
+    //
+    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
+    //
+    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
+    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
+    //
+    // using
+    //
+    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
+    //                = (                   d) * 2^-e + (                   r)
+    //
+    // or
+    //      10^m * p2 * 2^e = d + r * 2^e
+    //
+    // i.e.
+    //
+    //      M+ = buffer + p2 * 2^e
+    //         = buffer + 10^-m * (d + r * 2^e)
+    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
+    //
+    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
+
+    JSON_ASSERT(p2 > delta);
+
+    int m = 0;
+    for (;;)
+    {
+        // Invariant:
+        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
+        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
+        //
+        JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
+        p2 *= 10;
+        const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
+        const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
+        //
+        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
+        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
+        //
+        JSON_ASSERT(d <= 9);
+        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+        //
+        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
+        //
+        p2 = r;
+        m++;
+        //
+        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
+        // Invariant restored.
+
+        // Check if enough digits have been generated.
+        //
+        //      10^-m * p2 * 2^e <= delta * 2^e
+        //              p2 * 2^e <= 10^m * delta * 2^e
+        //                    p2 <= 10^m * delta
+        delta *= 10;
+        dist  *= 10;
+        if (p2 <= delta)
+        {
+            break;
+        }
+    }
+
+    // V = buffer * 10^-m, with M- <= V <= M+.
+
+    decimal_exponent -= m;
+
+    // 1 ulp in the decimal representation is now 10^-m.
+    // Since delta and dist are now scaled by 10^m, we need to do the
+    // same with ulp in order to keep the units in sync.
+    //
+    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
+    //
+    const std::uint64_t ten_m = one.f;
+    grisu2_round(buffer, length, dist, delta, p2, ten_m);
+
+    // By construction this algorithm generates the shortest possible decimal
+    // number (Loitsch, Theorem 6.2) which rounds back to w.
+    // For an input number of precision p, at least
+    //
+    //      N = 1 + ceil(p * log_10(2))
+    //
+    // decimal digits are sufficient to identify all binary floating-point
+    // numbers (Matula, "In-and-Out conversions").
+    // This implies that the algorithm does not produce more than N decimal
+    // digits.
+    //
+    //      N = 17 for p = 53 (IEEE double precision)
+    //      N = 9  for p = 24 (IEEE single precision)
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline void grisu2(char* buf, int& len, int& decimal_exponent,
+                   diyfp m_minus, diyfp v, diyfp m_plus)
+{
+    JSON_ASSERT(m_plus.e == m_minus.e);
+    JSON_ASSERT(m_plus.e == v.e);
+
+    //  --------(-----------------------+-----------------------)--------    (A)
+    //          m-                      v                       m+
+    //
+    //  --------------------(-----------+-----------------------)--------    (B)
+    //                      m-          v                       m+
+    //
+    // First scale v (and m- and m+) such that the exponent is in the range
+    // [alpha, gamma].
+
+    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
+
+    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
+
+    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
+    const diyfp w       = diyfp::mul(v,       c_minus_k);
+    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
+    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
+
+    //  ----(---+---)---------------(---+---)---------------(---+---)----
+    //          w-                      w                       w+
+    //          = c*m-                  = c*v                   = c*m+
+    //
+    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
+    // w+ are now off by a small amount.
+    // In fact:
+    //
+    //      w - v * 10^k < 1 ulp
+    //
+    // To account for this inaccuracy, add resp. subtract 1 ulp.
+    //
+    //  --------+---[---------------(---+---)---------------]---+--------
+    //          w-  M-                  w                   M+  w+
+    //
+    // Now any number in [M-, M+] (bounds included) will round to w when input,
+    // regardless of how the input rounding algorithm breaks ties.
+    //
+    // And digit_gen generates the shortest possible such number in [M-, M+].
+    // Note that this does not mean that Grisu2 always generates the shortest
+    // possible number in the interval (m-, m+).
+    const diyfp M_minus(w_minus.f + 1, w_minus.e);
+    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
+
+    decimal_exponent = -cached.k; // = -(-k) = k
+
+    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+template<typename FloatType>
+JSON_HEDLEY_NON_NULL(1)
+void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
+{
+    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
+                  "internal error: not enough precision");
+
+    JSON_ASSERT(std::isfinite(value));
+    JSON_ASSERT(value > 0);
+
+    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
+    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
+    // decimal representations are not exactly "short".
+    //
+    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
+    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
+    // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
+    // does.
+    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
+    // representation using the corresponding std::from_chars function recovers value exactly". That
+    // indicates that single precision floating-point numbers should be recovered using
+    // 'std::strtof'.
+    //
+    // NB: If the neighbors are computed for single-precision numbers, there is a single float
+    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
+    //     value is off by 1 ulp.
+#if 0
+    const boundaries w = compute_boundaries(static_cast<double>(value));
+#else
+    const boundaries w = compute_boundaries(value);
+#endif
+
+    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
+}
+
+/*!
+@brief appends a decimal representation of e to buf
+@return a pointer to the element following the exponent.
+@pre -1000 < e < 1000
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* append_exponent(char* buf, int e)
+{
+    JSON_ASSERT(e > -1000);
+    JSON_ASSERT(e <  1000);
+
+    if (e < 0)
+    {
+        e = -e;
+        *buf++ = '-';
+    }
+    else
+    {
+        *buf++ = '+';
+    }
+
+    auto k = static_cast<std::uint32_t>(e);
+    if (k < 10)
+    {
+        // Always print at least two digits in the exponent.
+        // This is for compatibility with printf("%g").
+        *buf++ = '0';
+        *buf++ = static_cast<char>('0' + k);
+    }
+    else if (k < 100)
+    {
+        *buf++ = static_cast<char>('0' + k / 10);
+        k %= 10;
+        *buf++ = static_cast<char>('0' + k);
+    }
+    else
+    {
+        *buf++ = static_cast<char>('0' + k / 100);
+        k %= 100;
+        *buf++ = static_cast<char>('0' + k / 10);
+        k %= 10;
+        *buf++ = static_cast<char>('0' + k);
+    }
+
+    return buf;
+}
+
+/*!
+@brief prettify v = buf * 10^decimal_exponent
+
+If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
+notation. Otherwise it will be printed in exponential notation.
+
+@pre min_exp < 0
+@pre max_exp > 0
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* format_buffer(char* buf, int len, int decimal_exponent,
+                           int min_exp, int max_exp)
+{
+    JSON_ASSERT(min_exp < 0);
+    JSON_ASSERT(max_exp > 0);
+
+    const int k = len;
+    const int n = len + decimal_exponent;
+
+    // v = buf * 10^(n-k)
+    // k is the length of the buffer (number of decimal digits)
+    // n is the position of the decimal point relative to the start of the buffer.
+
+    if (k <= n && n <= max_exp)
+    {
+        // digits[000]
+        // len <= max_exp + 2
+
+        std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
+        // Make it look like a floating-point number (#362, #378)
+        buf[n + 0] = '.';
+        buf[n + 1] = '0';
+        return buf + (static_cast<size_t>(n) + 2);
+    }
+
+    if (0 < n && n <= max_exp)
+    {
+        // dig.its
+        // len <= max_digits10 + 1
+
+        JSON_ASSERT(k > n);
+
+        std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
+        buf[n] = '.';
+        return buf + (static_cast<size_t>(k) + 1U);
+    }
+
+    if (min_exp < n && n <= 0)
+    {
+        // 0.[000]digits
+        // len <= 2 + (-min_exp - 1) + max_digits10
+
+        std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
+        buf[0] = '0';
+        buf[1] = '.';
+        std::memset(buf + 2, '0', static_cast<size_t>(-n));
+        return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
+    }
+
+    if (k == 1)
+    {
+        // dE+123
+        // len <= 1 + 5
+
+        buf += 1;
+    }
+    else
+    {
+        // d.igitsE+123
+        // len <= max_digits10 + 1 + 5
+
+        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
+        buf[1] = '.';
+        buf += 1 + static_cast<size_t>(k);
+    }
+
+    *buf++ = 'e';
+    return append_exponent(buf, n - 1);
+}
+
+}  // namespace dtoa_impl
+
+/*!
+@brief generates a decimal representation of the floating-point number value in [first, last).
+
+The format of the resulting decimal representation is similar to printf's %g
+format. Returns an iterator pointing past-the-end of the decimal representation.
+
+@note The input number must be finite, i.e. NaN's and Inf's are not supported.
+@note The buffer must be large enough.
+@note The result is NOT null-terminated.
+*/
+template<typename FloatType>
+JSON_HEDLEY_NON_NULL(1, 2)
+JSON_HEDLEY_RETURNS_NON_NULL
+char* to_chars(char* first, const char* last, FloatType value)
+{
+    static_cast<void>(last); // maybe unused - fix warning
+    JSON_ASSERT(std::isfinite(value));
+
+    // Use signbit(value) instead of (value < 0) since signbit works for -0.
+    if (std::signbit(value))
+    {
+        value = -value;
+        *first++ = '-';
+    }
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+    if (value == 0) // +-0
+    {
+        *first++ = '0';
+        // Make it look like a floating-point number (#362, #378)
+        *first++ = '.';
+        *first++ = '0';
+        return first;
+    }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
+
+    // Compute v = buffer * 10^decimal_exponent.
+    // The decimal digits are stored in the buffer, which needs to be interpreted
+    // as an unsigned decimal integer.
+    // len is the length of the buffer, i.e. the number of decimal digits.
+    int len = 0;
+    int decimal_exponent = 0;
+    dtoa_impl::grisu2(first, len, decimal_exponent, value);
+
+    JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
+
+    // Format the buffer like printf("%.*g", prec, value)
+    constexpr int kMinExp = -4;
+    // Use digits10 here to increase compatibility with version 2.
+    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
+
+    JSON_ASSERT(last - first >= kMaxExp + 2);
+    JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
+    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
+
+    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
+}
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+///////////////////
+// serialization //
+///////////////////
+
+/// how to treat decoding errors
+enum class error_handler_t
+{
+    strict,  ///< throw a type_error exception in case of invalid UTF-8
+    replace, ///< replace invalid UTF-8 sequences with U+FFFD
+    ignore   ///< ignore invalid UTF-8 sequences
+};
+
+template<typename BasicJsonType>
+class serializer
+{
+    using string_t = typename BasicJsonType::string_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using binary_char_t = typename BasicJsonType::binary_t::value_type;
+    static constexpr std::uint8_t UTF8_ACCEPT = 0;
+    static constexpr std::uint8_t UTF8_REJECT = 1;
+
+  public:
+    /*!
+    @param[in] s  output stream to serialize to
+    @param[in] ichar  indentation character to use
+    @param[in] error_handler_  how to react on decoding errors
+    */
+    serializer(output_adapter_t<char> s, const char ichar,
+               error_handler_t error_handler_ = error_handler_t::strict)
+        : o(std::move(s))
+        , loc(std::localeconv())
+        , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
+        , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
+        , indent_char(ichar)
+        , indent_string(512, indent_char)
+        , error_handler(error_handler_)
+    {}
+
+    // delete because of pointer members
+    serializer(const serializer&) = delete;
+    serializer& operator=(const serializer&) = delete;
+    serializer(serializer&&) = delete;
+    serializer& operator=(serializer&&) = delete;
+    ~serializer() = default;
+
+    /*!
+    @brief internal implementation of the serialization function
+
+    This function is called by the public member function dump and organizes
+    the serialization internally. The indentation level is propagated as
+    additional parameter. In case of arrays and objects, the function is
+    called recursively.
+
+    - strings and object keys are escaped using `escape_string()`
+    - integer numbers are converted implicitly via `operator<<`
+    - floating-point numbers are converted to a string using `"%g"` format
+    - binary values are serialized as objects containing the subtype and the
+      byte array
+
+    @param[in] val               value to serialize
+    @param[in] pretty_print      whether the output shall be pretty-printed
+    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+    in the output are escaped with `\uXXXX` sequences, and the result consists
+    of ASCII characters only.
+    @param[in] indent_step       the indent level
+    @param[in] current_indent    the current indent level (only used internally)
+    */
+    void dump(const BasicJsonType& val,
+              const bool pretty_print,
+              const bool ensure_ascii,
+              const unsigned int indent_step,
+              const unsigned int current_indent = 0)
+    {
+        switch (val.m_type)
+        {
+            case value_t::object:
+            {
+                if (val.m_value.object->empty())
+                {
+                    o->write_characters("{}", 2);
+                    return;
+                }
+
+                if (pretty_print)
+                {
+                    o->write_characters("{\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    // first n-1 elements
+                    auto i = val.m_value.object->cbegin();
+                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+                    {
+                        o->write_characters(indent_string.c_str(), new_indent);
+                        o->write_character('\"');
+                        dump_escaped(i->first, ensure_ascii);
+                        o->write_characters("\": ", 3);
+                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
+                        o->write_characters(",\n", 2);
+                    }
+
+                    // last element
+                    JSON_ASSERT(i != val.m_value.object->cend());
+                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
+                    o->write_characters(indent_string.c_str(), new_indent);
+                    o->write_character('\"');
+                    dump_escaped(i->first, ensure_ascii);
+                    o->write_characters("\": ", 3);
+                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
+
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character('}');
+                }
+                else
+                {
+                    o->write_character('{');
+
+                    // first n-1 elements
+                    auto i = val.m_value.object->cbegin();
+                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+                    {
+                        o->write_character('\"');
+                        dump_escaped(i->first, ensure_ascii);
+                        o->write_characters("\":", 2);
+                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
+                        o->write_character(',');
+                    }
+
+                    // last element
+                    JSON_ASSERT(i != val.m_value.object->cend());
+                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
+                    o->write_character('\"');
+                    dump_escaped(i->first, ensure_ascii);
+                    o->write_characters("\":", 2);
+                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
+
+                    o->write_character('}');
+                }
+
+                return;
+            }
+
+            case value_t::array:
+            {
+                if (val.m_value.array->empty())
+                {
+                    o->write_characters("[]", 2);
+                    return;
+                }
+
+                if (pretty_print)
+                {
+                    o->write_characters("[\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    // first n-1 elements
+                    for (auto i = val.m_value.array->cbegin();
+                            i != val.m_value.array->cend() - 1; ++i)
+                    {
+                        o->write_characters(indent_string.c_str(), new_indent);
+                        dump(*i, true, ensure_ascii, indent_step, new_indent);
+                        o->write_characters(",\n", 2);
+                    }
+
+                    // last element
+                    JSON_ASSERT(!val.m_value.array->empty());
+                    o->write_characters(indent_string.c_str(), new_indent);
+                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
+
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character(']');
+                }
+                else
+                {
+                    o->write_character('[');
+
+                    // first n-1 elements
+                    for (auto i = val.m_value.array->cbegin();
+                            i != val.m_value.array->cend() - 1; ++i)
+                    {
+                        dump(*i, false, ensure_ascii, indent_step, current_indent);
+                        o->write_character(',');
+                    }
+
+                    // last element
+                    JSON_ASSERT(!val.m_value.array->empty());
+                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
+
+                    o->write_character(']');
+                }
+
+                return;
+            }
+
+            case value_t::string:
+            {
+                o->write_character('\"');
+                dump_escaped(*val.m_value.string, ensure_ascii);
+                o->write_character('\"');
+                return;
+            }
+
+            case value_t::binary:
+            {
+                if (pretty_print)
+                {
+                    o->write_characters("{\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    o->write_characters(indent_string.c_str(), new_indent);
+
+                    o->write_characters("\"bytes\": [", 10);
+
+                    if (!val.m_value.binary->empty())
+                    {
+                        for (auto i = val.m_value.binary->cbegin();
+                                i != val.m_value.binary->cend() - 1; ++i)
+                        {
+                            dump_integer(*i);
+                            o->write_characters(", ", 2);
+                        }
+                        dump_integer(val.m_value.binary->back());
+                    }
+
+                    o->write_characters("],\n", 3);
+                    o->write_characters(indent_string.c_str(), new_indent);
+
+                    o->write_characters("\"subtype\": ", 11);
+                    if (val.m_value.binary->has_subtype())
+                    {
+                        dump_integer(val.m_value.binary->subtype());
+                    }
+                    else
+                    {
+                        o->write_characters("null", 4);
+                    }
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character('}');
+                }
+                else
+                {
+                    o->write_characters("{\"bytes\":[", 10);
+
+                    if (!val.m_value.binary->empty())
+                    {
+                        for (auto i = val.m_value.binary->cbegin();
+                                i != val.m_value.binary->cend() - 1; ++i)
+                        {
+                            dump_integer(*i);
+                            o->write_character(',');
+                        }
+                        dump_integer(val.m_value.binary->back());
+                    }
+
+                    o->write_characters("],\"subtype\":", 12);
+                    if (val.m_value.binary->has_subtype())
+                    {
+                        dump_integer(val.m_value.binary->subtype());
+                        o->write_character('}');
+                    }
+                    else
+                    {
+                        o->write_characters("null}", 5);
+                    }
+                }
+                return;
+            }
+
+            case value_t::boolean:
+            {
+                if (val.m_value.boolean)
+                {
+                    o->write_characters("true", 4);
+                }
+                else
+                {
+                    o->write_characters("false", 5);
+                }
+                return;
+            }
+
+            case value_t::number_integer:
+            {
+                dump_integer(val.m_value.number_integer);
+                return;
+            }
+
+            case value_t::number_unsigned:
+            {
+                dump_integer(val.m_value.number_unsigned);
+                return;
+            }
+
+            case value_t::number_float:
+            {
+                dump_float(val.m_value.number_float);
+                return;
+            }
+
+            case value_t::discarded:
+            {
+                o->write_characters("<discarded>", 11);
+                return;
+            }
+
+            case value_t::null:
+            {
+                o->write_characters("null", 4);
+                return;
+            }
+
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /*!
+    @brief dump escaped string
+
+    Escape a string by replacing certain special characters by a sequence of an
+    escape character (backslash) and another character and other control
+    characters by a sequence of "\u" followed by a four-digit hex
+    representation. The escaped string is written to output stream @a o.
+
+    @param[in] s  the string to escape
+    @param[in] ensure_ascii  whether to escape non-ASCII characters with
+                             \uXXXX sequences
+
+    @complexity Linear in the length of string @a s.
+    */
+    void dump_escaped(const string_t& s, const bool ensure_ascii)
+    {
+        std::uint32_t codepoint{};
+        std::uint8_t state = UTF8_ACCEPT;
+        std::size_t bytes = 0;  // number of bytes written to string_buffer
+
+        // number of bytes written at the point of the last valid byte
+        std::size_t bytes_after_last_accept = 0;
+        std::size_t undumped_chars = 0;
+
+        for (std::size_t i = 0; i < s.size(); ++i)
+        {
+            const auto byte = static_cast<std::uint8_t>(s[i]);
+
+            switch (decode(state, codepoint, byte))
+            {
+                case UTF8_ACCEPT:  // decode found a new code point
+                {
+                    switch (codepoint)
+                    {
+                        case 0x08: // backspace
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'b';
+                            break;
+                        }
+
+                        case 0x09: // horizontal tab
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 't';
+                            break;
+                        }
+
+                        case 0x0A: // newline
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'n';
+                            break;
+                        }
+
+                        case 0x0C: // formfeed
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'f';
+                            break;
+                        }
+
+                        case 0x0D: // carriage return
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'r';
+                            break;
+                        }
+
+                        case 0x22: // quotation mark
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = '\"';
+                            break;
+                        }
+
+                        case 0x5C: // reverse solidus
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = '\\';
+                            break;
+                        }
+
+                        default:
+                        {
+                            // escape control characters (0x00..0x1F) or, if
+                            // ensure_ascii parameter is used, non-ASCII characters
+                            if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
+                            {
+                                if (codepoint <= 0xFFFF)
+                                {
+                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
+                                                                      static_cast<std::uint16_t>(codepoint)));
+                                    bytes += 6;
+                                }
+                                else
+                                {
+                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
+                                                                      static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
+                                                                      static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
+                                    bytes += 12;
+                                }
+                            }
+                            else
+                            {
+                                // copy byte to buffer (all previous bytes
+                                // been copied have in default case above)
+                                string_buffer[bytes++] = s[i];
+                            }
+                            break;
+                        }
+                    }
+
+                    // write buffer and reset index; there must be 13 bytes
+                    // left, as this is the maximal number of bytes to be
+                    // written ("\uxxxx\uxxxx\0") for one code point
+                    if (string_buffer.size() - bytes < 13)
+                    {
+                        o->write_characters(string_buffer.data(), bytes);
+                        bytes = 0;
+                    }
+
+                    // remember the byte position of this accept
+                    bytes_after_last_accept = bytes;
+                    undumped_chars = 0;
+                    break;
+                }
+
+                case UTF8_REJECT:  // decode found invalid UTF-8 byte
+                {
+                    switch (error_handler)
+                    {
+                        case error_handler_t::strict:
+                        {
+                            JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
+                        }
+
+                        case error_handler_t::ignore:
+                        case error_handler_t::replace:
+                        {
+                            // in case we saw this character the first time, we
+                            // would like to read it again, because the byte
+                            // may be OK for itself, but just not OK for the
+                            // previous sequence
+                            if (undumped_chars > 0)
+                            {
+                                --i;
+                            }
+
+                            // reset length buffer to the last accepted index;
+                            // thus removing/ignoring the invalid characters
+                            bytes = bytes_after_last_accept;
+
+                            if (error_handler == error_handler_t::replace)
+                            {
+                                // add a replacement character
+                                if (ensure_ascii)
+                                {
+                                    string_buffer[bytes++] = '\\';
+                                    string_buffer[bytes++] = 'u';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'd';
+                                }
+                                else
+                                {
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
+                                }
+
+                                // write buffer and reset index; there must be 13 bytes
+                                // left, as this is the maximal number of bytes to be
+                                // written ("\uxxxx\uxxxx\0") for one code point
+                                if (string_buffer.size() - bytes < 13)
+                                {
+                                    o->write_characters(string_buffer.data(), bytes);
+                                    bytes = 0;
+                                }
+
+                                bytes_after_last_accept = bytes;
+                            }
+
+                            undumped_chars = 0;
+
+                            // continue processing the string
+                            state = UTF8_ACCEPT;
+                            break;
+                        }
+
+                        default:            // LCOV_EXCL_LINE
+                            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+                    }
+                    break;
+                }
+
+                default:  // decode found yet incomplete multi-byte code point
+                {
+                    if (!ensure_ascii)
+                    {
+                        // code point will not be escaped - copy byte to buffer
+                        string_buffer[bytes++] = s[i];
+                    }
+                    ++undumped_chars;
+                    break;
+                }
+            }
+        }
+
+        // we finished processing the string
+        if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
+        {
+            // write buffer
+            if (bytes > 0)
+            {
+                o->write_characters(string_buffer.data(), bytes);
+            }
+        }
+        else
+        {
+            // we finish reading, but do not accept: string was incomplete
+            switch (error_handler)
+            {
+                case error_handler_t::strict:
+                {
+                    JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
+                }
+
+                case error_handler_t::ignore:
+                {
+                    // write all accepted bytes
+                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
+                    break;
+                }
+
+                case error_handler_t::replace:
+                {
+                    // write all accepted bytes
+                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
+                    // add a replacement character
+                    if (ensure_ascii)
+                    {
+                        o->write_characters("\\ufffd", 6);
+                    }
+                    else
+                    {
+                        o->write_characters("\xEF\xBF\xBD", 3);
+                    }
+                    break;
+                }
+
+                default:            // LCOV_EXCL_LINE
+                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+            }
+        }
+    }
+
+  private:
+    /*!
+    @brief count digits
+
+    Count the number of decimal (base 10) digits for an input unsigned integer.
+
+    @param[in] x  unsigned integer number to count its digits
+    @return    number of decimal digits
+    */
+    inline unsigned int count_digits(number_unsigned_t x) noexcept
+    {
+        unsigned int n_digits = 1;
+        for (;;)
+        {
+            if (x < 10)
+            {
+                return n_digits;
+            }
+            if (x < 100)
+            {
+                return n_digits + 1;
+            }
+            if (x < 1000)
+            {
+                return n_digits + 2;
+            }
+            if (x < 10000)
+            {
+                return n_digits + 3;
+            }
+            x = x / 10000u;
+            n_digits += 4;
+        }
+    }
+
+    /*!
+     * @brief convert a byte to a uppercase hex representation
+     * @param[in] byte byte to represent
+     * @return representation ("00".."FF")
+     */
+    static std::string hex_bytes(std::uint8_t byte)
+    {
+        std::string result = "FF";
+        constexpr const char* nibble_to_hex = "0123456789ABCDEF";
+        result[0] = nibble_to_hex[byte / 16];
+        result[1] = nibble_to_hex[byte % 16];
+        return result;
+    }
+
+    // templates to avoid warnings about useless casts
+    template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
+    bool is_negative_number(NumberType x)
+    {
+        return x < 0;
+    }
+
+    template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
+    bool is_negative_number(NumberType /*unused*/)
+    {
+        return false;
+    }
+
+    /*!
+    @brief dump an integer
+
+    Dump a given integer to output stream @a o. Works internally with
+    @a number_buffer.
+
+    @param[in] x  integer number (signed or unsigned) to dump
+    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
+    */
+    template < typename NumberType, detail::enable_if_t <
+                   std::is_integral<NumberType>::value ||
+                   std::is_same<NumberType, number_unsigned_t>::value ||
+                   std::is_same<NumberType, number_integer_t>::value ||
+                   std::is_same<NumberType, binary_char_t>::value,
+                   int > = 0 >
+    void dump_integer(NumberType x)
+    {
+        static constexpr std::array<std::array<char, 2>, 100> digits_to_99
+        {
+            {
+                {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
+                {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
+                {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
+                {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
+                {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
+                {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
+                {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
+                {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
+                {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
+                {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
+            }
+        };
+
+        // special case for "0"
+        if (x == 0)
+        {
+            o->write_character('0');
+            return;
+        }
+
+        // use a pointer to fill the buffer
+        auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+
+        number_unsigned_t abs_value;
+
+        unsigned int n_chars{};
+
+        if (is_negative_number(x))
+        {
+            *buffer_ptr = '-';
+            abs_value = remove_sign(static_cast<number_integer_t>(x));
+
+            // account one more byte for the minus sign
+            n_chars = 1 + count_digits(abs_value);
+        }
+        else
+        {
+            abs_value = static_cast<number_unsigned_t>(x);
+            n_chars = count_digits(abs_value);
+        }
+
+        // spare 1 byte for '\0'
+        JSON_ASSERT(n_chars < number_buffer.size() - 1);
+
+        // jump to the end to generate the string from backward,
+        // so we later avoid reversing the result
+        buffer_ptr += n_chars;
+
+        // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
+        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
+        while (abs_value >= 100)
+        {
+            const auto digits_index = static_cast<unsigned>((abs_value % 100));
+            abs_value /= 100;
+            *(--buffer_ptr) = digits_to_99[digits_index][1];
+            *(--buffer_ptr) = digits_to_99[digits_index][0];
+        }
+
+        if (abs_value >= 10)
+        {
+            const auto digits_index = static_cast<unsigned>(abs_value);
+            *(--buffer_ptr) = digits_to_99[digits_index][1];
+            *(--buffer_ptr) = digits_to_99[digits_index][0];
+        }
+        else
+        {
+            *(--buffer_ptr) = static_cast<char>('0' + abs_value);
+        }
+
+        o->write_characters(number_buffer.data(), n_chars);
+    }
+
+    /*!
+    @brief dump a floating-point number
+
+    Dump a given floating-point number to output stream @a o. Works internally
+    with @a number_buffer.
+
+    @param[in] x  floating-point number to dump
+    */
+    void dump_float(number_float_t x)
+    {
+        // NaN / inf
+        if (!std::isfinite(x))
+        {
+            o->write_characters("null", 4);
+            return;
+        }
+
+        // If number_float_t is an IEEE-754 single or double precision number,
+        // use the Grisu2 algorithm to produce short numbers which are
+        // guaranteed to round-trip, using strtof and strtod, resp.
+        //
+        // NB: The test below works if <long double> == <double>.
+        static constexpr bool is_ieee_single_or_double
+            = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
+              (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
+
+        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
+    }
+
+    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
+    {
+        auto* begin = number_buffer.data();
+        auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
+
+        o->write_characters(begin, static_cast<size_t>(end - begin));
+    }
+
+    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
+    {
+        // get number of digits for a float -> text -> float round-trip
+        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
+
+        // the actual conversion
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
+
+        // negative value indicates an error
+        JSON_ASSERT(len > 0);
+        // check if buffer was large enough
+        JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
+
+        // erase thousands separator
+        if (thousands_sep != '\0')
+        {
+            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
+            const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
+            std::fill(end, number_buffer.end(), '\0');
+            JSON_ASSERT((end - number_buffer.begin()) <= len);
+            len = (end - number_buffer.begin());
+        }
+
+        // convert decimal point to '.'
+        if (decimal_point != '\0' && decimal_point != '.')
+        {
+            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
+            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
+            if (dec_pos != number_buffer.end())
+            {
+                *dec_pos = '.';
+            }
+        }
+
+        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
+
+        // determine if we need to append ".0"
+        const bool value_is_int_like =
+            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
+                         [](char c)
+        {
+            return c == '.' || c == 'e';
+        });
+
+        if (value_is_int_like)
+        {
+            o->write_characters(".0", 2);
+        }
+    }
+
+    /*!
+    @brief check whether a string is UTF-8 encoded
+
+    The function checks each byte of a string whether it is UTF-8 encoded. The
+    result of the check is stored in the @a state parameter. The function must
+    be called initially with state 0 (accept). State 1 means the string must
+    be rejected, because the current byte is not allowed. If the string is
+    completely processed, but the state is non-zero, the string ended
+    prematurely; that is, the last byte indicated more bytes should have
+    followed.
+
+    @param[in,out] state  the state of the decoding
+    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
+    @param[in] byte       next byte to decode
+    @return               new state
+
+    @note The function has been edited: a std::array is used.
+
+    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+    */
+    static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
+    {
+        static const std::array<std::uint8_t, 400> utf8d =
+        {
+            {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
+                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
+                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
+                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
+                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
+                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
+                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
+                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
+                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
+                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
+                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
+            }
+        };
+
+        JSON_ASSERT(byte < utf8d.size());
+        const std::uint8_t type = utf8d[byte];
+
+        codep = (state != UTF8_ACCEPT)
+                ? (byte & 0x3fu) | (codep << 6u)
+                : (0xFFu >> type) & (byte);
+
+        std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
+        JSON_ASSERT(index < 400);
+        state = utf8d[index];
+        return state;
+    }
+
+    /*
+     * Overload to make the compiler happy while it is instantiating
+     * dump_integer for number_unsigned_t.
+     * Must never be called.
+     */
+    number_unsigned_t remove_sign(number_unsigned_t x)
+    {
+        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        return x; // LCOV_EXCL_LINE
+    }
+
+    /*
+     * Helper function for dump_integer
+     *
+     * This function takes a negative signed integer and returns its absolute
+     * value as unsigned integer. The plus/minus shuffling is necessary as we can
+     * not directly remove the sign of an arbitrary signed integer as the
+     * absolute values of INT_MIN and INT_MAX are usually not the same. See
+     * #1708 for details.
+     */
+    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
+    {
+        JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
+        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
+    }
+
+  private:
+    /// the output of the serializer
+    output_adapter_t<char> o = nullptr;
+
+    /// a (hopefully) large enough character buffer
+    std::array<char, 64> number_buffer{{}};
+
+    /// the locale
+    const std::lconv* loc = nullptr;
+    /// the locale's thousand separator character
+    const char thousands_sep = '\0';
+    /// the locale's decimal point character
+    const char decimal_point = '\0';
+
+    /// string buffer
+    std::array<char, 512> string_buffer{{}};
+
+    /// the indentation character
+    const char indent_char;
+    /// the indentation string
+    string_t indent_string;
+
+    /// error_handler how to react on decoding errors
+    const error_handler_t error_handler;
+};
+
+}  // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/value_t.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+
+// #include <nlohmann/ordered_map.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <functional> // equal_to, less
+#include <initializer_list> // initializer_list
+#include <iterator> // input_iterator_tag, iterator_traits
+#include <memory> // allocator
+#include <stdexcept> // for out_of_range
+#include <type_traits> // enable_if, is_convertible
+#include <utility> // pair
+#include <vector> // vector
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/// ordered_map: a minimal map-like container that preserves insertion order
+/// for use within nlohmann::basic_json<ordered_map>
+template <class Key, class T, class IgnoredLess = std::less<Key>,
+          class Allocator = std::allocator<std::pair<const Key, T>>>
+                  struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
+{
+    using key_type = Key;
+    using mapped_type = T;
+    using Container = std::vector<std::pair<const Key, T>, Allocator>;
+    using iterator = typename Container::iterator;
+    using const_iterator = typename Container::const_iterator;
+    using size_type = typename Container::size_type;
+    using value_type = typename Container::value_type;
+#ifdef JSON_HAS_CPP_14
+    using key_compare = std::equal_to<>;
+#else
+    using key_compare = std::equal_to<Key>;
+#endif
+
+    // Explicit constructors instead of `using Container::Container`
+    // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
+    ordered_map() noexcept(noexcept(Container())) : Container{} {}
+    explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
+    template <class It>
+    ordered_map(It first, It last, const Allocator& alloc = Allocator())
+        : Container{first, last, alloc} {}
+    ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
+        : Container{init, alloc} {}
+
+    std::pair<iterator, bool> emplace(const key_type& key, T&& t)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return {it, false};
+            }
+        }
+        Container::emplace_back(key, std::forward<T>(t));
+        return {std::prev(this->end()), true};
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    std::pair<iterator, bool> emplace(KeyType && key, T && t)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return {it, false};
+            }
+        }
+        Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
+        return {std::prev(this->end()), true};
+    }
+
+    T& operator[](const key_type& key)
+    {
+        return emplace(key, T{}).first->second;
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    T & operator[](KeyType && key)
+    {
+        return emplace(std::forward<KeyType>(key), T{}).first->second;
+    }
+
+    const T& operator[](const key_type& key) const
+    {
+        return at(key);
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    const T & operator[](KeyType && key) const
+    {
+        return at(std::forward<KeyType>(key));
+    }
+
+    T& at(const key_type& key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it->second;
+            }
+        }
+
+        JSON_THROW(std::out_of_range("key not found"));
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    T & at(KeyType && key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it->second;
+            }
+        }
+
+        JSON_THROW(std::out_of_range("key not found"));
+    }
+
+    const T& at(const key_type& key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it->second;
+            }
+        }
+
+        JSON_THROW(std::out_of_range("key not found"));
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    const T & at(KeyType && key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it->second;
+            }
+        }
+
+        JSON_THROW(std::out_of_range("key not found"));
+    }
+
+    size_type erase(const key_type& key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                // Since we cannot move const Keys, re-construct them in place
+                for (auto next = it; ++next != this->end(); ++it)
+                {
+                    it->~value_type(); // Destroy but keep allocation
+                    new (&*it) value_type{std::move(*next)};
+                }
+                Container::pop_back();
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    size_type erase(KeyType && key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                // Since we cannot move const Keys, re-construct them in place
+                for (auto next = it; ++next != this->end(); ++it)
+                {
+                    it->~value_type(); // Destroy but keep allocation
+                    new (&*it) value_type{std::move(*next)};
+                }
+                Container::pop_back();
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    iterator erase(iterator pos)
+    {
+        return erase(pos, std::next(pos));
+    }
+
+    iterator erase(iterator first, iterator last)
+    {
+        if (first == last)
+        {
+            return first;
+        }
+
+        const auto elements_affected = std::distance(first, last);
+        const auto offset = std::distance(Container::begin(), first);
+
+        // This is the start situation. We need to delete elements_affected
+        // elements (3 in this example: e, f, g), and need to return an
+        // iterator past the last deleted element (h in this example).
+        // Note that offset is the distance from the start of the vector
+        // to first. We will need this later.
+
+        // [ a, b, c, d, e, f, g, h, i, j ]
+        //               ^        ^
+        //             first    last
+
+        // Since we cannot move const Keys, we re-construct them in place.
+        // We start at first and re-construct (viz. copy) the elements from
+        // the back of the vector. Example for first iteration:
+
+        //               ,--------.
+        //               v        |   destroy e and re-construct with h
+        // [ a, b, c, d, e, f, g, h, i, j ]
+        //               ^        ^
+        //               it       it + elements_affected
+
+        for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
+        {
+            it->~value_type(); // destroy but keep allocation
+            new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
+        }
+
+        // [ a, b, c, d, h, i, j, h, i, j ]
+        //               ^        ^
+        //             first    last
+
+        // remove the unneeded elements at the end of the vector
+        Container::resize(this->size() - static_cast<size_type>(elements_affected));
+
+        // [ a, b, c, d, h, i, j ]
+        //               ^        ^
+        //             first    last
+
+        // first is now pointing past the last deleted element, but we cannot
+        // use this iterator, because it may have been invalidated by the
+        // resize call. Instead, we can return begin() + offset.
+        return Container::begin() + offset;
+    }
+
+    size_type count(const key_type& key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    size_type count(KeyType && key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    iterator find(const key_type& key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it;
+            }
+        }
+        return Container::end();
+    }
+
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+    iterator find(KeyType && key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it;
+            }
+        }
+        return Container::end();
+    }
+
+    const_iterator find(const key_type& key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, key))
+            {
+                return it;
+            }
+        }
+        return Container::end();
+    }
+
+    std::pair<iterator, bool> insert( value_type&& value )
+    {
+        return emplace(value.first, std::move(value.second));
+    }
+
+    std::pair<iterator, bool> insert( const value_type& value )
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (m_compare(it->first, value.first))
+            {
+                return {it, false};
+            }
+        }
+        Container::push_back(value);
+        return {--this->end(), true};
+    }
+
+    template<typename InputIt>
+    using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
+            std::input_iterator_tag>::value>::type;
+
+    template<typename InputIt, typename = require_input_iter<InputIt>>
+    void insert(InputIt first, InputIt last)
+    {
+        for (auto it = first; it != last; ++it)
+        {
+            insert(*it);
+        }
+    }
+
+private:
+    JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
+};
+
+NLOHMANN_JSON_NAMESPACE_END
+
+
+#if defined(JSON_HAS_CPP_17)
+    #include <any>
+    #include <string_view>
+#endif
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/*!
+@brief a class to store JSON values
+
+@internal
+@invariant The member variables @a m_value and @a m_type have the following
+relationship:
+- If `m_type == value_t::object`, then `m_value.object != nullptr`.
+- If `m_type == value_t::array`, then `m_value.array != nullptr`.
+- If `m_type == value_t::string`, then `m_value.string != nullptr`.
+The invariants are checked by member function assert_invariant().
+
+@note ObjectType trick from https://stackoverflow.com/a/9860911
+@endinternal
+
+@since version 1.0.0
+
+@nosubgrouping
+*/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+{
+  private:
+    template<detail::value_t> friend struct detail::external_constructor;
+
+    template<typename>
+    friend class ::nlohmann::json_pointer;
+    // can be restored when json_pointer backwards compatibility is removed
+    // friend ::nlohmann::json_pointer<StringType>;
+
+    template<typename BasicJsonType, typename InputType>
+    friend class ::nlohmann::detail::parser;
+    friend ::nlohmann::detail::serializer<basic_json>;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::iter_impl;
+    template<typename BasicJsonType, typename CharType>
+    friend class ::nlohmann::detail::binary_writer;
+    template<typename BasicJsonType, typename InputType, typename SAX>
+    friend class ::nlohmann::detail::binary_reader;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::json_sax_dom_parser;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
+    friend class ::nlohmann::detail::exception;
+
+    /// workaround type for MSVC
+    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    // convenience aliases for types residing in namespace detail;
+    using lexer = ::nlohmann::detail::lexer_base<basic_json>;
+
+    template<typename InputAdapterType>
+    static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
+        InputAdapterType adapter,
+        detail::parser_callback_t<basic_json>cb = nullptr,
+        const bool allow_exceptions = true,
+        const bool ignore_comments = false
+                                 )
+    {
+        return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
+                std::move(cb), allow_exceptions, ignore_comments);
+    }
+
+  private:
+    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
+    template<typename BasicJsonType>
+    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
+    template<typename BasicJsonType>
+    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
+    template<typename Iterator>
+    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
+    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
+
+    template<typename CharType>
+    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
+
+    template<typename InputType>
+    using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
+    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    using serializer = ::nlohmann::detail::serializer<basic_json>;
+
+  public:
+    using value_t = detail::value_t;
+    /// JSON Pointer, see @ref nlohmann::json_pointer
+    using json_pointer = ::nlohmann::json_pointer<StringType>;
+    template<typename T, typename SFINAE>
+    using json_serializer = JSONSerializer<T, SFINAE>;
+    /// how to treat decoding errors
+    using error_handler_t = detail::error_handler_t;
+    /// how to treat CBOR tags
+    using cbor_tag_handler_t = detail::cbor_tag_handler_t;
+    /// helper type for initializer lists of basic_json values
+    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+
+    using input_format_t = detail::input_format_t;
+    /// SAX interface type, see @ref nlohmann::json_sax
+    using json_sax_t = json_sax<basic_json>;
+
+    ////////////////
+    // exceptions //
+    ////////////////
+
+    /// @name exceptions
+    /// Classes to implement user-defined exceptions.
+    /// @{
+
+    using exception = detail::exception;
+    using parse_error = detail::parse_error;
+    using invalid_iterator = detail::invalid_iterator;
+    using type_error = detail::type_error;
+    using out_of_range = detail::out_of_range;
+    using other_error = detail::other_error;
+
+    /// @}
+
+
+    /////////////////////
+    // container types //
+    /////////////////////
+
+    /// @name container types
+    /// The canonic container types to use @ref basic_json like any other STL
+    /// container.
+    /// @{
+
+    /// the type of elements in a basic_json container
+    using value_type = basic_json;
+
+    /// the type of an element reference
+    using reference = value_type&;
+    /// the type of an element const reference
+    using const_reference = const value_type&;
+
+    /// a type to represent differences between iterators
+    using difference_type = std::ptrdiff_t;
+    /// a type to represent container sizes
+    using size_type = std::size_t;
+
+    /// the allocator type
+    using allocator_type = AllocatorType<basic_json>;
+
+    /// the type of an element pointer
+    using pointer = typename std::allocator_traits<allocator_type>::pointer;
+    /// the type of an element const pointer
+    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+
+    /// an iterator for a basic_json container
+    using iterator = iter_impl<basic_json>;
+    /// a const iterator for a basic_json container
+    using const_iterator = iter_impl<const basic_json>;
+    /// a reverse iterator for a basic_json container
+    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
+    /// a const reverse iterator for a basic_json container
+    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
+
+    /// @}
+
+
+    /// @brief returns the allocator associated with the container
+    /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
+    static allocator_type get_allocator()
+    {
+        return allocator_type();
+    }
+
+    /// @brief returns version information on the library
+    /// @sa https://json.nlohmann.me/api/basic_json/meta/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json meta()
+    {
+        basic_json result;
+
+        result["copyright"] = "(C) 2013-2022 Niels Lohmann";
+        result["name"] = "JSON for Modern C++";
+        result["url"] = "https://github.com/nlohmann/json";
+        result["version"]["string"] =
+            detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
+                           std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
+                           std::to_string(NLOHMANN_JSON_VERSION_PATCH));
+        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
+        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
+        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
+
+#ifdef _WIN32
+        result["platform"] = "win32";
+#elif defined __linux__
+        result["platform"] = "linux";
+#elif defined __APPLE__
+        result["platform"] = "apple";
+#elif defined __unix__
+        result["platform"] = "unix";
+#else
+        result["platform"] = "unknown";
+#endif
+
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
+#elif defined(__clang__)
+        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
+#elif defined(__GNUC__) || defined(__GNUG__)
+        result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
+                    std::to_string(__GNUC__), '.',
+                    std::to_string(__GNUC_MINOR__), '.',
+                    std::to_string(__GNUC_PATCHLEVEL__))
+            }
+        };
+#elif defined(__HP_cc) || defined(__HP_aCC)
+        result["compiler"] = "hp"
+#elif defined(__IBMCPP__)
+        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
+#elif defined(_MSC_VER)
+        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
+#elif defined(__PGI)
+        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
+#elif defined(__SUNPRO_CC)
+        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
+#else
+        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
+#endif
+
+
+#if defined(_MSVC_LANG)
+        result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
+#elif defined(__cplusplus)
+        result["compiler"]["c++"] = std::to_string(__cplusplus);
+#else
+        result["compiler"]["c++"] = "unknown";
+#endif
+        return result;
+    }
+
+
+    ///////////////////////////
+    // JSON value data types //
+    ///////////////////////////
+
+    /// @name JSON value data types
+    /// The data types to store a JSON value. These types are derived from
+    /// the template arguments passed to class @ref basic_json.
+    /// @{
+
+    /// @brief default object key comparator type
+    /// The actual object key comparator type (@ref object_comparator_t) may be
+    /// different.
+    /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
+#if defined(JSON_HAS_CPP_14)
+    // use of transparent comparator avoids unnecessary repeated construction of temporaries
+    // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
+    using default_object_comparator_t = std::less<>;
+#else
+    using default_object_comparator_t = std::less<StringType>;
+#endif
+
+    /// @brief a type for an object
+    /// @sa https://json.nlohmann.me/api/basic_json/object_t/
+    using object_t = ObjectType<StringType,
+          basic_json,
+          default_object_comparator_t,
+          AllocatorType<std::pair<const StringType,
+          basic_json>>>;
+
+    /// @brief a type for an array
+    /// @sa https://json.nlohmann.me/api/basic_json/array_t/
+    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
+
+    /// @brief a type for a string
+    /// @sa https://json.nlohmann.me/api/basic_json/string_t/
+    using string_t = StringType;
+
+    /// @brief a type for a boolean
+    /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
+    using boolean_t = BooleanType;
+
+    /// @brief a type for a number (integer)
+    /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
+    using number_integer_t = NumberIntegerType;
+
+    /// @brief a type for a number (unsigned)
+    /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
+    using number_unsigned_t = NumberUnsignedType;
+
+    /// @brief a type for a number (floating-point)
+    /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
+    using number_float_t = NumberFloatType;
+
+    /// @brief a type for a packed binary type
+    /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
+    using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
+
+    /// @brief object key comparator type
+    /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
+    using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
+
+    /// @}
+
+  private:
+
+    /// helper for exception-safe object creation
+    template<typename T, typename... Args>
+    JSON_HEDLEY_RETURNS_NON_NULL
+    static T* create(Args&& ... args)
+    {
+        AllocatorType<T> alloc;
+        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
+
+        auto deleter = [&](T * obj)
+        {
+            AllocatorTraits::deallocate(alloc, obj, 1);
+        };
+        std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
+        AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
+        JSON_ASSERT(obj != nullptr);
+        return obj.release();
+    }
+
+    ////////////////////////
+    // JSON value storage //
+    ////////////////////////
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /*!
+    @brief a JSON value
+
+    The actual storage for a JSON value of the @ref basic_json class. This
+    union combines the different storage types for the JSON value types
+    defined in @ref value_t.
+
+    JSON type | value_t type    | used type
+    --------- | --------------- | ------------------------
+    object    | object          | pointer to @ref object_t
+    array     | array           | pointer to @ref array_t
+    string    | string          | pointer to @ref string_t
+    boolean   | boolean         | @ref boolean_t
+    number    | number_integer  | @ref number_integer_t
+    number    | number_unsigned | @ref number_unsigned_t
+    number    | number_float    | @ref number_float_t
+    binary    | binary          | pointer to @ref binary_t
+    null      | null            | *no value is stored*
+
+    @note Variable-length types (objects, arrays, and strings) are stored as
+    pointers. The size of the union should not exceed 64 bits if the default
+    value types are used.
+
+    @since version 1.0.0
+    */
+    union json_value
+    {
+        /// object (stored with pointer to save storage)
+        object_t* object;
+        /// array (stored with pointer to save storage)
+        array_t* array;
+        /// string (stored with pointer to save storage)
+        string_t* string;
+        /// binary (stored with pointer to save storage)
+        binary_t* binary;
+        /// boolean
+        boolean_t boolean;
+        /// number (integer)
+        number_integer_t number_integer;
+        /// number (unsigned integer)
+        number_unsigned_t number_unsigned;
+        /// number (floating-point)
+        number_float_t number_float;
+
+        /// default constructor (for null values)
+        json_value() = default;
+        /// constructor for booleans
+        json_value(boolean_t v) noexcept : boolean(v) {}
+        /// constructor for numbers (integer)
+        json_value(number_integer_t v) noexcept : number_integer(v) {}
+        /// constructor for numbers (unsigned)
+        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
+        /// constructor for numbers (floating-point)
+        json_value(number_float_t v) noexcept : number_float(v) {}
+        /// constructor for empty values of a given type
+        json_value(value_t t)
+        {
+            switch (t)
+            {
+                case value_t::object:
+                {
+                    object = create<object_t>();
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    array = create<array_t>();
+                    break;
+                }
+
+                case value_t::string:
+                {
+                    string = create<string_t>("");
+                    break;
+                }
+
+                case value_t::binary:
+                {
+                    binary = create<binary_t>();
+                    break;
+                }
+
+                case value_t::boolean:
+                {
+                    boolean = static_cast<boolean_t>(false);
+                    break;
+                }
+
+                case value_t::number_integer:
+                {
+                    number_integer = static_cast<number_integer_t>(0);
+                    break;
+                }
+
+                case value_t::number_unsigned:
+                {
+                    number_unsigned = static_cast<number_unsigned_t>(0);
+                    break;
+                }
+
+                case value_t::number_float:
+                {
+                    number_float = static_cast<number_float_t>(0.0);
+                    break;
+                }
+
+                case value_t::null:
+                {
+                    object = nullptr;  // silence warning, see #821
+                    break;
+                }
+
+                case value_t::discarded:
+                default:
+                {
+                    object = nullptr;  // silence warning, see #821
+                    if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
+                    {
+                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE
+                    }
+                    break;
+                }
+            }
+        }
+
+        /// constructor for strings
+        json_value(const string_t& value) : string(create<string_t>(value)) {}
+
+        /// constructor for rvalue strings
+        json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
+
+        /// constructor for objects
+        json_value(const object_t& value) : object(create<object_t>(value)) {}
+
+        /// constructor for rvalue objects
+        json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
+
+        /// constructor for arrays
+        json_value(const array_t& value) : array(create<array_t>(value)) {}
+
+        /// constructor for rvalue arrays
+        json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
+
+        /// constructor for binary arrays
+        json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
+
+        /// constructor for rvalue binary arrays
+        json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
+
+        /// constructor for binary arrays (internal type)
+        json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
+
+        /// constructor for rvalue binary arrays (internal type)
+        json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
+
+        void destroy(value_t t)
+        {
+            if (t == value_t::array || t == value_t::object)
+            {
+                // flatten the current json_value to a heap-allocated stack
+                std::vector<basic_json> stack;
+
+                // move the top-level items to stack
+                if (t == value_t::array)
+                {
+                    stack.reserve(array->size());
+                    std::move(array->begin(), array->end(), std::back_inserter(stack));
+                }
+                else
+                {
+                    stack.reserve(object->size());
+                    for (auto&& it : *object)
+                    {
+                        stack.push_back(std::move(it.second));
+                    }
+                }
+
+                while (!stack.empty())
+                {
+                    // move the last item to local variable to be processed
+                    basic_json current_item(std::move(stack.back()));
+                    stack.pop_back();
+
+                    // if current_item is array/object, move
+                    // its children to the stack to be processed later
+                    if (current_item.is_array())
+                    {
+                        std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
+
+                        current_item.m_value.array->clear();
+                    }
+                    else if (current_item.is_object())
+                    {
+                        for (auto&& it : *current_item.m_value.object)
+                        {
+                            stack.push_back(std::move(it.second));
+                        }
+
+                        current_item.m_value.object->clear();
+                    }
+
+                    // it's now safe that current_item get destructed
+                    // since it doesn't have any children
+                }
+            }
+
+            switch (t)
+            {
+                case value_t::object:
+                {
+                    AllocatorType<object_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    AllocatorType<array_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
+                    break;
+                }
+
+                case value_t::string:
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
+                    break;
+                }
+
+                case value_t::binary:
+                {
+                    AllocatorType<binary_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
+                    break;
+                }
+
+                case value_t::null:
+                case value_t::boolean:
+                case value_t::number_integer:
+                case value_t::number_unsigned:
+                case value_t::number_float:
+                case value_t::discarded:
+                default:
+                {
+                    break;
+                }
+            }
+        }
+    };
+
+  private:
+    /*!
+    @brief checks the class invariants
+
+    This function asserts the class invariants. It needs to be called at the
+    end of every constructor to make sure that created objects respect the
+    invariant. Furthermore, it has to be called each time the type of a JSON
+    value is changed, because the invariant expresses a relationship between
+    @a m_type and @a m_value.
+
+    Furthermore, the parent relation is checked for arrays and objects: If
+    @a check_parents true and the value is an array or object, then the
+    container's elements must have the current value as parent.
+
+    @param[in] check_parents  whether the parent relation should be checked.
+               The value is true by default and should only be set to false
+               during destruction of objects when the invariant does not
+               need to hold.
+    */
+    void assert_invariant(bool check_parents = true) const noexcept
+    {
+        JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
+        JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
+        JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
+        JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
+
+#if JSON_DIAGNOSTICS
+        JSON_TRY
+        {
+            // cppcheck-suppress assertWithSideEffect
+            JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
+            {
+                return j.m_parent == this;
+            }));
+        }
+        JSON_CATCH(...) {} // LCOV_EXCL_LINE
+#endif
+        static_cast<void>(check_parents);
+    }
+
+    void set_parents()
+    {
+#if JSON_DIAGNOSTICS
+        switch (m_type)
+        {
+            case value_t::array:
+            {
+                for (auto& element : *m_value.array)
+                {
+                    element.m_parent = this;
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                for (auto& element : *m_value.object)
+                {
+                    element.second.m_parent = this;
+                }
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                break;
+        }
+#endif
+    }
+
+    iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
+    {
+#if JSON_DIAGNOSTICS
+        for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
+        {
+            (it + i)->m_parent = this;
+        }
+#else
+        static_cast<void>(count_set_parents);
+#endif
+        return it;
+    }
+
+    reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
+    {
+#if JSON_DIAGNOSTICS
+        if (old_capacity != static_cast<std::size_t>(-1))
+        {
+            // see https://github.com/nlohmann/json/issues/2838
+            JSON_ASSERT(type() == value_t::array);
+            if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
+            {
+                // capacity has changed: update all parents
+                set_parents();
+                return j;
+            }
+        }
+
+        // ordered_json uses a vector internally, so pointers could have
+        // been invalidated; see https://github.com/nlohmann/json/issues/2962
+#ifdef JSON_HEDLEY_MSVC_VERSION
+#pragma warning(push )
+#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
+#endif
+        if (detail::is_ordered_map<object_t>::value)
+        {
+            set_parents();
+            return j;
+        }
+#ifdef JSON_HEDLEY_MSVC_VERSION
+#pragma warning( pop )
+#endif
+
+        j.m_parent = this;
+#else
+        static_cast<void>(j);
+        static_cast<void>(old_capacity);
+#endif
+        return j;
+    }
+
+  public:
+    //////////////////////////
+    // JSON parser callback //
+    //////////////////////////
+
+    /// @brief parser event types
+    /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
+    using parse_event_t = detail::parse_event_t;
+
+    /// @brief per-element parser callback type
+    /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
+    using parser_callback_t = detail::parser_callback_t<basic_json>;
+
+    //////////////////
+    // constructors //
+    //////////////////
+
+    /// @name constructors and destructors
+    /// Constructors of class @ref basic_json, copy/move constructor, copy
+    /// assignment, static functions creating objects, and the destructor.
+    /// @{
+
+    /// @brief create an empty value with a given type
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    basic_json(const value_t v)
+        : m_type(v), m_value(v)
+    {
+        assert_invariant();
+    }
+
+    /// @brief create a null object
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
+        : basic_json(value_t::null)
+    {
+        assert_invariant();
+    }
+
+    /// @brief create a JSON value from compatible types
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    template < typename CompatibleType,
+               typename U = detail::uncvref_t<CompatibleType>,
+               detail::enable_if_t <
+                   !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
+    basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
+                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
+                                           std::forward<CompatibleType>(val))))
+    {
+        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
+        set_parents();
+        assert_invariant();
+    }
+
+    /// @brief create a JSON value from an existing one
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    template < typename BasicJsonType,
+               detail::enable_if_t <
+                   detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
+    basic_json(const BasicJsonType& val)
+    {
+        using other_boolean_t = typename BasicJsonType::boolean_t;
+        using other_number_float_t = typename BasicJsonType::number_float_t;
+        using other_number_integer_t = typename BasicJsonType::number_integer_t;
+        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+        using other_string_t = typename BasicJsonType::string_t;
+        using other_object_t = typename BasicJsonType::object_t;
+        using other_array_t = typename BasicJsonType::array_t;
+        using other_binary_t = typename BasicJsonType::binary_t;
+
+        switch (val.type())
+        {
+            case value_t::boolean:
+                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
+                break;
+            case value_t::number_float:
+                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
+                break;
+            case value_t::number_integer:
+                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
+                break;
+            case value_t::number_unsigned:
+                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
+                break;
+            case value_t::string:
+                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
+                break;
+            case value_t::object:
+                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
+                break;
+            case value_t::array:
+                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
+                break;
+            case value_t::binary:
+                JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
+                break;
+            case value_t::null:
+                *this = nullptr;
+                break;
+            case value_t::discarded:
+                m_type = value_t::discarded;
+                break;
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+        JSON_ASSERT(m_type == val.type());
+        set_parents();
+        assert_invariant();
+    }
+
+    /// @brief create a container (array or object) from an initializer list
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    basic_json(initializer_list_t init,
+               bool type_deduction = true,
+               value_t manual_type = value_t::array)
+    {
+        // check if each element is an array with two elements whose first
+        // element is a string
+        bool is_an_object = std::all_of(init.begin(), init.end(),
+                                        [](const detail::json_ref<basic_json>& element_ref)
+        {
+            return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
+        });
+
+        // adjust type if type deduction is not wanted
+        if (!type_deduction)
+        {
+            // if array is wanted, do not create an object though possible
+            if (manual_type == value_t::array)
+            {
+                is_an_object = false;
+            }
+
+            // if object is wanted but impossible, throw an exception
+            if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
+            {
+                JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
+            }
+        }
+
+        if (is_an_object)
+        {
+            // the initializer list is a list of pairs -> create object
+            m_type = value_t::object;
+            m_value = value_t::object;
+
+            for (auto& element_ref : init)
+            {
+                auto element = element_ref.moved_or_copied();
+                m_value.object->emplace(
+                    std::move(*((*element.m_value.array)[0].m_value.string)),
+                    std::move((*element.m_value.array)[1]));
+            }
+        }
+        else
+        {
+            // the initializer list describes an array -> create array
+            m_type = value_t::array;
+            m_value.array = create<array_t>(init.begin(), init.end());
+        }
+
+        set_parents();
+        assert_invariant();
+    }
+
+    /// @brief explicitly create a binary array (without subtype)
+    /// @sa https://json.nlohmann.me/api/basic_json/binary/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(const typename binary_t::container_type& init)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = init;
+        return res;
+    }
+
+    /// @brief explicitly create a binary array (with subtype)
+    /// @sa https://json.nlohmann.me/api/basic_json/binary/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = binary_t(init, subtype);
+        return res;
+    }
+
+    /// @brief explicitly create a binary array
+    /// @sa https://json.nlohmann.me/api/basic_json/binary/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(typename binary_t::container_type&& init)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = std::move(init);
+        return res;
+    }
+
+    /// @brief explicitly create a binary array (with subtype)
+    /// @sa https://json.nlohmann.me/api/basic_json/binary/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = binary_t(std::move(init), subtype);
+        return res;
+    }
+
+    /// @brief explicitly create an array from an initializer list
+    /// @sa https://json.nlohmann.me/api/basic_json/array/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json array(initializer_list_t init = {})
+    {
+        return basic_json(init, false, value_t::array);
+    }
+
+    /// @brief explicitly create an object from an initializer list
+    /// @sa https://json.nlohmann.me/api/basic_json/object/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json object(initializer_list_t init = {})
+    {
+        return basic_json(init, false, value_t::object);
+    }
+
+    /// @brief construct an array with count copies of given value
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    basic_json(size_type cnt, const basic_json& val)
+        : m_type(value_t::array)
+    {
+        m_value.array = create<array_t>(cnt, val);
+        set_parents();
+        assert_invariant();
+    }
+
+    /// @brief construct a JSON container given an iterator range
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    template < class InputIT, typename std::enable_if <
+                   std::is_same<InputIT, typename basic_json_t::iterator>::value ||
+                   std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
+    basic_json(InputIT first, InputIT last)
+    {
+        JSON_ASSERT(first.m_object != nullptr);
+        JSON_ASSERT(last.m_object != nullptr);
+
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
+        }
+
+        // copy type from first iterator
+        m_type = first.m_object->m_type;
+
+        // check if iterator range is complete for primitive values
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            {
+                if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
+                                         || !last.m_it.primitive_iterator.is_end()))
+                {
+                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
+                }
+                break;
+            }
+
+            case value_t::null:
+            case value_t::object:
+            case value_t::array:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                break;
+        }
+
+        switch (m_type)
+        {
+            case value_t::number_integer:
+            {
+                m_value.number_integer = first.m_object->m_value.number_integer;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value.number_float = first.m_object->m_value.number_float;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value.boolean = first.m_object->m_value.boolean;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value = *first.m_object->m_value.string;
+                break;
+            }
+
+            case value_t::object:
+            {
+                m_value.object = create<object_t>(first.m_it.object_iterator,
+                                                  last.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value.array = create<array_t>(first.m_it.array_iterator,
+                                                last.m_it.array_iterator);
+                break;
+            }
+
+            case value_t::binary:
+            {
+                m_value = *first.m_object->m_value.binary;
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
+        }
+
+        set_parents();
+        assert_invariant();
+    }
+
+
+    ///////////////////////////////////////
+    // other constructors and destructor //
+    ///////////////////////////////////////
+
+    template<typename JsonRef,
+             detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
+                                 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
+    basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
+
+    /// @brief copy constructor
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    basic_json(const basic_json& other)
+        : m_type(other.m_type)
+    {
+        // check of passed value is valid
+        other.assert_invariant();
+
+        switch (m_type)
+        {
+            case value_t::object:
+            {
+                m_value = *other.m_value.object;
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value = *other.m_value.array;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value = *other.m_value.string;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value = other.m_value.boolean;
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                m_value = other.m_value.number_integer;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value = other.m_value.number_unsigned;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value = other.m_value.number_float;
+                break;
+            }
+
+            case value_t::binary:
+            {
+                m_value = *other.m_value.binary;
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                break;
+        }
+
+        set_parents();
+        assert_invariant();
+    }
+
+    /// @brief move constructor
+    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
+    basic_json(basic_json&& other) noexcept
+        : m_type(std::move(other.m_type)),
+          m_value(std::move(other.m_value))
+    {
+        // check that passed value is valid
+        other.assert_invariant(false);
+
+        // invalidate payload
+        other.m_type = value_t::null;
+        other.m_value = {};
+
+        set_parents();
+        assert_invariant();
+    }
+
+    /// @brief copy assignment
+    /// @sa https://json.nlohmann.me/api/basic_json/operator=/
+    basic_json& operator=(basic_json other) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value&&
+        std::is_nothrow_move_assignable<value_t>::value&&
+        std::is_nothrow_move_constructible<json_value>::value&&
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        // check that passed value is valid
+        other.assert_invariant();
+
+        using std::swap;
+        swap(m_type, other.m_type);
+        swap(m_value, other.m_value);
+
+        set_parents();
+        assert_invariant();
+        return *this;
+    }
+
+    /// @brief destructor
+    /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
+    ~basic_json() noexcept
+    {
+        assert_invariant(false);
+        m_value.destroy(m_type);
+    }
+
+    /// @}
+
+  public:
+    ///////////////////////
+    // object inspection //
+    ///////////////////////
+
+    /// @name object inspection
+    /// Functions to inspect the type of a JSON value.
+    /// @{
+
+    /// @brief serialization
+    /// @sa https://json.nlohmann.me/api/basic_json/dump/
+    string_t dump(const int indent = -1,
+                  const char indent_char = ' ',
+                  const bool ensure_ascii = false,
+                  const error_handler_t error_handler = error_handler_t::strict) const
+    {
+        string_t result;
+        serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
+
+        if (indent >= 0)
+        {
+            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
+        }
+        else
+        {
+            s.dump(*this, false, ensure_ascii, 0);
+        }
+
+        return result;
+    }
+
+    /// @brief return the type of the JSON value (explicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/type/
+    constexpr value_t type() const noexcept
+    {
+        return m_type;
+    }
+
+    /// @brief return whether type is primitive
+    /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
+    constexpr bool is_primitive() const noexcept
+    {
+        return is_null() || is_string() || is_boolean() || is_number() || is_binary();
+    }
+
+    /// @brief return whether type is structured
+    /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
+    constexpr bool is_structured() const noexcept
+    {
+        return is_array() || is_object();
+    }
+
+    /// @brief return whether value is null
+    /// @sa https://json.nlohmann.me/api/basic_json/is_null/
+    constexpr bool is_null() const noexcept
+    {
+        return m_type == value_t::null;
+    }
+
+    /// @brief return whether value is a boolean
+    /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
+    constexpr bool is_boolean() const noexcept
+    {
+        return m_type == value_t::boolean;
+    }
+
+    /// @brief return whether value is a number
+    /// @sa https://json.nlohmann.me/api/basic_json/is_number/
+    constexpr bool is_number() const noexcept
+    {
+        return is_number_integer() || is_number_float();
+    }
+
+    /// @brief return whether value is an integer number
+    /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
+    constexpr bool is_number_integer() const noexcept
+    {
+        return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
+    }
+
+    /// @brief return whether value is an unsigned integer number
+    /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
+    constexpr bool is_number_unsigned() const noexcept
+    {
+        return m_type == value_t::number_unsigned;
+    }
+
+    /// @brief return whether value is a floating-point number
+    /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
+    constexpr bool is_number_float() const noexcept
+    {
+        return m_type == value_t::number_float;
+    }
+
+    /// @brief return whether value is an object
+    /// @sa https://json.nlohmann.me/api/basic_json/is_object/
+    constexpr bool is_object() const noexcept
+    {
+        return m_type == value_t::object;
+    }
+
+    /// @brief return whether value is an array
+    /// @sa https://json.nlohmann.me/api/basic_json/is_array/
+    constexpr bool is_array() const noexcept
+    {
+        return m_type == value_t::array;
+    }
+
+    /// @brief return whether value is a string
+    /// @sa https://json.nlohmann.me/api/basic_json/is_string/
+    constexpr bool is_string() const noexcept
+    {
+        return m_type == value_t::string;
+    }
+
+    /// @brief return whether value is a binary array
+    /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
+    constexpr bool is_binary() const noexcept
+    {
+        return m_type == value_t::binary;
+    }
+
+    /// @brief return whether value is discarded
+    /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
+    constexpr bool is_discarded() const noexcept
+    {
+        return m_type == value_t::discarded;
+    }
+
+    /// @brief return the type of the JSON value (implicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
+    constexpr operator value_t() const noexcept
+    {
+        return m_type;
+    }
+
+    /// @}
+
+  private:
+    //////////////////
+    // value access //
+    //////////////////
+
+    /// get a boolean (explicit)
+    boolean_t get_impl(boolean_t* /*unused*/) const
+    {
+        if (JSON_HEDLEY_LIKELY(is_boolean()))
+        {
+            return m_value.boolean;
+        }
+
+        JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
+    }
+
+    /// get a pointer to the value (object)
+    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (object)
+    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (unsigned number)
+    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+
+    /// get a pointer to the value (unsigned number)
+    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
+    /// get a pointer to the value (binary)
+    binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
+    {
+        return is_binary() ? m_value.binary : nullptr;
+    }
+
+    /// get a pointer to the value (binary)
+    constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
+    {
+        return is_binary() ? m_value.binary : nullptr;
+    }
+
+    /*!
+    @brief helper function to implement get_ref()
+
+    This function helps to implement get_ref() without code duplication for
+    const and non-const overloads
+
+    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
+
+    @throw type_error.303 if ReferenceType does not match underlying value
+    type of the current JSON
+    */
+    template<typename ReferenceType, typename ThisType>
+    static ReferenceType get_ref_impl(ThisType& obj)
+    {
+        // delegate the call to get_ptr<>()
+        auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
+
+        if (JSON_HEDLEY_LIKELY(ptr != nullptr))
+        {
+            return *ptr;
+        }
+
+        JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
+    }
+
+  public:
+    /// @name value access
+    /// Direct access to the stored value of a JSON value.
+    /// @{
+
+    /// @brief get a pointer value (implicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+    {
+        // delegate the call to get_impl_ptr<>()
+        return get_impl_ptr(static_cast<PointerType>(nullptr));
+    }
+
+    /// @brief get a pointer value (implicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
+    template < typename PointerType, typename std::enable_if <
+                   std::is_pointer<PointerType>::value&&
+                   std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
+    constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+    {
+        // delegate the call to get_impl_ptr<>() const
+        return get_impl_ptr(static_cast<PointerType>(nullptr));
+    }
+
+  private:
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value
+    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+    The value is converted by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    ValueType ret;
+    JSONSerializer<ValueType>::from_json(*this, ret);
+    return ret;
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json,
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `void from_json(const basic_json&, ValueType&)`, and
+    - @ref json_serializer<ValueType> does not have a `from_json()` method of
+      the form `ValueType from_json(const basic_json&)`
+
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @a ValueType
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,get__ValueType_const}
+
+    @since version 2.1.0
+    */
+    template < typename ValueType,
+               detail::enable_if_t <
+                   detail::is_default_constructible<ValueType>::value&&
+                   detail::has_from_json<basic_json_t, ValueType>::value,
+                   int > = 0 >
+    ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
+    {
+        auto ret = ValueType();
+        JSONSerializer<ValueType>::from_json(*this, ret);
+        return ret;
+    }
+
+    /*!
+    @brief get a value (explicit); special case
+
+    Explicit type conversion between the JSON value and a compatible value
+    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+    The value is converted by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    return JSONSerializer<ValueType>::from_json(*this);
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json and
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `ValueType from_json(const basic_json&)`
+
+    @note If @ref json_serializer<ValueType> has both overloads of
+    `from_json()`, this one is chosen.
+
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @a ValueType
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @since version 2.1.0
+    */
+    template < typename ValueType,
+               detail::enable_if_t <
+                   detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+                   int > = 0 >
+    ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
+    {
+        return JSONSerializer<ValueType>::from_json(*this);
+    }
+
+    /*!
+    @brief get special-case overload
+
+    This overloads converts the current @ref basic_json in a different
+    @ref basic_json type
+
+    @tparam BasicJsonType == @ref basic_json
+
+    @return a copy of *this, converted into @a BasicJsonType
+
+    @complexity Depending on the implementation of the called `from_json()`
+                method.
+
+    @since version 3.2.0
+    */
+    template < typename BasicJsonType,
+               detail::enable_if_t <
+                   detail::is_basic_json<BasicJsonType>::value,
+                   int > = 0 >
+    BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
+    {
+        return *this;
+    }
+
+    /*!
+    @brief get special-case overload
+
+    This overloads avoids a lot of template boilerplate, it can be seen as the
+    identity method
+
+    @tparam BasicJsonType == @ref basic_json
+
+    @return a copy of *this
+
+    @complexity Constant.
+
+    @since version 2.1.0
+    */
+    template<typename BasicJsonType,
+             detail::enable_if_t<
+                 std::is_same<BasicJsonType, basic_json_t>::value,
+                 int> = 0>
+    basic_json get_impl(detail::priority_tag<3> /*unused*/) const
+    {
+        return *this;
+    }
+
+    /*!
+    @brief get a pointer value (explicit)
+    @copydoc get()
+    */
+    template<typename PointerType,
+             detail::enable_if_t<
+                 std::is_pointer<PointerType>::value,
+                 int> = 0>
+    constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
+    -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
+    {
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+  public:
+    /*!
+    @brief get a (pointer) value (explicit)
+
+    Performs explicit type conversion between the JSON value and a compatible value if required.
+
+    - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
+    No copies are made.
+
+    - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
+    from the current @ref basic_json.
+
+    - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
+    method.
+
+    @tparam ValueTypeCV the provided value type
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @tparam ValueType if necessary
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
+
+    @since version 2.1.0
+    */
+    template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
+#if defined(JSON_HAS_CPP_14)
+    constexpr
+#endif
+    auto get() const noexcept(
+    noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
+    -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
+    {
+        // we cannot static_assert on ValueTypeCV being non-const, because
+        // there is support for get<const basic_json_t>(), which is why we
+        // still need the uncvref
+        static_assert(!std::is_reference<ValueTypeCV>::value,
+                      "get() cannot be used with reference types, you might want to use get_ref()");
+        return get_impl<ValueType>(detail::priority_tag<4> {});
+    }
+
+    /*!
+    @brief get a pointer value (explicit)
+
+    Explicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning The pointer becomes invalid if the underlying JSON object
+    changes.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+    @ref number_unsigned_t, or @ref number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested
+    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get__PointerType}
+
+    @sa see @ref get_ptr() for explicit pointer-member access
+
+    @since version 1.0.0
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
+    {
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+    /// @brief get a value (explicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/get_to/
+    template < typename ValueType,
+               detail::enable_if_t <
+                   !detail::is_basic_json<ValueType>::value&&
+                   detail::has_from_json<basic_json_t, ValueType>::value,
+                   int > = 0 >
+    ValueType & get_to(ValueType& v) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
+    {
+        JSONSerializer<ValueType>::from_json(*this, v);
+        return v;
+    }
+
+    // specialization to allow calling get_to with a basic_json value
+    // see https://github.com/nlohmann/json/issues/2175
+    template<typename ValueType,
+             detail::enable_if_t <
+                 detail::is_basic_json<ValueType>::value,
+                 int> = 0>
+    ValueType & get_to(ValueType& v) const
+    {
+        v = *this;
+        return v;
+    }
+
+    template <
+        typename T, std::size_t N,
+        typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+        detail::enable_if_t <
+            detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
+    Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+    noexcept(noexcept(JSONSerializer<Array>::from_json(
+                          std::declval<const basic_json_t&>(), v)))
+    {
+        JSONSerializer<Array>::from_json(*this, v);
+        return v;
+    }
+
+    /// @brief get a reference value (implicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
+    template<typename ReferenceType, typename std::enable_if<
+                 std::is_reference<ReferenceType>::value, int>::type = 0>
+    ReferenceType get_ref()
+    {
+        // delegate call to get_ref_impl
+        return get_ref_impl<ReferenceType>(*this);
+    }
+
+    /// @brief get a reference value (implicit)
+    /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
+    template < typename ReferenceType, typename std::enable_if <
+                   std::is_reference<ReferenceType>::value&&
+                   std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
+    ReferenceType get_ref() const
+    {
+        // delegate call to get_ref_impl
+        return get_ref_impl<ReferenceType>(*this);
+    }
+
+    /*!
+    @brief get a value (implicit)
+
+    Implicit type conversion between the JSON value and a compatible value.
+    The call is realized by calling @ref get() const.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays. The character type of @ref string_t
+    as well as an initializer list of this type is excluded to avoid
+    ambiguities as these types implicitly convert to `std::string`.
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw type_error.302 in case passed type @a ValueType is incompatible
+    to the JSON value type (e.g., the JSON value is of type boolean, but a
+    string is requested); see example below
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,operator__ValueType}
+
+    @since version 1.0.0
+    */
+    template < typename ValueType, typename std::enable_if <
+                   detail::conjunction <
+                       detail::negation<std::is_pointer<ValueType>>,
+                       detail::negation<std::is_same<ValueType, std::nullptr_t>>,
+                       detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
+                                        detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
+                                        detail::negation<detail::is_basic_json<ValueType>>,
+                                        detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
+#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
+                                                detail::negation<std::is_same<ValueType, std::string_view>>,
+#endif
+#if defined(JSON_HAS_CPP_17)
+                                                detail::negation<std::is_same<ValueType, std::any>>,
+#endif
+                                                detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
+                                                >::value, int >::type = 0 >
+                                        JSON_EXPLICIT operator ValueType() const
+    {
+        // delegate the call to get<>() const
+        return get<ValueType>();
+    }
+
+    /// @brief get a binary value
+    /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
+    binary_t& get_binary()
+    {
+        if (!is_binary())
+        {
+            JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
+        }
+
+        return *get_ptr<binary_t*>();
+    }
+
+    /// @brief get a binary value
+    /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
+    const binary_t& get_binary() const
+    {
+        if (!is_binary())
+        {
+            JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
+        }
+
+        return *get_ptr<const binary_t*>();
+    }
+
+    /// @}
+
+
+    ////////////////////
+    // element access //
+    ////////////////////
+
+    /// @name element access
+    /// Access to the JSON value.
+    /// @{
+
+    /// @brief access specified array element with bounds checking
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    reference at(size_type idx)
+    {
+        // at only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            JSON_TRY
+            {
+                return set_parent(m_value.array->at(idx));
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
+        }
+    }
+
+    /// @brief access specified array element with bounds checking
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    const_reference at(size_type idx) const
+    {
+        // at only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            JSON_TRY
+            {
+                return m_value.array->at(idx);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
+        }
+    }
+
+    /// @brief access specified object element with bounds checking
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    reference at(const typename object_t::key_type& key)
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
+        }
+
+        auto it = m_value.object->find(key);
+        if (it == m_value.object->end())
+        {
+            JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
+        }
+        return set_parent(it->second);
+    }
+
+    /// @brief access specified object element with bounds checking
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    reference at(KeyType && key)
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
+        }
+
+        auto it = m_value.object->find(std::forward<KeyType>(key));
+        if (it == m_value.object->end())
+        {
+            JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
+        }
+        return set_parent(it->second);
+    }
+
+    /// @brief access specified object element with bounds checking
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    const_reference at(const typename object_t::key_type& key) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
+        }
+
+        auto it = m_value.object->find(key);
+        if (it == m_value.object->end())
+        {
+            JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
+        }
+        return it->second;
+    }
+
+    /// @brief access specified object element with bounds checking
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    const_reference at(KeyType && key) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
+        }
+
+        auto it = m_value.object->find(std::forward<KeyType>(key));
+        if (it == m_value.object->end())
+        {
+            JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
+        }
+        return it->second;
+    }
+
+    /// @brief access specified array element
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    reference operator[](size_type idx)
+    {
+        // implicitly convert null value to an empty array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value.array = create<array_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // fill up array with null values if given idx is outside range
+            if (idx >= m_value.array->size())
+            {
+#if JSON_DIAGNOSTICS
+                // remember array size & capacity before resizing
+                const auto old_size = m_value.array->size();
+                const auto old_capacity = m_value.array->capacity();
+#endif
+                m_value.array->resize(idx + 1);
+
+#if JSON_DIAGNOSTICS
+                if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
+                {
+                    // capacity has changed: update all parents
+                    set_parents();
+                }
+                else
+                {
+                    // set parent for values added above
+                    set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
+                }
+#endif
+                assert_invariant();
+            }
+
+            return m_value.array->operator[](idx);
+        }
+
+        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
+    }
+
+    /// @brief access specified array element
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    const_reference operator[](size_type idx) const
+    {
+        // const operator[] only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            return m_value.array->operator[](idx);
+        }
+
+        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
+    }
+
+    /// @brief access specified object element
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    reference operator[](typename object_t::key_type key)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            auto result = m_value.object->emplace(std::move(key), nullptr);
+            return set_parent(result.first->second);
+        }
+
+        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
+    }
+
+    /// @brief access specified object element
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    const_reference operator[](const typename object_t::key_type& key) const
+    {
+        // const operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            auto it = m_value.object->find(key);
+            JSON_ASSERT(it != m_value.object->end());
+            return it->second;
+        }
+
+        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
+    }
+
+    // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
+    // (they seemingly cannot be constrained to resolve the ambiguity)
+    template<typename T>
+    reference operator[](T* key)
+    {
+        return operator[](typename object_t::key_type(key));
+    }
+
+    template<typename T>
+    const_reference operator[](T* key) const
+    {
+        return operator[](typename object_t::key_type(key));
+    }
+
+    /// @brief access specified object element
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
+    reference operator[](KeyType && key)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
+            return set_parent(result.first->second);
+        }
+
+        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
+    }
+
+    /// @brief access specified object element
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
+    const_reference operator[](KeyType && key) const
+    {
+        // const operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            auto it = m_value.object->find(std::forward<KeyType>(key));
+            JSON_ASSERT(it != m_value.object->end());
+            return it->second;
+        }
+
+        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
+    }
+
+  private:
+    template<typename KeyType>
+    using is_comparable_with_object_key = detail::is_comparable <
+        object_comparator_t, const typename object_t::key_type&, KeyType >;
+
+    template<typename ValueType>
+    using value_return_type = std::conditional <
+        detail::is_c_string_uncvref<ValueType>::value,
+        string_t, typename std::decay<ValueType>::type >;
+
+  public:
+    /// @brief access specified object element with default value
+    /// @sa https://json.nlohmann.me/api/basic_json/value/
+    template < class ValueType, detail::enable_if_t <
+                   !detail::is_transparent<object_comparator_t>::value
+                   && detail::is_getable<basic_json_t, ValueType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
+    {
+        // value only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if key is found, return value and given default value otherwise
+            const auto it = find(key);
+            if (it != end())
+            {
+                return it->template get<ValueType>();
+            }
+
+            return default_value;
+        }
+
+        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+    }
+
+    /// @brief access specified object element with default value
+    /// @sa https://json.nlohmann.me/api/basic_json/value/
+    template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
+               detail::enable_if_t <
+                   !detail::is_transparent<object_comparator_t>::value
+                   && detail::is_getable<basic_json_t, ReturnType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
+    {
+        // value only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if key is found, return value and given default value otherwise
+            const auto it = find(key);
+            if (it != end())
+            {
+                return it->template get<ReturnType>();
+            }
+
+            return std::forward<ValueType>(default_value);
+        }
+
+        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+    }
+
+    /// @brief access specified object element with default value
+    /// @sa https://json.nlohmann.me/api/basic_json/value/
+    template < class ValueType, class KeyType, detail::enable_if_t <
+                   detail::is_transparent<object_comparator_t>::value
+                   && !detail::is_json_pointer<KeyType>::value
+                   && is_comparable_with_object_key<KeyType>::value
+                   && detail::is_getable<basic_json_t, ValueType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    ValueType value(KeyType && key, const ValueType& default_value) const
+    {
+        // value only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if key is found, return value and given default value otherwise
+            const auto it = find(std::forward<KeyType>(key));
+            if (it != end())
+            {
+                return it->template get<ValueType>();
+            }
+
+            return default_value;
+        }
+
+        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+    }
+
+    /// @brief access specified object element via JSON Pointer with default value
+    /// @sa https://json.nlohmann.me/api/basic_json/value/
+    template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
+               detail::enable_if_t <
+                   detail::is_transparent<object_comparator_t>::value
+                   && !detail::is_json_pointer<KeyType>::value
+                   && is_comparable_with_object_key<KeyType>::value
+                   && detail::is_getable<basic_json_t, ReturnType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    ReturnType value(KeyType && key, ValueType && default_value) const
+    {
+        // value only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if key is found, return value and given default value otherwise
+            const auto it = find(std::forward<KeyType>(key));
+            if (it != end())
+            {
+                return it->template get<ReturnType>();
+            }
+
+            return std::forward<ValueType>(default_value);
+        }
+
+        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+    }
+
+    /// @brief access specified object element via JSON Pointer with default value
+    /// @sa https://json.nlohmann.me/api/basic_json/value/
+    template < class ValueType, detail::enable_if_t <
+                   detail::is_getable<basic_json_t, ValueType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
+    {
+        // value only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if pointer resolves a value, return it or use default value
+            JSON_TRY
+            {
+                return ptr.get_checked(this).template get<ValueType>();
+            }
+            JSON_INTERNAL_CATCH (out_of_range&)
+            {
+                return default_value;
+            }
+        }
+
+        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+    }
+
+    /// @brief access specified object element via JSON Pointer with default value
+    /// @sa https://json.nlohmann.me/api/basic_json/value/
+    template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
+               detail::enable_if_t <
+                   detail::is_getable<basic_json_t, ReturnType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    ReturnType value(const json_pointer& ptr, ValueType && default_value) const
+    {
+        // value only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if pointer resolves a value, return it or use default value
+            JSON_TRY
+            {
+                return ptr.get_checked(this).template get<ReturnType>();
+            }
+            JSON_INTERNAL_CATCH (out_of_range&)
+            {
+                return std::forward<ValueType>(default_value);
+            }
+        }
+
+        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+    }
+
+    template < class ValueType, class BasicJsonType, detail::enable_if_t <
+                   detail::is_basic_json<BasicJsonType>::value
+                   && detail::is_getable<basic_json_t, ValueType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
+    {
+        return value(ptr.convert(), default_value);
+    }
+
+    template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
+               detail::enable_if_t <
+                   detail::is_basic_json<BasicJsonType>::value
+                   && detail::is_getable<basic_json_t, ReturnType>::value
+                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
+    {
+        return value(ptr.convert(), std::forward<ValueType>(default_value));
+    }
+
+    /// @brief access the first element
+    /// @sa https://json.nlohmann.me/api/basic_json/front/
+    reference front()
+    {
+        return *begin();
+    }
+
+    /// @brief access the first element
+    /// @sa https://json.nlohmann.me/api/basic_json/front/
+    const_reference front() const
+    {
+        return *cbegin();
+    }
+
+    /// @brief access the last element
+    /// @sa https://json.nlohmann.me/api/basic_json/back/
+    reference back()
+    {
+        auto tmp = end();
+        --tmp;
+        return *tmp;
+    }
+
+    /// @brief access the last element
+    /// @sa https://json.nlohmann.me/api/basic_json/back/
+    const_reference back() const
+    {
+        auto tmp = cend();
+        --tmp;
+        return *tmp;
+    }
+
+    /// @brief remove element given an iterator
+    /// @sa https://json.nlohmann.me/api/basic_json/erase/
+    template < class IteratorType, detail::enable_if_t <
+                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
+                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
+    IteratorType erase(IteratorType pos)
+    {
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
+        }
+
+        IteratorType result = end();
+
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            case value_t::binary:
+            {
+                if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
+                {
+                    JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
+                }
+
+                if (is_string())
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+                    m_value.string = nullptr;
+                }
+                else if (is_binary())
+                {
+                    AllocatorType<binary_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
+                    m_value.binary = nullptr;
+                }
+
+                m_type = value_t::null;
+                assert_invariant();
+                break;
+            }
+
+            case value_t::object:
+            {
+                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
+        }
+
+        return result;
+    }
+
+    /// @brief remove elements given an iterator range
+    /// @sa https://json.nlohmann.me/api/basic_json/erase/
+    template < class IteratorType, detail::enable_if_t <
+                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
+                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
+    IteratorType erase(IteratorType first, IteratorType last)
+    {
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
+        }
+
+        IteratorType result = end();
+
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            case value_t::binary:
+            {
+                if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
+                                       || !last.m_it.primitive_iterator.is_end()))
+                {
+                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
+                }
+
+                if (is_string())
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+                    m_value.string = nullptr;
+                }
+                else if (is_binary())
+                {
+                    AllocatorType<binary_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
+                    m_value.binary = nullptr;
+                }
+
+                m_type = value_t::null;
+                assert_invariant();
+                break;
+            }
+
+            case value_t::object:
+            {
+                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
+                                              last.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
+                                             last.m_it.array_iterator);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
+        }
+
+        return result;
+    }
+
+  private:
+    template < typename KeyType, detail::enable_if_t <
+                   detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
+    size_type erase_internal(KeyType && key)
+    {
+        // this erase only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
+        }
+
+        return m_value.object->erase(std::forward<KeyType>(key));
+    }
+
+    template < typename KeyType, detail::enable_if_t <
+                   !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
+    size_type erase_internal(KeyType && key)
+    {
+        // this erase only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
+        }
+
+        const auto it = m_value.object->find(std::forward<KeyType>(key));
+        if (it != m_value.object->end())
+        {
+            m_value.object->erase(it);
+            return 1;
+        }
+        return 0;
+    }
+
+  public:
+
+    /// @brief remove element from a JSON object given a key
+    /// @sa https://json.nlohmann.me/api/basic_json/erase/
+    size_type erase(const typename object_t::key_type& key)
+    {
+        // the indirection via erase_internal() is added to avoid making this
+        // function a template and thus de-rank it during overload resolution
+        return erase_internal(key);
+    }
+
+    /// @brief remove element from a JSON object given a key
+    /// @sa https://json.nlohmann.me/api/basic_json/erase/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    size_type erase(KeyType && key)
+    {
+        return erase_internal(std::forward<KeyType>(key));
+    }
+
+    /// @brief remove element from a JSON array given an index
+    /// @sa https://json.nlohmann.me/api/basic_json/erase/
+    void erase(const size_type idx)
+    {
+        // this erase only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            if (JSON_HEDLEY_UNLIKELY(idx >= size()))
+            {
+                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
+            }
+
+            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
+        }
+        else
+        {
+            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
+        }
+    }
+
+    /// @}
+
+
+    ////////////
+    // lookup //
+    ////////////
+
+    /// @name lookup
+    /// @{
+
+    /// @brief find an element in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/find/
+    iterator find(const typename object_t::key_type& key)
+    {
+        auto result = end();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(key);
+        }
+
+        return result;
+    }
+
+    /// @brief find an element in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/find/
+    const_iterator find(const typename object_t::key_type& key) const
+    {
+        auto result = cend();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(key);
+        }
+
+        return result;
+    }
+
+    /// @brief find an element in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/find/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    iterator find(KeyType && key)
+    {
+        auto result = end();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
+        }
+
+        return result;
+    }
+
+    /// @brief find an element in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/find/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    const_iterator find(KeyType && key) const
+    {
+        auto result = cend();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
+        }
+
+        return result;
+    }
+
+    /// @brief returns the number of occurrences of a key in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/count/
+    size_type count(const typename object_t::key_type& key) const
+    {
+        // return 0 for all nonobject types
+        return is_object() ? m_value.object->count(key) : 0;
+    }
+
+    /// @brief returns the number of occurrences of a key in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/count/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    size_type count(KeyType && key) const
+    {
+        // return 0 for all nonobject types
+        return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
+    }
+
+    /// @brief check the existence of an element in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/contains/
+    bool contains(const typename object_t::key_type& key) const
+    {
+        return is_object() && m_value.object->find(key) != m_value.object->end();
+    }
+
+    /// @brief check the existence of an element in a JSON object
+    /// @sa https://json.nlohmann.me/api/basic_json/contains/
+    template<class KeyType, detail::enable_if_t<
+                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+    bool contains(KeyType && key) const
+    {
+        return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
+    }
+
+    /// @brief check the existence of an element in a JSON object given a JSON pointer
+    /// @sa https://json.nlohmann.me/api/basic_json/contains/
+    bool contains(const json_pointer& ptr) const
+    {
+        return ptr.contains(this);
+    }
+
+    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
+    {
+        return ptr.contains(this);
+    }
+
+    /// @}
+
+
+    ///////////////
+    // iterators //
+    ///////////////
+
+    /// @name iterators
+    /// @{
+
+    /// @brief returns an iterator to the first element
+    /// @sa https://json.nlohmann.me/api/basic_json/begin/
+    iterator begin() noexcept
+    {
+        iterator result(this);
+        result.set_begin();
+        return result;
+    }
+
+    /// @brief returns an iterator to the first element
+    /// @sa https://json.nlohmann.me/api/basic_json/begin/
+    const_iterator begin() const noexcept
+    {
+        return cbegin();
+    }
+
+    /// @brief returns a const iterator to the first element
+    /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
+    const_iterator cbegin() const noexcept
+    {
+        const_iterator result(this);
+        result.set_begin();
+        return result;
+    }
+
+    /// @brief returns an iterator to one past the last element
+    /// @sa https://json.nlohmann.me/api/basic_json/end/
+    iterator end() noexcept
+    {
+        iterator result(this);
+        result.set_end();
+        return result;
+    }
+
+    /// @brief returns an iterator to one past the last element
+    /// @sa https://json.nlohmann.me/api/basic_json/end/
+    const_iterator end() const noexcept
+    {
+        return cend();
+    }
+
+    /// @brief returns an iterator to one past the last element
+    /// @sa https://json.nlohmann.me/api/basic_json/cend/
+    const_iterator cend() const noexcept
+    {
+        const_iterator result(this);
+        result.set_end();
+        return result;
+    }
+
+    /// @brief returns an iterator to the reverse-beginning
+    /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
+    reverse_iterator rbegin() noexcept
+    {
+        return reverse_iterator(end());
+    }
+
+    /// @brief returns an iterator to the reverse-beginning
+    /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
+    const_reverse_iterator rbegin() const noexcept
+    {
+        return crbegin();
+    }
+
+    /// @brief returns an iterator to the reverse-end
+    /// @sa https://json.nlohmann.me/api/basic_json/rend/
+    reverse_iterator rend() noexcept
+    {
+        return reverse_iterator(begin());
+    }
+
+    /// @brief returns an iterator to the reverse-end
+    /// @sa https://json.nlohmann.me/api/basic_json/rend/
+    const_reverse_iterator rend() const noexcept
+    {
+        return crend();
+    }
+
+    /// @brief returns a const reverse iterator to the last element
+    /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
+    const_reverse_iterator crbegin() const noexcept
+    {
+        return const_reverse_iterator(cend());
+    }
+
+    /// @brief returns a const reverse iterator to one before the first
+    /// @sa https://json.nlohmann.me/api/basic_json/crend/
+    const_reverse_iterator crend() const noexcept
+    {
+        return const_reverse_iterator(cbegin());
+    }
+
+  public:
+    /// @brief wrapper to access iterator member functions in range-based for
+    /// @sa https://json.nlohmann.me/api/basic_json/items/
+    /// @deprecated This function is deprecated since 3.1.0 and will be removed in
+    ///             version 4.0.0 of the library. Please use @ref items() instead;
+    ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
+    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
+    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
+    {
+        return ref.items();
+    }
+
+    /// @brief wrapper to access iterator member functions in range-based for
+    /// @sa https://json.nlohmann.me/api/basic_json/items/
+    /// @deprecated This function is deprecated since 3.1.0 and will be removed in
+    ///         version 4.0.0 of the library. Please use @ref items() instead;
+    ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
+    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
+    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
+    {
+        return ref.items();
+    }
+
+    /// @brief helper to access iterator member functions in range-based for
+    /// @sa https://json.nlohmann.me/api/basic_json/items/
+    iteration_proxy<iterator> items() noexcept
+    {
+        return iteration_proxy<iterator>(*this);
+    }
+
+    /// @brief helper to access iterator member functions in range-based for
+    /// @sa https://json.nlohmann.me/api/basic_json/items/
+    iteration_proxy<const_iterator> items() const noexcept
+    {
+        return iteration_proxy<const_iterator>(*this);
+    }
+
+    /// @}
+
+
+    //////////////
+    // capacity //
+    //////////////
+
+    /// @name capacity
+    /// @{
+
+    /// @brief checks whether the container is empty.
+    /// @sa https://json.nlohmann.me/api/basic_json/empty/
+    bool empty() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+            {
+                // null values are empty
+                return true;
+            }
+
+            case value_t::array:
+            {
+                // delegate call to array_t::empty()
+                return m_value.array->empty();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::empty()
+                return m_value.object->empty();
+            }
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // all other types are nonempty
+                return false;
+            }
+        }
+    }
+
+    /// @brief returns the number of elements
+    /// @sa https://json.nlohmann.me/api/basic_json/size/
+    size_type size() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+            {
+                // null values are empty
+                return 0;
+            }
+
+            case value_t::array:
+            {
+                // delegate call to array_t::size()
+                return m_value.array->size();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::size()
+                return m_value.object->size();
+            }
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // all other types have size 1
+                return 1;
+            }
+        }
+    }
+
+    /// @brief returns the maximum possible number of elements
+    /// @sa https://json.nlohmann.me/api/basic_json/max_size/
+    size_type max_size() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::array:
+            {
+                // delegate call to array_t::max_size()
+                return m_value.array->max_size();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::max_size()
+                return m_value.object->max_size();
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // all other types have max_size() == size()
+                return size();
+            }
+        }
+    }
+
+    /// @}
+
+
+    ///////////////
+    // modifiers //
+    ///////////////
+
+    /// @name modifiers
+    /// @{
+
+    /// @brief clears the contents
+    /// @sa https://json.nlohmann.me/api/basic_json/clear/
+    void clear() noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::number_integer:
+            {
+                m_value.number_integer = 0;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = 0;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value.number_float = 0.0;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value.boolean = false;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value.string->clear();
+                break;
+            }
+
+            case value_t::binary:
+            {
+                m_value.binary->clear();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value.array->clear();
+                break;
+            }
+
+            case value_t::object:
+            {
+                m_value.object->clear();
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+    /// @brief add an object to an array
+    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
+    void push_back(basic_json&& val)
+    {
+        // push_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+        {
+            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (move semantics)
+        const auto old_capacity = m_value.array->capacity();
+        m_value.array->push_back(std::move(val));
+        set_parent(m_value.array->back(), old_capacity);
+        // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
+    }
+
+    /// @brief add an object to an array
+    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
+    reference operator+=(basic_json&& val)
+    {
+        push_back(std::move(val));
+        return *this;
+    }
+
+    /// @brief add an object to an array
+    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
+    void push_back(const basic_json& val)
+    {
+        // push_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+        {
+            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array
+        const auto old_capacity = m_value.array->capacity();
+        m_value.array->push_back(val);
+        set_parent(m_value.array->back(), old_capacity);
+    }
+
+    /// @brief add an object to an array
+    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
+    reference operator+=(const basic_json& val)
+    {
+        push_back(val);
+        return *this;
+    }
+
+    /// @brief add an object to an object
+    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
+    void push_back(const typename object_t::value_type& val)
+    {
+        // push_back only works for null objects or objects
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
+        {
+            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to object
+        auto res = m_value.object->insert(val);
+        set_parent(res.first->second);
+    }
+
+    /// @brief add an object to an object
+    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
+    reference operator+=(const typename object_t::value_type& val)
+    {
+        push_back(val);
+        return *this;
+    }
+
+    /// @brief add an object to an object
+    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
+    void push_back(initializer_list_t init)
+    {
+        if (is_object() && init.size() == 2 && (*init.begin())->is_string())
+        {
+            basic_json&& key = init.begin()->moved_or_copied();
+            push_back(typename object_t::value_type(
+                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
+        }
+        else
+        {
+            push_back(basic_json(init));
+        }
+    }
+
+    /// @brief add an object to an object
+    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
+    reference operator+=(initializer_list_t init)
+    {
+        push_back(init);
+        return *this;
+    }
+
+    /// @brief add an object to an array
+    /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
+    template<class... Args>
+    reference emplace_back(Args&& ... args)
+    {
+        // emplace_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+        {
+            JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        const auto old_capacity = m_value.array->capacity();
+        m_value.array->emplace_back(std::forward<Args>(args)...);
+        return set_parent(m_value.array->back(), old_capacity);
+    }
+
+    /// @brief add an object to an object if key does not exist
+    /// @sa https://json.nlohmann.me/api/basic_json/emplace/
+    template<class... Args>
+    std::pair<iterator, bool> emplace(Args&& ... args)
+    {
+        // emplace only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
+        {
+            JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        auto res = m_value.object->emplace(std::forward<Args>(args)...);
+        set_parent(res.first->second);
+
+        // create result iterator and set iterator to the result of emplace
+        auto it = begin();
+        it.m_it.object_iterator = res.first;
+
+        // return pair of iterator and boolean
+        return {it, res.second};
+    }
+
+    /// Helper for insertion of an iterator
+    /// @note: This uses std::distance to support GCC 4.8,
+    ///        see https://github.com/nlohmann/json/pull/1257
+    template<typename... Args>
+    iterator insert_iterator(const_iterator pos, Args&& ... args)
+    {
+        iterator result(this);
+        JSON_ASSERT(m_value.array != nullptr);
+
+        auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
+        m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
+        result.m_it.array_iterator = m_value.array->begin() + insert_pos;
+
+        // This could have been written as:
+        // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
+        // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
+
+        set_parents();
+        return result;
+    }
+
+    /// @brief inserts element into array
+    /// @sa https://json.nlohmann.me/api/basic_json/insert/
+    iterator insert(const_iterator pos, const basic_json& val)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // check if iterator pos fits to this JSON value
+            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+            {
+                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
+            }
+
+            // insert to array and return iterator
+            return insert_iterator(pos, val);
+        }
+
+        JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
+    }
+
+    /// @brief inserts element into array
+    /// @sa https://json.nlohmann.me/api/basic_json/insert/
+    iterator insert(const_iterator pos, basic_json&& val)
+    {
+        return insert(pos, val);
+    }
+
+    /// @brief inserts copies of element into array
+    /// @sa https://json.nlohmann.me/api/basic_json/insert/
+    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // check if iterator pos fits to this JSON value
+            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+            {
+                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
+            }
+
+            // insert to array and return iterator
+            return insert_iterator(pos, cnt, val);
+        }
+
+        JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
+    }
+
+    /// @brief inserts range of elements into array
+    /// @sa https://json.nlohmann.me/api/basic_json/insert/
+    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_UNLIKELY(!is_array()))
+        {
+            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
+        }
+
+        // check if iterator pos fits to this JSON value
+        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
+        {
+            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
+        }
+
+        // insert to array and return iterator
+        return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
+    }
+
+    /// @brief inserts elements from initializer list into array
+    /// @sa https://json.nlohmann.me/api/basic_json/insert/
+    iterator insert(const_iterator pos, initializer_list_t ilist)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_UNLIKELY(!is_array()))
+        {
+            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
+        }
+
+        // check if iterator pos fits to this JSON value
+        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
+        }
+
+        // insert to array and return iterator
+        return insert_iterator(pos, ilist.begin(), ilist.end());
+    }
+
+    /// @brief inserts range of elements into object
+    /// @sa https://json.nlohmann.me/api/basic_json/insert/
+    void insert(const_iterator first, const_iterator last)
+    {
+        // insert only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
+        }
+
+        // passed iterators must belong to objects
+        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
+        }
+
+        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
+    }
+
+    /// @brief updates a JSON object from another object, overwriting existing keys
+    /// @sa https://json.nlohmann.me/api/basic_json/update/
+    void update(const_reference j, bool merge_objects = false)
+    {
+        update(j.begin(), j.end(), merge_objects);
+    }
+
+    /// @brief updates a JSON object from another object, overwriting existing keys
+    /// @sa https://json.nlohmann.me/api/basic_json/update/
+    void update(const_iterator first, const_iterator last, bool merge_objects = false)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
+        }
+
+        // passed iterators must belong to objects
+        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
+        {
+            JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
+        }
+
+        for (auto it = first; it != last; ++it)
+        {
+            if (merge_objects && it.value().is_object())
+            {
+                auto it2 = m_value.object->find(it.key());
+                if (it2 != m_value.object->end())
+                {
+                    it2->second.update(it.value(), true);
+                    continue;
+                }
+            }
+            m_value.object->operator[](it.key()) = it.value();
+#if JSON_DIAGNOSTICS
+            m_value.object->operator[](it.key()).m_parent = this;
+#endif
+        }
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    void swap(reference other) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value&&
+        std::is_nothrow_move_assignable<value_t>::value&&
+        std::is_nothrow_move_constructible<json_value>::value&&
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        std::swap(m_type, other.m_type);
+        std::swap(m_value, other.m_value);
+
+        set_parents();
+        other.set_parents();
+        assert_invariant();
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    friend void swap(reference left, reference right) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value&&
+        std::is_nothrow_move_assignable<value_t>::value&&
+        std::is_nothrow_move_constructible<json_value>::value&&
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        left.swap(right);
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    void swap(array_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            using std::swap;
+            swap(*(m_value.array), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
+        }
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    void swap(object_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            using std::swap;
+            swap(*(m_value.object), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
+        }
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    void swap(string_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_string()))
+        {
+            using std::swap;
+            swap(*(m_value.string), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
+        }
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_binary()))
+        {
+            using std::swap;
+            swap(*(m_value.binary), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
+        }
+    }
+
+    /// @brief exchanges the values
+    /// @sa https://json.nlohmann.me/api/basic_json/swap/
+    void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_binary()))
+        {
+            using std::swap;
+            swap(*(m_value.binary), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
+        }
+    }
+
+    /// @}
+
+    //////////////////////////////////////////
+    // lexicographical comparison operators //
+    //////////////////////////////////////////
+
+    /// @name lexicographical comparison operators
+    /// @{
+
+    // note parentheses around operands are necessary; see
+    // https://github.com/nlohmann/json/issues/1530
+#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
+    const auto lhs_type = lhs.type();                                                                    \
+    const auto rhs_type = rhs.type();                                                                    \
+    \
+    if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
+    {                                                                                                    \
+        switch (lhs_type)                                                                                \
+        {                                                                                                \
+            case value_t::array:                                                                         \
+                return (*lhs.m_value.array) op (*rhs.m_value.array);                                     \
+                \
+            case value_t::object:                                                                        \
+                return (*lhs.m_value.object) op (*rhs.m_value.object);                                   \
+                \
+            case value_t::null:                                                                          \
+                return (null_result);                                                                    \
+                \
+            case value_t::string:                                                                        \
+                return (*lhs.m_value.string) op (*rhs.m_value.string);                                   \
+                \
+            case value_t::boolean:                                                                       \
+                return (lhs.m_value.boolean) op (rhs.m_value.boolean);                                   \
+                \
+            case value_t::number_integer:                                                                \
+                return (lhs.m_value.number_integer) op (rhs.m_value.number_integer);                     \
+                \
+            case value_t::number_unsigned:                                                               \
+                return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned);                   \
+                \
+            case value_t::number_float:                                                                  \
+                return (lhs.m_value.number_float) op (rhs.m_value.number_float);                         \
+                \
+            case value_t::binary:                                                                        \
+                return (*lhs.m_value.binary) op (*rhs.m_value.binary);                                   \
+                \
+            case value_t::discarded:                                                                     \
+            default:                                                                                     \
+                return (unordered_result);                                                               \
+        }                                                                                                \
+    }                                                                                                    \
+    else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
+    {                                                                                                    \
+        return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float;      \
+    }                                                                                                    \
+    else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
+    {                                                                                                    \
+        return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer);      \
+    }                                                                                                    \
+    else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
+    {                                                                                                    \
+        return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float;     \
+    }                                                                                                    \
+    else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
+    {                                                                                                    \
+        return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned);     \
+    }                                                                                                    \
+    else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
+    {                                                                                                    \
+        return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
+    }                                                                                                    \
+    else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
+    {                                                                                                    \
+        return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
+    }                                                                                                    \
+    else if(compares_unordered(lhs, rhs))\
+    {\
+        return (unordered_result);\
+    }\
+    \
+    return (default_result);
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    // returns true if:
+    // - any operand is NaN and the other operand is of number type
+    // - any operand is discarded
+    // in legacy mode, discarded values are considered ordered if
+    // an operation is computed as an odd number of inverses of others
+    static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
+    {
+        if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
+                || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
+        {
+            return true;
+        }
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+        return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
+#else
+        static_cast<void>(inverse);
+        return lhs.is_discarded() || rhs.is_discarded();
+#endif
+    }
+
+  private:
+    bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
+    {
+        return compares_unordered(*this, rhs, inverse);
+    }
+
+  public:
+#if JSON_HAS_THREE_WAY_COMPARISON
+    /// @brief comparison: equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+    bool operator==(const_reference rhs) const noexcept
+    {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+        const_reference lhs = *this;
+        JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+    }
+
+    /// @brief comparison: equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+    template<typename ScalarType>
+    requires std::is_scalar_v<ScalarType>
+    bool operator==(ScalarType rhs) const noexcept
+    {
+        return *this == basic_json(rhs);
+    }
+
+    /// @brief comparison: not equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
+    bool operator!=(const_reference rhs) const noexcept
+    {
+        if (compares_unordered(rhs, true))
+        {
+            return false;
+        }
+        return !operator==(rhs);
+    }
+
+    /// @brief comparison: 3-way
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
+    std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
+    {
+        const_reference lhs = *this;
+        // default_result is used if we cannot compare values. In that case,
+        // we compare types.
+        JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
+                                std::partial_ordering::equivalent,
+                                std::partial_ordering::unordered,
+                                lhs_type <=> rhs_type) // *NOPAD*
+    }
+
+    /// @brief comparison: 3-way
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
+    template<typename ScalarType>
+    requires std::is_scalar_v<ScalarType>
+    std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
+    {
+        return *this <=> basic_json(rhs); // *NOPAD*
+    }
+
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+    // all operators that are computed as an odd number of inverses of others
+    // need to be overloaded to emulate the legacy comparison behavior
+
+    /// @brief comparison: less than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
+    bool operator<=(const_reference rhs) const noexcept
+    {
+        if (compares_unordered(rhs, true))
+        {
+            return false;
+        }
+        return !(rhs < *this);
+    }
+
+    /// @brief comparison: less than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+    template<typename ScalarType>
+    requires std::is_scalar_v<ScalarType>
+    bool operator<=(ScalarType rhs) const noexcept
+    {
+        return *this <= basic_json(rhs);
+    }
+
+    /// @brief comparison: greater than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
+    bool operator>=(const_reference rhs) const noexcept
+    {
+        if (compares_unordered(rhs, true))
+        {
+            return false;
+        }
+        return !(*this < rhs);
+    }
+
+    /// @brief comparison: greater than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+    template<typename ScalarType>
+    requires std::is_scalar_v<ScalarType>
+    bool operator>=(ScalarType rhs) const noexcept
+    {
+        return *this >= basic_json(rhs);
+    }
+#endif
+#else
+    /// @brief comparison: equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
+    {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+        JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+    }
+
+    /// @brief comparison: equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs == basic_json(rhs);
+    }
+
+    /// @brief comparison: equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) == rhs;
+    }
+
+    /// @brief comparison: not equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
+    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
+    {
+        if (compares_unordered(lhs, rhs, true))
+        {
+            return false;
+        }
+        return !(lhs == rhs);
+    }
+
+    /// @brief comparison: not equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs != basic_json(rhs);
+    }
+
+    /// @brief comparison: not equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) != rhs;
+    }
+
+    /// @brief comparison: less than
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
+    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
+    {
+        // default_result is used if we cannot compare values. In that case,
+        // we compare types. Note we have to call the operator explicitly,
+        // because MSVC has problems otherwise.
+        JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
+    }
+
+    /// @brief comparison: less than
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs < basic_json(rhs);
+    }
+
+    /// @brief comparison: less than
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) < rhs;
+    }
+
+    /// @brief comparison: less than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
+    {
+        if (compares_unordered(lhs, rhs, true))
+        {
+            return false;
+        }
+        return !(rhs < lhs);
+    }
+
+    /// @brief comparison: less than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs <= basic_json(rhs);
+    }
+
+    /// @brief comparison: less than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) <= rhs;
+    }
+
+    /// @brief comparison: greater than
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
+    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
+    {
+        // double inverse
+        if (compares_unordered(lhs, rhs))
+        {
+            return false;
+        }
+        return !(lhs <= rhs);
+    }
+
+    /// @brief comparison: greater than
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs > basic_json(rhs);
+    }
+
+    /// @brief comparison: greater than
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) > rhs;
+    }
+
+    /// @brief comparison: greater than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
+    {
+        if (compares_unordered(lhs, rhs, true))
+        {
+            return false;
+        }
+        return !(lhs < rhs);
+    }
+
+    /// @brief comparison: greater than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs >= basic_json(rhs);
+    }
+
+    /// @brief comparison: greater than or equal
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) >= rhs;
+    }
+#endif
+
+#undef JSON_IMPLEMENT_OPERATOR
+
+    /// @}
+
+    ///////////////////
+    // serialization //
+    ///////////////////
+
+    /// @name serialization
+    /// @{
+#ifndef JSON_NO_IO
+    /// @brief serialize to stream
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
+    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
+    {
+        // read width member and use it as indentation parameter if nonzero
+        const bool pretty_print = o.width() > 0;
+        const auto indentation = pretty_print ? o.width() : 0;
+
+        // reset width to 0 for subsequent calls to this stream
+        o.width(0);
+
+        // do the actual serialization
+        serializer s(detail::output_adapter<char>(o), o.fill());
+        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
+        return o;
+    }
+
+    /// @brief serialize to stream
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
+    /// @deprecated This function is deprecated since 3.0.0 and will be removed in
+    ///             version 4.0.0 of the library. Please use
+    ///             operator<<(std::ostream&, const basic_json&) instead; that is,
+    ///             replace calls like `j >> o;` with `o << j;`.
+    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
+    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
+    {
+        return o << j;
+    }
+#endif  // JSON_NO_IO
+    /// @}
+
+
+    /////////////////////
+    // deserialization //
+    /////////////////////
+
+    /// @name deserialization
+    /// @{
+
+    /// @brief deserialize from a compatible input
+    /// @sa https://json.nlohmann.me/api/basic_json/parse/
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json parse(InputType&& i,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true,
+                            const bool ignore_comments = false)
+    {
+        basic_json result;
+        parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
+        return result;
+    }
+
+    /// @brief deserialize from a pair of character iterators
+    /// @sa https://json.nlohmann.me/api/basic_json/parse/
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json parse(IteratorType first,
+                            IteratorType last,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true,
+                            const bool ignore_comments = false)
+    {
+        basic_json result;
+        parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
+        return result;
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
+    static basic_json parse(detail::span_input_adapter&& i,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true,
+                            const bool ignore_comments = false)
+    {
+        basic_json result;
+        parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
+        return result;
+    }
+
+    /// @brief check if the input is valid JSON
+    /// @sa https://json.nlohmann.me/api/basic_json/accept/
+    template<typename InputType>
+    static bool accept(InputType&& i,
+                       const bool ignore_comments = false)
+    {
+        return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
+    }
+
+    /// @brief check if the input is valid JSON
+    /// @sa https://json.nlohmann.me/api/basic_json/accept/
+    template<typename IteratorType>
+    static bool accept(IteratorType first, IteratorType last,
+                       const bool ignore_comments = false)
+    {
+        return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
+    static bool accept(detail::span_input_adapter&& i,
+                       const bool ignore_comments = false)
+    {
+        return parser(i.get(), nullptr, false, ignore_comments).accept(true);
+    }
+
+    /// @brief generate SAX events
+    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
+    template <typename InputType, typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    static bool sax_parse(InputType&& i, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true,
+                          const bool ignore_comments = false)
+    {
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        return format == input_format_t::json
+               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
+    }
+
+    /// @brief generate SAX events
+    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
+    template<class IteratorType, class SAX>
+    JSON_HEDLEY_NON_NULL(3)
+    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true,
+                          const bool ignore_comments = false)
+    {
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        return format == input_format_t::json
+               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
+    }
+
+    /// @brief generate SAX events
+    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
+    /// @deprecated This function is deprecated since 3.8.0 and will be removed in
+    ///             version 4.0.0 of the library. Please use
+    ///             sax_parse(ptr, ptr + len) instead.
+    template <typename SAX>
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
+    JSON_HEDLEY_NON_NULL(2)
+    static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true,
+                          const bool ignore_comments = false)
+    {
+        auto ia = i.get();
+        return format == input_format_t::json
+               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
+    }
+#ifndef JSON_NO_IO
+    /// @brief deserialize from stream
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
+    /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
+    ///             version 4.0.0 of the library. Please use
+    ///             operator>>(std::istream&, basic_json&) instead; that is,
+    ///             replace calls like `j << i;` with `i >> j;`.
+    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
+    friend std::istream& operator<<(basic_json& j, std::istream& i)
+    {
+        return operator>>(i, j);
+    }
+
+    /// @brief deserialize from stream
+    /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
+    friend std::istream& operator>>(std::istream& i, basic_json& j)
+    {
+        parser(detail::input_adapter(i)).parse(false, j);
+        return i;
+    }
+#endif  // JSON_NO_IO
+    /// @}
+
+    ///////////////////////////
+    // convenience functions //
+    ///////////////////////////
+
+    /// @brief return the type as string
+    /// @sa https://json.nlohmann.me/api/basic_json/type_name/
+    JSON_HEDLEY_RETURNS_NON_NULL
+    const char* type_name() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+                return "null";
+            case value_t::object:
+                return "object";
+            case value_t::array:
+                return "array";
+            case value_t::string:
+                return "string";
+            case value_t::boolean:
+                return "boolean";
+            case value_t::binary:
+                return "binary";
+            case value_t::discarded:
+                return "discarded";
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            default:
+                return "number";
+        }
+    }
+
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    //////////////////////
+    // member variables //
+    //////////////////////
+
+    /// the type of the current element
+    value_t m_type = value_t::null;
+
+    /// the value of the current element
+    json_value m_value = {};
+
+#if JSON_DIAGNOSTICS
+    /// a pointer to a parent value (for debugging purposes)
+    basic_json* m_parent = nullptr;
+#endif
+
+    //////////////////////////////////////////
+    // binary serialization/deserialization //
+    //////////////////////////////////////////
+
+    /// @name binary serialization/deserialization support
+    /// @{
+
+  public:
+    /// @brief create a CBOR serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
+    static std::vector<std::uint8_t> to_cbor(const basic_json& j)
+    {
+        std::vector<std::uint8_t> result;
+        to_cbor(j, result);
+        return result;
+    }
+
+    /// @brief create a CBOR serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
+    static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+    {
+        binary_writer<std::uint8_t>(o).write_cbor(j);
+    }
+
+    /// @brief create a CBOR serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
+    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_cbor(j);
+    }
+
+    /// @brief create a MessagePack serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
+    static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
+    {
+        std::vector<std::uint8_t> result;
+        to_msgpack(j, result);
+        return result;
+    }
+
+    /// @brief create a MessagePack serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
+    static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+    {
+        binary_writer<std::uint8_t>(o).write_msgpack(j);
+    }
+
+    /// @brief create a MessagePack serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
+    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_msgpack(j);
+    }
+
+    /// @brief create a UBJSON serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
+    static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
+            const bool use_size = false,
+            const bool use_type = false)
+    {
+        std::vector<std::uint8_t> result;
+        to_ubjson(j, result, use_size, use_type);
+        return result;
+    }
+
+    /// @brief create a UBJSON serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
+    static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
+    }
+
+    /// @brief create a UBJSON serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
+    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
+    }
+
+    /// @brief create a BJData serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
+    static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
+            const bool use_size = false,
+            const bool use_type = false)
+    {
+        std::vector<std::uint8_t> result;
+        to_bjdata(j, result, use_size, use_type);
+        return result;
+    }
+
+    /// @brief create a BJData serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
+    static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
+    }
+
+    /// @brief create a BJData serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
+    static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
+    }
+
+    /// @brief create a BSON serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
+    static std::vector<std::uint8_t> to_bson(const basic_json& j)
+    {
+        std::vector<std::uint8_t> result;
+        to_bson(j, result);
+        return result;
+    }
+
+    /// @brief create a BSON serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
+    static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+    {
+        binary_writer<std::uint8_t>(o).write_bson(j);
+    }
+
+    /// @brief create a BSON serialization of a given JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
+    static void to_bson(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_bson(j);
+    }
+
+    /// @brief create a JSON value from an input in CBOR format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_cbor(InputType&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in CBOR format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_cbor(IteratorType first, IteratorType last,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
+    static basic_json from_cbor(const T* ptr, std::size_t len,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
+    }
+
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
+    static basic_json from_cbor(detail::span_input_adapter&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in MessagePack format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_msgpack(InputType&& i,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in MessagePack format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_msgpack(IteratorType first, IteratorType last,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
+    static basic_json from_msgpack(const T* ptr, std::size_t len,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
+    static basic_json from_msgpack(detail::span_input_adapter&& i,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in UBJSON format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_ubjson(InputType&& i,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in UBJSON format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_ubjson(IteratorType first, IteratorType last,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
+    static basic_json from_ubjson(const T* ptr, std::size_t len,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
+    static basic_json from_ubjson(detail::span_input_adapter&& i,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+
+    /// @brief create a JSON value from an input in BJData format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bjdata(InputType&& i,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in BJData format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bjdata(IteratorType first, IteratorType last,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in BSON format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bson(InputType&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /// @brief create a JSON value from an input in BSON format
+    /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bson(IteratorType first, IteratorType last,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
+    static basic_json from_bson(const T* ptr, std::size_t len,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        return from_bson(ptr, ptr + len, strict, allow_exceptions);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
+    static basic_json from_bson(detail::span_input_adapter&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+    /// @}
+
+    //////////////////////////
+    // JSON Pointer support //
+    //////////////////////////
+
+    /// @name JSON Pointer functions
+    /// @{
+
+    /// @brief access specified element via JSON Pointer
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    reference operator[](const json_pointer& ptr)
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    /// @brief access specified element via JSON Pointer
+    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+    const_reference operator[](const json_pointer& ptr) const
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    /// @brief access specified element via JSON Pointer
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    reference at(const json_pointer& ptr)
+    {
+        return ptr.get_checked(this);
+    }
+
+    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
+    {
+        return ptr.get_checked(this);
+    }
+
+    /// @brief access specified element via JSON Pointer
+    /// @sa https://json.nlohmann.me/api/basic_json/at/
+    const_reference at(const json_pointer& ptr) const
+    {
+        return ptr.get_checked(this);
+    }
+
+    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+    const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
+    {
+        return ptr.get_checked(this);
+    }
+
+    /// @brief return flattened JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/flatten/
+    basic_json flatten() const
+    {
+        basic_json result(value_t::object);
+        json_pointer::flatten("", *this, result);
+        return result;
+    }
+
+    /// @brief unflatten a previously flattened JSON value
+    /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
+    basic_json unflatten() const
+    {
+        return json_pointer::unflatten(*this);
+    }
+
+    /// @}
+
+    //////////////////////////
+    // JSON Patch functions //
+    //////////////////////////
+
+    /// @name JSON Patch functions
+    /// @{
+
+    /// @brief applies a JSON patch in-place without copying the object
+    /// @sa https://json.nlohmann.me/api/basic_json/patch/
+    void patch_inplace(const basic_json& json_patch)
+    {
+        basic_json& result = *this;
+        // the valid JSON Patch operations
+        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
+
+        const auto get_op = [](const std::string & op)
+        {
+            if (op == "add")
+            {
+                return patch_operations::add;
+            }
+            if (op == "remove")
+            {
+                return patch_operations::remove;
+            }
+            if (op == "replace")
+            {
+                return patch_operations::replace;
+            }
+            if (op == "move")
+            {
+                return patch_operations::move;
+            }
+            if (op == "copy")
+            {
+                return patch_operations::copy;
+            }
+            if (op == "test")
+            {
+                return patch_operations::test;
+            }
+
+            return patch_operations::invalid;
+        };
+
+        // wrapper for "add" operation; add value at ptr
+        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
+        {
+            // adding to the root of the target document means replacing it
+            if (ptr.empty())
+            {
+                result = val;
+                return;
+            }
+
+            // make sure the top element of the pointer exists
+            json_pointer top_pointer = ptr.top();
+            if (top_pointer != ptr)
+            {
+                result.at(top_pointer);
+            }
+
+            // get reference to parent of JSON pointer ptr
+            const auto last_path = ptr.back();
+            ptr.pop_back();
+            // parent must exist when performing patch add per RFC6902 specs
+            basic_json& parent = result.at(ptr);
+
+            switch (parent.m_type)
+            {
+                case value_t::null:
+                case value_t::object:
+                {
+                    // use operator[] to add value
+                    parent[last_path] = val;
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    if (last_path == "-")
+                    {
+                        // special case: append to back
+                        parent.push_back(val);
+                    }
+                    else
+                    {
+                        const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
+                        if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
+                        {
+                            // avoid undefined behavior
+                            JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
+                        }
+
+                        // default case: insert add offset
+                        parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
+                    }
+                    break;
+                }
+
+                // if there exists a parent it cannot be primitive
+                case value_t::string: // LCOV_EXCL_LINE
+                case value_t::boolean: // LCOV_EXCL_LINE
+                case value_t::number_integer: // LCOV_EXCL_LINE
+                case value_t::number_unsigned: // LCOV_EXCL_LINE
+                case value_t::number_float: // LCOV_EXCL_LINE
+                case value_t::binary: // LCOV_EXCL_LINE
+                case value_t::discarded: // LCOV_EXCL_LINE
+                default:            // LCOV_EXCL_LINE
+                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+            }
+        };
+
+        // wrapper for "remove" operation; remove value at ptr
+        const auto operation_remove = [this, &result](json_pointer & ptr)
+        {
+            // get reference to parent of JSON pointer ptr
+            const auto last_path = ptr.back();
+            ptr.pop_back();
+            basic_json& parent = result.at(ptr);
+
+            // remove child
+            if (parent.is_object())
+            {
+                // perform range check
+                auto it = parent.find(last_path);
+                if (JSON_HEDLEY_LIKELY(it != parent.end()))
+                {
+                    parent.erase(it);
+                }
+                else
+                {
+                    JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
+                }
+            }
+            else if (parent.is_array())
+            {
+                // note erase performs range check
+                parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
+            }
+        };
+
+        // type check: top level value must be an array
+        if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
+        {
+            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
+        }
+
+        // iterate and apply the operations
+        for (const auto& val : json_patch)
+        {
+            // wrapper to get a value for an operation
+            const auto get_value = [&val](const std::string & op,
+                                          const std::string & member,
+                                          bool string_type) -> basic_json &
+            {
+                // find value
+                auto it = val.m_value.object->find(member);
+
+                // context-sensitive error message
+                const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
+
+                // check if desired value is present
+                if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
+                {
+                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
+                    JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
+                }
+
+                // check if result is of type string
+                if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
+                {
+                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
+                    JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
+                }
+
+                // no error: return value
+                return it->second;
+            };
+
+            // type check: every element of the array must be an object
+            if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
+            {
+                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
+            }
+
+            // collect mandatory members
+            const auto op = get_value("op", "op", true).template get<std::string>();
+            const auto path = get_value(op, "path", true).template get<std::string>();
+            json_pointer ptr(path);
+
+            switch (get_op(op))
+            {
+                case patch_operations::add:
+                {
+                    operation_add(ptr, get_value("add", "value", false));
+                    break;
+                }
+
+                case patch_operations::remove:
+                {
+                    operation_remove(ptr);
+                    break;
+                }
+
+                case patch_operations::replace:
+                {
+                    // the "path" location must exist - use at()
+                    result.at(ptr) = get_value("replace", "value", false);
+                    break;
+                }
+
+                case patch_operations::move:
+                {
+                    const auto from_path = get_value("move", "from", true).template get<std::string>();
+                    json_pointer from_ptr(from_path);
+
+                    // the "from" location must exist - use at()
+                    basic_json v = result.at(from_ptr);
+
+                    // The move operation is functionally identical to a
+                    // "remove" operation on the "from" location, followed
+                    // immediately by an "add" operation at the target
+                    // location with the value that was just removed.
+                    operation_remove(from_ptr);
+                    operation_add(ptr, v);
+                    break;
+                }
+
+                case patch_operations::copy:
+                {
+                    const auto from_path = get_value("copy", "from", true).template get<std::string>();
+                    const json_pointer from_ptr(from_path);
+
+                    // the "from" location must exist - use at()
+                    basic_json v = result.at(from_ptr);
+
+                    // The copy is functionally identical to an "add"
+                    // operation at the target location using the value
+                    // specified in the "from" member.
+                    operation_add(ptr, v);
+                    break;
+                }
+
+                case patch_operations::test:
+                {
+                    bool success = false;
+                    JSON_TRY
+                    {
+                        // check if "value" matches the one at "path"
+                        // the "path" location must exist - use at()
+                        success = (result.at(ptr) == get_value("test", "value", false));
+                    }
+                    JSON_INTERNAL_CATCH (out_of_range&)
+                    {
+                        // ignore out of range errors: success remains false
+                    }
+
+                    // throw an exception if test fails
+                    if (JSON_HEDLEY_UNLIKELY(!success))
+                    {
+                        JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
+                    }
+
+                    break;
+                }
+
+                case patch_operations::invalid:
+                default:
+                {
+                    // op must be "add", "remove", "replace", "move", "copy", or
+                    // "test"
+                    JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
+                }
+            }
+        }
+    }
+
+    /// @brief applies a JSON patch to a copy of the current object
+    /// @sa https://json.nlohmann.me/api/basic_json/patch/
+    basic_json patch(const basic_json& json_patch) const
+    {
+        basic_json result = *this;
+        result.patch_inplace(json_patch);
+        return result;
+    }
+
+    /// @brief creates a diff as a JSON patch
+    /// @sa https://json.nlohmann.me/api/basic_json/diff/
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json diff(const basic_json& source, const basic_json& target,
+                           const std::string& path = "")
+    {
+        // the patch
+        basic_json result(value_t::array);
+
+        // if the values are the same, return empty patch
+        if (source == target)
+        {
+            return result;
+        }
+
+        if (source.type() != target.type())
+        {
+            // different types: replace value
+            result.push_back(
+            {
+                {"op", "replace"}, {"path", path}, {"value", target}
+            });
+            return result;
+        }
+
+        switch (source.type())
+        {
+            case value_t::array:
+            {
+                // first pass: traverse common elements
+                std::size_t i = 0;
+                while (i < source.size() && i < target.size())
+                {
+                    // recursive call to compare array values at index i
+                    auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
+                    result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+                    ++i;
+                }
+
+                // We now reached the end of at least one array
+                // in a second pass, traverse the remaining elements
+
+                // remove my remaining elements
+                const auto end_index = static_cast<difference_type>(result.size());
+                while (i < source.size())
+                {
+                    // add operations in reverse order to avoid invalid
+                    // indices
+                    result.insert(result.begin() + end_index, object(
+                    {
+                        {"op", "remove"},
+                        {"path", detail::concat(path, '/', std::to_string(i))}
+                    }));
+                    ++i;
+                }
+
+                // add other remaining elements
+                while (i < target.size())
+                {
+                    result.push_back(
+                    {
+                        {"op", "add"},
+                        {"path", detail::concat(path, "/-")},
+                        {"value", target[i]}
+                    });
+                    ++i;
+                }
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // first pass: traverse this object's elements
+                for (auto it = source.cbegin(); it != source.cend(); ++it)
+                {
+                    // escape the key name to be used in a JSON patch
+                    const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
+
+                    if (target.find(it.key()) != target.end())
+                    {
+                        // recursive call to compare object values at key it
+                        auto temp_diff = diff(it.value(), target[it.key()], path_key);
+                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+                    }
+                    else
+                    {
+                        // found a key that is not in o -> remove it
+                        result.push_back(object(
+                        {
+                            {"op", "remove"}, {"path", path_key}
+                        }));
+                    }
+                }
+
+                // second pass: traverse other object's elements
+                for (auto it = target.cbegin(); it != target.cend(); ++it)
+                {
+                    if (source.find(it.key()) == source.end())
+                    {
+                        // found a key that is not in this -> add it
+                        const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
+                        result.push_back(
+                        {
+                            {"op", "add"}, {"path", path_key},
+                            {"value", it.value()}
+                        });
+                    }
+                }
+
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // both primitive type: replace value
+                result.push_back(
+                {
+                    {"op", "replace"}, {"path", path}, {"value", target}
+                });
+                break;
+            }
+        }
+
+        return result;
+    }
+    /// @}
+
+    ////////////////////////////////
+    // JSON Merge Patch functions //
+    ////////////////////////////////
+
+    /// @name JSON Merge Patch functions
+    /// @{
+
+    /// @brief applies a JSON Merge Patch
+    /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
+    void merge_patch(const basic_json& apply_patch)
+    {
+        if (apply_patch.is_object())
+        {
+            if (!is_object())
+            {
+                *this = object();
+            }
+            for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
+            {
+                if (it.value().is_null())
+                {
+                    erase(it.key());
+                }
+                else
+                {
+                    operator[](it.key()).merge_patch(it.value());
+                }
+            }
+        }
+        else
+        {
+            *this = apply_patch;
+        }
+    }
+
+    /// @}
+};
+
+/// @brief user-defined to_string function for JSON values
+/// @sa https://json.nlohmann.me/api/basic_json/to_string/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
+{
+    return j.dump();
+}
+
+inline namespace literals
+{
+inline namespace json_literals
+{
+
+/// @brief user-defined string literal for JSON values
+/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json operator "" _json(const char* s, std::size_t n)
+{
+    return nlohmann::json::parse(s, s + n);
+}
+
+/// @brief user-defined string literal for JSON pointer
+/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
+{
+    return nlohmann::json::json_pointer(std::string(s, n));
+}
+
+}  // namespace json_literals
+}  // namespace literals
+NLOHMANN_JSON_NAMESPACE_END
+
+///////////////////////
+// nonmember support //
+///////////////////////
+
+namespace std // NOLINT(cert-dcl58-cpp)
+{
+
+/// @brief hash value for JSON objects
+/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
+{
+    std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
+    {
+        return nlohmann::detail::hash(j);
+    }
+};
+
+// specialization for std::less<value_t>
+template<>
+struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
+{
+    /*!
+    @brief compare two value_t enum values
+    @since version 3.0.0
+    */
+    bool operator()(::nlohmann::detail::value_t lhs,
+                    ::nlohmann::detail::value_t rhs) const noexcept
+    {
+#if JSON_HAS_THREE_WAY_COMPARISON
+        return std::is_lt(lhs <=> rhs); // *NOPAD*
+#else
+        return ::nlohmann::detail::operator<(lhs, rhs);
+#endif
+    }
+};
+
+// C++20 prohibit function specialization in the std namespace.
+#ifndef JSON_HAS_CPP_20
+
+/// @brief exchanges the values of two JSON objects
+/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name)
+    is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression)
+    is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
+{
+    j1.swap(j2);
+}
+
+#endif
+
+}  // namespace std
+
+#if JSON_USE_GLOBAL_UDLS
+    using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
+    using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
+#endif
+
+// #include <nlohmann/detail/macro_unscope.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// restore clang diagnostic settings
+#if defined(__clang__)
+    #pragma clang diagnostic pop
+#endif
+
+// clean up
+#undef JSON_ASSERT
+#undef JSON_INTERNAL_CATCH
+#undef JSON_THROW
+#undef JSON_PRIVATE_UNLESS_TESTED
+#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
+#undef NLOHMANN_BASIC_JSON_TPL
+#undef JSON_EXPLICIT
+#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
+#undef JSON_INLINE_VARIABLE
+#undef JSON_NO_UNIQUE_ADDRESS
+#undef JSON_DISABLE_ENUM_SERIALIZATION
+#undef JSON_USE_GLOBAL_UDLS
+
+#ifndef JSON_TEST_KEEP_MACROS
+    #undef JSON_CATCH
+    #undef JSON_TRY
+    #undef JSON_HAS_CPP_11
+    #undef JSON_HAS_CPP_14
+    #undef JSON_HAS_CPP_17
+    #undef JSON_HAS_CPP_20
+    #undef JSON_HAS_FILESYSTEM
+    #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+    #undef JSON_HAS_THREE_WAY_COMPARISON
+    #undef JSON_HAS_RANGES
+    #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+#endif
+
+// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#undef JSON_HEDLEY_ALWAYS_INLINE
+#undef JSON_HEDLEY_ARM_VERSION
+#undef JSON_HEDLEY_ARM_VERSION_CHECK
+#undef JSON_HEDLEY_ARRAY_PARAM
+#undef JSON_HEDLEY_ASSUME
+#undef JSON_HEDLEY_BEGIN_C_DECLS
+#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#undef JSON_HEDLEY_CLANG_HAS_WARNING
+#undef JSON_HEDLEY_COMPCERT_VERSION
+#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#undef JSON_HEDLEY_CONCAT
+#undef JSON_HEDLEY_CONCAT3
+#undef JSON_HEDLEY_CONCAT3_EX
+#undef JSON_HEDLEY_CONCAT_EX
+#undef JSON_HEDLEY_CONST
+#undef JSON_HEDLEY_CONSTEXPR
+#undef JSON_HEDLEY_CONST_CAST
+#undef JSON_HEDLEY_CPP_CAST
+#undef JSON_HEDLEY_CRAY_VERSION
+#undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#undef JSON_HEDLEY_C_DECL
+#undef JSON_HEDLEY_DEPRECATED
+#undef JSON_HEDLEY_DEPRECATED_FOR
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#undef JSON_HEDLEY_DIAGNOSTIC_POP
+#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#undef JSON_HEDLEY_DMC_VERSION
+#undef JSON_HEDLEY_DMC_VERSION_CHECK
+#undef JSON_HEDLEY_EMPTY_BASES
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#undef JSON_HEDLEY_END_C_DECLS
+#undef JSON_HEDLEY_FLAGS
+#undef JSON_HEDLEY_FLAGS_CAST
+#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#undef JSON_HEDLEY_GCC_HAS_FEATURE
+#undef JSON_HEDLEY_GCC_HAS_WARNING
+#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#undef JSON_HEDLEY_GCC_VERSION
+#undef JSON_HEDLEY_GCC_VERSION_CHECK
+#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#undef JSON_HEDLEY_GNUC_HAS_WARNING
+#undef JSON_HEDLEY_GNUC_VERSION
+#undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#undef JSON_HEDLEY_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_BUILTIN
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_EXTENSION
+#undef JSON_HEDLEY_HAS_FEATURE
+#undef JSON_HEDLEY_HAS_WARNING
+#undef JSON_HEDLEY_IAR_VERSION
+#undef JSON_HEDLEY_IAR_VERSION_CHECK
+#undef JSON_HEDLEY_IBM_VERSION
+#undef JSON_HEDLEY_IBM_VERSION_CHECK
+#undef JSON_HEDLEY_IMPORT
+#undef JSON_HEDLEY_INLINE
+#undef JSON_HEDLEY_INTEL_CL_VERSION
+#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
+#undef JSON_HEDLEY_INTEL_VERSION
+#undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#undef JSON_HEDLEY_IS_CONSTANT
+#undef JSON_HEDLEY_IS_CONSTEXPR_
+#undef JSON_HEDLEY_LIKELY
+#undef JSON_HEDLEY_MALLOC
+#undef JSON_HEDLEY_MCST_LCC_VERSION
+#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
+#undef JSON_HEDLEY_MESSAGE
+#undef JSON_HEDLEY_MSVC_VERSION
+#undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#undef JSON_HEDLEY_NEVER_INLINE
+#undef JSON_HEDLEY_NON_NULL
+#undef JSON_HEDLEY_NO_ESCAPE
+#undef JSON_HEDLEY_NO_RETURN
+#undef JSON_HEDLEY_NO_THROW
+#undef JSON_HEDLEY_NULL
+#undef JSON_HEDLEY_PELLES_VERSION
+#undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#undef JSON_HEDLEY_PGI_VERSION
+#undef JSON_HEDLEY_PGI_VERSION_CHECK
+#undef JSON_HEDLEY_PREDICT
+#undef JSON_HEDLEY_PRINTF_FORMAT
+#undef JSON_HEDLEY_PRIVATE
+#undef JSON_HEDLEY_PUBLIC
+#undef JSON_HEDLEY_PURE
+#undef JSON_HEDLEY_REINTERPRET_CAST
+#undef JSON_HEDLEY_REQUIRE
+#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#undef JSON_HEDLEY_REQUIRE_MSG
+#undef JSON_HEDLEY_RESTRICT
+#undef JSON_HEDLEY_RETURNS_NON_NULL
+#undef JSON_HEDLEY_SENTINEL
+#undef JSON_HEDLEY_STATIC_ASSERT
+#undef JSON_HEDLEY_STATIC_CAST
+#undef JSON_HEDLEY_STRINGIFY
+#undef JSON_HEDLEY_STRINGIFY_EX
+#undef JSON_HEDLEY_SUNPRO_VERSION
+#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#undef JSON_HEDLEY_TINYC_VERSION
+#undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#undef JSON_HEDLEY_TI_ARMCL_VERSION
+#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL2000_VERSION
+#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL430_VERSION
+#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL6X_VERSION
+#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL7X_VERSION
+#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CLPRU_VERSION
+#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
+#undef JSON_HEDLEY_TI_VERSION
+#undef JSON_HEDLEY_TI_VERSION_CHECK
+#undef JSON_HEDLEY_UNAVAILABLE
+#undef JSON_HEDLEY_UNLIKELY
+#undef JSON_HEDLEY_UNPREDICTABLE
+#undef JSON_HEDLEY_UNREACHABLE
+#undef JSON_HEDLEY_UNREACHABLE_RETURN
+#undef JSON_HEDLEY_VERSION
+#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#undef JSON_HEDLEY_VERSION_ENCODE
+#undef JSON_HEDLEY_WARNING
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
+#undef JSON_HEDLEY_FALL_THROUGH
+
+
+
+#endif  // INCLUDE_NLOHMANN_JSON_HPP_
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/single_include/nlohmann/json_fwd.hpp b/3rd-party/nlohmann_json_cmake_fetchcontent/single_include/nlohmann/json_fwd.hpp
new file mode 100644
index 0000000..67172b1
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/single_include/nlohmann/json_fwd.hpp
@@ -0,0 +1,74 @@
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++
+// |  |  |__   |  |  | | | |  version 3.11.2
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
+#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+#include <cstdint> // int64_t, uint64_t
+#include <map> // map
+#include <memory> // allocator
+#include <string> // string
+#include <vector> // vector
+
+#include <nlohmann/detail/abi_macros.hpp>
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
+/*!
+@brief default JSONSerializer template argument
+
+This serializer ignores the template arguments and uses ADL
+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
+for serialization.
+*/
+template<typename T = void, typename SFINAE = void>
+struct adl_serializer;
+
+/// a class to store JSON values
+/// @sa https://json.nlohmann.me/api/basic_json/
+template<template<typename U, typename V, typename... Args> class ObjectType =
+         std::map,
+         template<typename U, typename... Args> class ArrayType = std::vector,
+         class StringType = std::string, class BooleanType = bool,
+         class NumberIntegerType = std::int64_t,
+         class NumberUnsignedType = std::uint64_t,
+         class NumberFloatType = double,
+         template<typename U> class AllocatorType = std::allocator,
+         template<typename T, typename SFINAE = void> class JSONSerializer =
+         adl_serializer,
+         class BinaryType = std::vector<std::uint8_t>>
+class basic_json;
+
+/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
+/// @sa https://json.nlohmann.me/api/json_pointer/
+template<typename RefStringType>
+class json_pointer;
+
+/*!
+@brief default specialization
+@sa https://json.nlohmann.me/api/json/
+*/
+using json = basic_json<>;
+
+/// @brief a minimal map-like container that preserves insertion order
+/// @sa https://json.nlohmann.me/api/ordered_map/
+template<class Key, class T, class IgnoredLess, class Allocator>
+struct ordered_map;
+
+/// @brief specialization that maintains the insertion order of object keys
+/// @sa https://json.nlohmann.me/api/ordered_json/
+using ordered_json = basic_json<nlohmann::ordered_map>;
+
+NLOHMANN_JSON_NAMESPACE_END
+
+#endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/test/CMakeLists.txt b/3rd-party/nlohmann_json_cmake_fetchcontent/test/CMakeLists.txt
new file mode 100644
index 0000000..0897869
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/test/CMakeLists.txt
@@ -0,0 +1 @@
+message(FATAL_ERROR "The JSON_CI option is not availablewhen using the nlohmann_json_cmake_fetchcontent repository.")
\ No newline at end of file
diff --git a/3rd-party/nlohmann_json_cmake_fetchcontent/update.py b/3rd-party/nlohmann_json_cmake_fetchcontent/update.py
new file mode 100755
index 0000000..23ca1f6
--- /dev/null
+++ b/3rd-party/nlohmann_json_cmake_fetchcontent/update.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+
+import sys, os
+import json
+import subprocess
+import urllib.request
+import hashlib
+
+# Go to the directory this script is stored in
+os.chdir(os.path.dirname(os.path.realpath(__file__)))
+
+# Download release data
+releases = json.loads(str(urllib.request.urlopen('https://api.github.com/repos/nlohmann/json/releases').read(), 'utf-8'))
+
+# Fetch all releases and the corresponding URL
+release_url_map = []
+for release in releases:
+  for asset in release['assets']:
+    if asset['name'] == 'json.hpp':
+      release_url_map.append((release['tag_name'], asset['browser_download_url'], release['body']))
+
+# List all git tags
+process = subprocess.Popen(['git', 'tag'], stdout=subprocess.PIPE)
+tags, _ = process.communicate()
+tags = set(filter(None, str(tags, 'utf-8').split("\n")))
+print("Releases already contained in this repository are " + str(tags))
+
+# Go over the release_url_map in reverse order; if a release is not yet a Git
+# tag, download the file, commit and add a tag
+for tag, url, body in release_url_map[::-1]:
+  if tag in tags:
+    continue
+
+  print("Downloading release " + tag)
+  if tag >= "v3.10.5":
+      os.system("rm -rf ./tmp")
+      os.system("rm -rf ./include")
+      os.system("git clone https://github.com/nlohmann/json ./tmp --depth 1 --branch {}".format(tag));
+      os.system("cp -rf ./tmp/single_include .")
+      os.system("cp -rf ./tmp/include/nlohmann/json_fwd.hpp ./single_include/nlohmann/")
+      os.system("cp -rf ./tmp/cmake .")
+      os.system("cp -rf ./tmp/CMakeLists.txt .")
+      os.system("cp -rf ./tmp/meson.build .")
+      os.system("cp -rf ./tmp/LICENSE.MIT .")
+      os.system("rm -rf ./tmp")
+      os.makedirs('./cmake', mode=0o777, exist_ok=True)
+      os.makedirs('./test', mode=0o777, exist_ok=True)
+      with open("./cmake/ci.cmake", "w") as f:
+        f .write("message(FATAL_ERROR \"The JSON_CI option is not available" \
+                 "when using the nlohmann_json_cmake_fetchcontent repository.\")")
+      with open("./test/CMakeLists.txt", "w") as f:
+        f.write("message(FATAL_ERROR \"The JSON_CI option is not available" \
+                "when using the nlohmann_json_cmake_fetchcontent repository.\")")
+      os.system("git add .")
+  else:
+      os.makedirs('./include', mode=0o777, exist_ok=True)
+      os.makedirs('./include/nlohmann', mode=0o777, exist_ok=True)
+      data = urllib.request.urlopen(url).read();
+      with open('./include/nlohmann/json.hpp', 'wb') as f:
+        f.write(data)
+
+      # Try to download the json_fwd.hpp header -- only exists since release
+      # v3.1.0
+      has_json_fwd = False
+      try:
+        json_fwd_url = 'https://github.com/nlohmann/json/raw/{}/include/nlohmann/json_fwd.hpp'.format(tag);
+        print("Trying to download " + json_fwd_url)
+        data = urllib.request.urlopen(json_fwd_url).read();
+        with open('./include/nlohmann/json_fwd.hpp', 'wb') as f:
+          f.write(data)
+        has_json_fwd = True
+      except:
+        pass
+
+      subprocess.call(['git', 'add', './include/nlohmann/json.hpp'])
+      if has_json_fwd:
+        subprocess.call(['git', 'add', './include/nlohmann/json_fwd.hpp'])
+  # Update the nlohman json options.
+  subprocess.call([ 'sed', '-i', '-e', 's/library.\" ON/library.\" OFF/g', './CMakeLists.txt'])
+  subprocess.call(['git', 'add', './CMakeLists.txt'])
+
+  # Update the README.md:
+  subprocess.call([ 'sed', '-i', '-e', 's/GIT_TAG .*)/GIT_TAG '+ tag + ')/g', './README.md'])
+  subprocess.call(['git', 'add', './README.md'])
+
+  # Commit:
+  subprocess.call(['git', 'commit', '-m', 'Upstream release ' + tag])
+  subprocess.call(['git', 'tag', '-a', tag, '-m', body])
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..836a7e0
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,96 @@
+# Do not change these options in this file. Use cmake.config, cmake -DOPTION=VALUE, or ccmake to specify them.
+option(BUILD_TEST "Build tests" OFF)
+
+cmake_minimum_required(VERSION 3.17)
+
+include(CMakeDependentOption)
+project(InfiniTensor C CXX)
+
+cmake_dependent_option(BUILD_TEST_CORE "Build tests for core components" ON BUILD_TEST OFF)
+
+set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
+# Build Type
+if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+    message("Configuring for Debug build.")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0")
+    add_compile_definitions(DEBUG_MODE)
+elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
+    message("Configuring for Release build.")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
+    add_compile_definitions(NDEBUG)
+elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
+    message("Configuring for RelWithDebInfo build.")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2")
+else()
+    message("Build type not specified. Configuring for RelWithDebInfo build.")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2")
+endif()
+
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_EXTENSIONS OFF) # -std=gnu++11 when on, -std=c++11 when off
+add_compile_options(-Wno-error=unused-variable)
+
+find_package(
+  Python
+  COMPONENTS Interpreter Development
+  REQUIRED)
+
+# OpenMP
+find_package(OpenMP)
+if(OpenMP_C_FOUND)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+endif()
+if(OpenMP_CXX_FOUND)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+endif()
+
+include_directories(include)
+
+if(BUILD_TEST)
+  set(BUILD_GMOCK
+      OFF
+      CACHE BOOL "Do not build gmock" FORCE)
+  set(INSTALL_GTEST
+      OFF
+      CACHE BOOL "Do not install gtest" FORCE)
+  add_subdirectory(3rd-party/googletest)
+  include_directories(3rd-party/googletest/googletest/include)
+endif()
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Werror -Wno-error=deprecated-declarations -Wno-error=pointer-arith")
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG") # Enable assertion
+set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -UNDEBUG") # Enable assertion
+
+
+# Source files
+file(GLOB_RECURSE SRC src/core/*.cc src/kernels/cpu/*.cc src/operators/*.cc src/utils/*.cc)
+
+if(USE_INTELCPU)
+  file(GLOB_RECURSE SRC_INTELCPU src/intelcpu/*.cc src/kernels/intelcpu/*.cc )
+  list (APPEND SRC ${SRC_INTELCPU})
+endif()
+
+# Libraries
+add_library(InfiniTensor SHARED ${SRC})
+
+function(build_test files)
+  # Non-recursive glob for skip failed tests
+  file(GLOB TEST_SOURCES ${files})
+  foreach(testsourcefile ${TEST_SOURCES})
+    get_filename_component(testname ${testsourcefile} NAME_WE)
+    add_executable(${testname} ${testsourcefile})
+    target_link_libraries(${testname} InfiniTensor GTest::gtest_main)
+    add_test(NAME ${testname} COMMAND ${testname})
+  endforeach(testsourcefile ${TEST_SOURCES})
+endfunction()
+
+if(BUILD_TEST)
+  add_compile_definitions(BUILD_TEST=1)
+  enable_testing()
+  if(BUILD_TEST_CORE)
+    build_test(test/core/*.cc)
+    build_test(test/operators/*.cc)
+    build_test(test/kernels/nativecpu/*.cc)
+  endif()
+endif()
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..35ef7ef
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+.PHONY : build clean format install-python test-cpp test-onnx
+
+TYPE ?= Release
+TEST ?= ON
+
+CMAKE_OPT = -DCMAKE_BUILD_TYPE=$(TYPE)
+CMAKE_OPT += -DBUILD_TEST=$(TEST)
+
+build:
+	mkdir -p build/$(TYPE)
+	cd build/$(TYPE) && cmake $(CMAKE_OPT) ../.. && make -j8
+
+clean:
+	rm -rf build
+
+test-cpp:
+	@echo
+	cd build/$(TYPE) && make test
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7bbac1c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# TinyInfiniTensor
+
+一个简化版的 ai compiler,用于初学者快速上手学习,保留了计算图和 kernel 层的概念,能够基于 c++ 搭建计算图进行推理计算,目前只支持 cpu 平台。
+
+[环境部署文档](docs/项目部署.md)
+
+[训练营作业介绍文档](docs/训练营作业介绍.md)
\ No newline at end of file
diff --git "a/docs/\350\256\255\347\273\203\350\220\245\344\275\234\344\270\232\344\273\213\347\273\215.md" "b/docs/\350\256\255\347\273\203\350\220\245\344\275\234\344\270\232\344\273\213\347\273\215.md"
new file mode 100644
index 0000000..c767b53
--- /dev/null
+++ "b/docs/\350\256\255\347\273\203\350\220\245\344\275\234\344\270\232\344\273\213\347\273\215.md"
@@ -0,0 +1,186 @@
+# 本地自测
+
+运行 ``make test-cpp``,通过所有测例即为完成作业,每个测例 10 分。
+
+1. test_allocator:依赖作业一
+2. test_cast:依赖作业四
+3. test_clip:依赖作业三
+4. test_concat:依赖作业五
+5. test_element_wise:依赖作业六
+6. test_transpose:依赖作业二
+7. test_nativecpu_concat:依赖作业一、作业五
+8. test_nativecpu_elementwise:依赖作业一、作业六
+9. test_nativecpu_transpose:依赖作业一、作业二
+
+# 作业题目
+
+## 作业一:内存分配器
+
+难度:⭐⭐⭐⭐
+
+对应测例:``test_allocator``,``test_nativecpu_concat``,``test_nativecpu_elementwise``,``test_nativecpu_transpose``
+
+### step1 完善 allocator 声明
+
+需要实现的代码块位置:`include/core/allocator.h`
+
+````c++
+// =================================== 作业 ===================================
+// TODO:可能需要设计一个数据结构来存储free block,以便于管理和合并
+// HINT: 可以使用一个 map 来存储 free block,key 为 block 的起始/结尾地址,value 为 block 的大小
+// =================================== 作业 ===================================
+````
+
+### step2 完善 allocator 定义
+
+需要实现的代码块位置:`src/core/allocator.cc`
+
+完善分配函数:
+
+````c++
+    size_t Allocator::alloc(size_t size)
+    {
+        IT_ASSERT(this->ptr == nullptr);
+        // pad the size to the multiple of alignment
+        size = this->getAlignedSize(size);
+
+        // =================================== 作业 ===================================
+        // TODO: 设计一个算法来分配内存,返回起始地址偏移量
+        // =================================== 作业 ===================================
+
+        return 0;
+    }
+````
+
+完善释放函数:
+
+````c++
+    void Allocator::free(size_t addr, size_t size)
+    {
+        IT_ASSERT(this->ptr == nullptr);
+        size = getAlignedSize(size);
+
+        // =================================== 作业 ===================================
+        // TODO: 设计一个算法来回收内存
+        // =================================== 作业 ===================================
+    }
+````
+
+## 作业二:transpose 算子形状推导
+
+难度:⭐
+
+对应测例:``test_transpose``,``test_nativecpu_transpose``
+
+需要实现的代码块位置:`src/operators/transpose.cc`
+
+````c++
+    optional<vector<Shape>> TransposeObj::inferShape(const TensorVec &inputs)
+    {
+        const auto A = inputs[0];
+        auto input_dim = A->getDims();
+        auto output_dim = input_dim;
+        int rank = A->getRank();
+
+        // =================================== 作业 ===================================
+        // TODO:修改 output_dim,返回正确的 transpose 后的 shape
+        // REF: https://onnx.ai/onnx/operators/onnx__Transpose.html#transpose-21
+        // =================================== 作业 ===================================
+
+        return {{}};
+    }
+
+````
+
+## 作业三:clip 算子形状推导
+
+难度:⭐
+
+对应测例:``test_clip``
+
+需要实现的代码块位置:`src/operators/unary.cc`
+
+````c++
+    optional<vector<Shape>> ClipObj::inferShape(const TensorVec &inputs)
+    {
+        // =================================== 作业 ===================================
+        // TODO:返回经过 clip 操作后的 shape
+        // REF: https://onnx.ai/onnx/operators/onnx__Clip.html#clip-13
+        // =================================== 作业 ===================================
+        return {{}};
+    }
+````
+
+## 作业四:cast 算子形状推导 & 数据类型推导
+
+难度:⭐⭐
+
+对应测例:``test_cast``
+
+需要实现的代码块位置:`src/operators/unary.cc`
+
+````c++
+    vector<DataType> CastObj::inferDataType(const TensorVec &inputs) const
+    {
+        // =================================== 作业 ===================================
+        // TODO:返回经过 cast 操作后, 输出 tensor 的数目和数据类型
+        // REF_FILE: src/core/operator.cc
+        // REF: https://onnx.ai/onnx/operators/onnx__Cast.html#cast-21
+        // =================================== 作业 ===================================
+        return {};
+    }
+
+    optional<vector<Shape>> CastObj::inferShape(const TensorVec &inputs)
+    {
+        // =================================== 作业 ===================================
+        // TODO:返回经过 cast 操作后的 shape
+        // REF: https://onnx.ai/onnx/operators/onnx__Cast.html#cast-21
+        // =================================== 作业 ===================================
+        return {{}};
+    }
+````
+
+
+
+## 作业五:concat 算子形状推导
+
+难度:⭐⭐
+
+对应测例:``test_concat``,``test_nativecpu_concat``
+
+需要实现的代码块位置:`src/operators/concat.cc`
+
+````c++
+optional<vector<Shape>> ConcatObj::inferShape(const TensorVec &inputs) {
+    Shape dims = inputs[0]->getDims();
+    auto rank = inputs[0]->getRank();
+
+    // =================================== 作业 ===================================
+    // TODO:修改 dims,返回正确的 concat 后的 shape
+    // REF: https://onnx.ai/onnx/operators/onnx__Concat.html#concat-13
+    // =================================== 作业 ===================================
+
+    return {{dims}};
+}
+````
+
+## 作业六:双向广播
+
+难度:⭐⭐⭐
+
+对应测例:``test_element_wise``,``test_nativecpu_elementwise``
+
+需要实现的代码块位置:`src/utils/operator_utils.cc`
+
+````c++
+Shape infer_broadcast(const Shape &A, const Shape &B) {
+
+    // =================================== 作业 ===================================
+    // TODO:对 A 和 B 进行双向广播,返回广播后的形状。
+    // REF: https://github.com/onnx/onnx/blob/main/docs/Broadcasting.md
+    // =================================== 作业 ===================================
+    
+    return {};
+}
+````
+
diff --git "a/docs/\351\241\271\347\233\256\351\203\250\347\275\262.md" "b/docs/\351\241\271\347\233\256\351\203\250\347\275\262.md"
new file mode 100644
index 0000000..5690349
--- /dev/null
+++ "b/docs/\351\241\271\347\233\256\351\203\250\347\275\262.md"
@@ -0,0 +1,35 @@
+### 环境准备
+建议使用Linux系统或Mac系统,windows下使用WSL,配置方法和Linux一致。
+
+1. 安装gcc、g++,请确认版本为 11.3 及以上的稳定版本
+``` bash
+# linux 使用apt安装
+sudo apt install gcc g++
+
+# mac 使用Homebrew安装
+brew install gcc
+```
+
+2. 安装CMake,请确认版本为 3.17 及以上的稳定版本
+``` bash
+# linux 使用apt安装
+sudo apt install cmake
+
+# mac 使用Homebrew安装
+brew install cmake
+```
+
+2. 安装make
+``` bash
+# linux 使用apt安装
+sudo apt install make
+
+# mac 使用Homebrew安装
+brew install make
+```
+
+### 构建命令
+配置好上述环境后,进入项目目录后可以通过以下命令进行构建。
+- `make`/`make build`: 构建整个项目;
+- `make test-cpp`: 构建项目后执行测例;
+- `make clean`:清理生成文件
\ No newline at end of file
diff --git a/include/core/allocator.h b/include/core/allocator.h
new file mode 100644
index 0000000..002601d
--- /dev/null
+++ b/include/core/allocator.h
@@ -0,0 +1,59 @@
+#pragma once
+#include "core/runtime.h"
+#include "core/tensor.h"
+#ifdef BUILD_TEST
+#include "gtest/gtest.h"
+#endif
+#include <cstddef>
+#include <map>
+#include <unordered_set>
+
+namespace infini {
+  class Allocator
+  {
+  private:
+    Runtime runtime;
+
+    size_t used;
+
+    size_t peak;
+
+    size_t alignment;
+
+    // pointer to the memory actually allocated
+    void *ptr;
+
+    // =================================== 作业 ===================================
+    // TODO:可能需要设计一个数据结构来存储free block,以便于管理和合并
+    // HINT: 可以使用一个 map 来存储 free block,key 为 block 的起始/结尾地址,value 为 block 的大小
+    // =================================== 作业 ===================================
+
+  public:
+    Allocator(Runtime runtime);
+
+    virtual ~Allocator();
+
+    // function: simulate memory allocation
+    // arguments:
+    //     size: size of memory block to be allocated
+    // return: head address offset of the allocated memory block
+    size_t alloc(size_t size);
+
+    // function: simulate memory free
+    // arguments:
+    //     addr: head address offset of memory block to be free
+    //     size: size of memory block to be freed
+    void free(size_t addr, size_t size);
+
+    // function: perform actual memory allocation
+    // return: pointer to the head address of the allocated memory
+    void *getPtr();
+
+    void info();
+
+  private:
+    // function: memory alignment, rouned up
+    // return: size of the aligned memory block
+    size_t getAlignedSize(size_t size);
+  };
+}
diff --git a/include/core/blob.h b/include/core/blob.h
new file mode 100644
index 0000000..01684f6
--- /dev/null
+++ b/include/core/blob.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "core/common.h"
+#include "core/ref.h"
+
+namespace infini {
+
+class RuntimeObj;
+using Runtime = Ref<RuntimeObj>;
+
+class BlobObj
+{
+  Runtime runtime;
+  void *ptr;
+
+public:
+  BlobObj(Runtime runtime, void *ptr) : runtime(runtime), ptr(ptr) {}
+  BlobObj(BlobObj &other) = delete;
+  BlobObj &operator=(BlobObj const &) = delete;
+  ~BlobObj() {};
+
+  template <typename T>
+  T getPtr() const { return reinterpret_cast<T>(ptr); }
+};
+
+} // namespace infini
diff --git a/include/core/common.h b/include/core/common.h
new file mode 100644
index 0000000..e4fd65b
--- /dev/null
+++ b/include/core/common.h
@@ -0,0 +1,85 @@
+#pragma once
+#include "utils/exception.h"
+#include <cassert>
+#include <functional>
+#include <iostream>
+#include <list>
+#include <map>
+#include <optional>
+#include <set>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <unordered_set>
+#include <variant>
+#include <vector>
+
+namespace infini {
+using std::list;
+using std::map;
+using std::optional;
+using std::pair;
+using std::set;
+using std::string;
+using std::tie;
+using std::to_string;
+using std::tuple;
+using std::unordered_map;
+using std::vector;
+
+// Metaprogramming utilities
+#define _CAT(A, B) A##B
+#define _SELECT(NAME, NUM) _CAT(NAME##_, NUM)
+#define _GET_COUNT(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, COUNT, ...) COUNT
+#define _VA_SIZE(...) _GET_COUNT(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
+#define _VA_SELECT(NAME, ...) _SELECT(NAME, _VA_SIZE(__VA_ARGS__))(__VA_ARGS__)
+
+// Assert: conditions should have no side effect
+#define _IT_ASSERT_2(condition, info)                                          \
+    static_cast<bool>(condition)                                               \
+        ? void(0)                                                              \
+        : throw ::infini::Exception(                                           \
+              std::string("[") + __FILE__ + ":" + std::to_string(__LINE__) +   \
+              "] Assertion failed (" + #condition + "): " + info)
+#define _IT_ASSERT_1(condition) _IT_ASSERT_2(condition, "")
+#define IT_ASSERT(...) _VA_SELECT(_IT_ASSERT, __VA_ARGS__)
+
+#define IT_TODO_HALT() _IT_ASSERT_2(false, "Unimplemented")
+#define IT_TODO_HALT_MSG(msg) _IT_ASSERT_2(false, msg)
+#define IT_ASSERT_TODO(condition) _IT_ASSERT_2(condition, "Unimplemented")
+#define IT_TODO_SKIP() puts("Unimplemented " __FILE__ ":" __LINE__)
+
+// std::to_underlying is avaiable since C++23
+template <typename T> auto enum_to_underlying(T e) {
+    return static_cast<std::underlying_type_t<T>>(e);
+}
+
+template <typename T> std::string vecToString(const std::vector<T> &vec) {
+    std::stringstream ss;
+    ss << "[";
+    for (size_t i = 0; i < vec.size(); ++i) {
+        ss << vec.at(i);
+        if (i < vec.size() - 1) {
+            ss << ",";
+        }
+    }
+    ss << "]";
+    return ss.str();
+}
+
+template <typename T> std::string vecToString(const T *st, size_t length) {
+    std::stringstream ss;
+    ss << "[";
+    size_t i = 0;
+    for (i = 0; i < length; i++) {
+        ss << *(st + i);
+        if (i < length - 1) {
+            ss << ",";
+        }
+    }
+    ss << "]";
+    return ss.str();
+}
+
+} // namespace infini
diff --git a/include/core/constants.h b/include/core/constants.h
new file mode 100644
index 0000000..bf74f47
--- /dev/null
+++ b/include/core/constants.h
@@ -0,0 +1,5 @@
+#pragma once
+
+namespace infini {
+constexpr double E_CONSTANT = 2.718281828459;
+}
diff --git a/include/core/data_type.h b/include/core/data_type.h
new file mode 100644
index 0000000..0b7c1fa
--- /dev/null
+++ b/include/core/data_type.h
@@ -0,0 +1,103 @@
+#pragma once
+#include "core/common.h"
+
+namespace infini {
+
+class DataType {
+  public:
+    // <https://onnx.ai/onnx/intro/concepts.html#element-type>
+    static const DataType Undefine;
+    static const DataType Float32;
+    static const DataType UInt8;
+    static const DataType Int8;
+    static const DataType UInt16;
+    static const DataType Int16;
+    static const DataType Int32;
+    static const DataType Int64;
+    static const DataType String;
+    static const DataType Bool;
+    static const DataType Float16;
+    static const DataType Double;
+    static const DataType UInt32;
+    static const DataType UInt64;
+    static const DataType BFloat16;
+    // "sizePerElement" show the DType to cpu_type
+    // DataType::Bool -> int8_t   DataType::Float16 -> uint16_t
+    static constexpr size_t sizePerElement[]{0,
+                                             sizeof(float),
+                                             sizeof(uint8_t),
+                                             sizeof(int8_t),
+                                             sizeof(uint16_t),
+                                             sizeof(int16_t),
+                                             sizeof(int32_t),
+                                             sizeof(int64_t),
+                                             sizeof(std::string),
+                                             sizeof(int8_t),
+                                             sizeof(uint16_t),
+                                             sizeof(double),
+                                             sizeof(uint32_t),
+                                             sizeof(uint64_t),
+                                             0,
+                                             0,
+                                             sizeof(uint16_t)};
+
+    static constexpr std::string_view names[]{
+        "Undefine",    "Float32", "UInt8",  "Int8",   "UInt16",
+        "Int16",       "Int32",   "Int64",  "String", "Bool",
+        "Float16",     "Double",  "UInt32", "UInt64", "PlaceHolder",
+        "PlaceHolder", "BFloat16"};
+
+    static constexpr int cpuType[]{-1, 0, 2, 3, 4, 5,  6,  7, -1,
+                                   3,  4, 9, 1, 8, -1, -1, 4};
+
+  private:
+    int index;
+
+  public:
+    // FIXME: default ctor should be deleted but json requires it. Solution:
+    // https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
+    DataType() = default;
+    constexpr DataType(int index) : index(index) {}
+    bool operator==(const DataType &rhs) const { return index == rhs.index; }
+    bool operator<(const DataType &rhs) const { return index < rhs.index; }
+
+    template <typename T> static int get() {
+        IT_TODO_HALT_MSG("Unsupported data type");
+    }
+    size_t getSize() const { return sizePerElement[index]; }
+    string toString() const { return string(names[index]); }
+    int cpuTypeInt() const { return cpuType[index]; }
+    int getIndex() const { return index; }
+};
+
+// Method definitions are out of the declaration due to GCC bug:
+// https://stackoverflow.com/questions/49707184/explicit-specialization-in-non-namespace-scope-does-not-compile-in-gcc
+template <> inline int DataType::get<float>() { return 0; }
+template <> inline int DataType::get<uint32_t>() { return 1; }
+template <> inline int DataType::get<uint8_t>() { return 2; }
+template <> inline int DataType::get<int8_t>() { return 3; }
+template <> inline int DataType::get<uint16_t>() { return 4; }
+template <> inline int DataType::get<int16_t>() { return 5; }
+template <> inline int DataType::get<int32_t>() { return 6; }
+template <> inline int DataType::get<int64_t>() { return 7; }
+template <> inline int DataType::get<uint64_t>() { return 8; }
+template <> inline int DataType::get<double>() { return 9; }
+
+template <int index> struct DT {};
+template <> struct DT<0> { using t = bool; };
+template <> struct DT<1> { using t = float; };
+template <> struct DT<2> { using t = uint8_t; };
+template <> struct DT<3> { using t = int8_t; };
+template <> struct DT<4> { using t = uint16_t; };
+template <> struct DT<5> { using t = int16_t; };
+template <> struct DT<6> { using t = int32_t; };
+template <> struct DT<7> { using t = int64_t; };
+template <> struct DT<8> { using t = char; };
+template <> struct DT<9> { using t = int8_t; };
+template <> struct DT<10> { using t = uint16_t; };
+template <> struct DT<11> { using t = double; };
+template <> struct DT<12> { using t = uint32_t; };
+template <> struct DT<13> { using t = uint64_t; };
+template <> struct DT<16> { using t = uint16_t; };
+
+} // namespace infini
diff --git a/include/core/graph.h b/include/core/graph.h
new file mode 100644
index 0000000..49101a5
--- /dev/null
+++ b/include/core/graph.h
@@ -0,0 +1,130 @@
+#pragma once
+#include "core/allocator.h"
+#include "core/operator.h"
+#include "core/tensor.h"
+
+namespace infini
+{
+
+    class GraphObj : public Object
+    {
+    protected:
+        Runtime runtime;
+        TensorVec tensors;
+        OpVec ops;
+        Allocator allocator;
+
+    public:
+        explicit GraphObj(Runtime runtime)
+            : runtime(runtime), allocator(runtime), sorted(false){};
+        string toString() const override;
+        Runtime getRuntime() const { return runtime; }
+
+        Tensor addTensor(Shape dim, DataType dtype = DataType::Float32);
+        Tensor addTensor(const Tensor &tensor);
+        TensorVec addTensor(const TensorVec &tensors);
+        void removeOperator(Operator op)
+        {
+            auto it = std::find(ops.begin(), ops.end(), op);
+            if (it != ops.end())
+                ops.erase(it);
+        }
+
+        void removeTensor(Tensor tensor)
+        {
+            auto it = std::find(tensors.begin(), tensors.end(), tensor);
+            if (it != tensors.end())
+                tensors.erase(it);
+        }
+
+        void deleteConnection(Tensor tensor, Operator op);
+        void addConnection(Tensor tensor, Operator op);
+        void replaceConnection(Tensor oldInput, Tensor newInput, Operator op);
+
+        Operator cloneOperator(Operator op, TensorVec inputs, TensorVec outputs)
+        {
+            auto opClone = op->clone(inputs, outputs);
+            addOperatorAndConnect(opClone);
+            return opClone;
+        }
+
+        const TensorVec &getTensors() const { return tensors; }
+        const OpVec &getOperators() const { return ops; }
+        Tensor getTensor(int) const;
+
+        /**
+         * @brief Sort the nodes in topological order.
+         * It returns true if the sorting is successful.
+         * Otherwise false is returned, means that there are rings in the graph,
+         * so the topological sorting fails.
+         */
+        bool topo_sort();
+
+        void optimize();
+
+        void shape_infer();
+
+        void dataMalloc();
+
+        /**
+         * @brief Add an operator and create its outputs. Output tensor arguments
+         * should be empty Refs (e.g., nullptr).
+         */
+        template <typename T, typename... Args>
+        Ref<T> addOp(Args &&...args)
+        {
+            Ref<T> op = infini::make_ref<T>(this, std::forward<Args>(args)...);
+            addOperatorAndConnect(op);
+            return op;
+        }
+
+        /**
+         * @brief Add an operator with its outputs specified.
+         */
+        template <typename T, typename... Args>
+        Ref<T> addOpWithOutputs(Args &&...args)
+        {
+            Ref<T> op = infini::make_ref<T>(nullptr, std::forward<Args>(args)...);
+            addOperatorAndConnect(op);
+            return op;
+        }
+
+        /**
+         * @brief Gets input tensors of this graph.
+         */
+        inline TensorVec getInputs() const
+        {
+            TensorVec ret;
+            for (const auto &t : tensors)
+                if (!t->getSource())
+                    ret.emplace_back(t);
+            return ret;
+        }
+
+        /**
+         * @brief Gets output tensors of this graph.
+         */
+        inline TensorVec getOutputs() const
+        {
+            TensorVec ret;
+            for (const auto &t : tensors)
+                if (t->getTargets().empty())
+                    ret.emplace_back(t);
+            return ret;
+        }
+
+        bool checkValid() const;
+
+    private:
+        /**
+         * @brief Add reverse connections and Op relationship in ctor.
+         */
+        void addOperatorAndConnect(const Operator &op);
+
+        /**
+         * @brief If the nodes is sorted in topological order.
+         */
+        bool sorted;
+    };
+
+} // namespace infini
\ No newline at end of file
diff --git a/include/core/kernel.h b/include/core/kernel.h
new file mode 100644
index 0000000..a762424
--- /dev/null
+++ b/include/core/kernel.h
@@ -0,0 +1,87 @@
+#pragma once
+#include "core/common.h"
+#include "core/operator.h"
+#include "core/tensor.h"
+#include "utils/operator_utils.h"
+#include <functional>
+
+namespace infini
+{
+
+    class RuntimeObj;
+
+    class Kernel
+    {
+    public:
+        Kernel() {}
+        virtual ~Kernel() {}
+
+        /**
+         * @brief Executes an op with a default parameter.
+         */
+        virtual void compute(const Operator &op,
+                             const RuntimeObj *context) const = 0;
+    };
+
+    class KernelRegistry
+    {
+    public:
+        using KernelRecord =
+            tuple<Kernel *const, const string, const int>; // Kernel, name, ID
+
+    private:
+        std::map<KernelAttrs, KernelRecord> kernels;
+        int nKernels = 0;
+
+    public:
+        ~KernelRegistry()
+        {
+            for (auto &[k, v] : kernels)
+                delete std::get<0>(v);
+        }
+        static KernelRegistry &getInstance()
+        {
+            static KernelRegistry instance;
+            return instance;
+        }
+        bool registerKernel(const KernelAttrs &key, Kernel *kernel, string name)
+        {
+            IT_ASSERT(kernels.find(key) == kernels.end(),
+                      "Kernel already registered");
+            kernels.emplace(key, KernelRecord{kernel, name, ++nKernels});
+            return true;
+        }
+        Kernel *getKernel(const KernelAttrs &kernelAttrs) const
+        {
+            auto it = kernels.find(kernelAttrs);
+            IT_ASSERT(it != kernels.end(), "Kernel not found for key {" +
+                                               get_kernel_attrs_str(kernelAttrs) +
+                                               "}");
+            return std::get<0>(it->second);
+        }
+        const KernelRecord &getKernelItem(const KernelAttrs &kernelAttrs) const
+        {
+            return kernels.at(kernelAttrs);
+        }
+    };
+
+    class CpuKernelWithoutConfig : public Kernel
+    {
+    public:
+        virtual void compute(const Operator &op,
+                             const RuntimeObj *context) const = 0;
+    };
+
+} // namespace infini
+
+#define _REGISTER_KERNEL_1(device, opType, kernel, name, cnt)                 \
+    namespace infini                                                          \
+    {                                                                         \
+        static const bool _CAT(_register_kernel_, cnt) =                      \
+            KernelRegistry::getInstance().registerKernel(KernelAttrs{device,  \
+                                                                     opType}, \
+                                                         new kernel(), name); \
+    }
+
+#define REGISTER_KERNEL(device, opType, kernel, name) \
+    _REGISTER_KERNEL_1(device, opType, kernel, name, __COUNTER__)
diff --git a/include/core/object.h b/include/core/object.h
new file mode 100644
index 0000000..2db50ad
--- /dev/null
+++ b/include/core/object.h
@@ -0,0 +1,71 @@
+#pragma once
+#include "core/common.h"
+#include "ref.h"
+
+namespace infini {
+
+using UidBaseType = int;
+
+class Uid {
+  private:
+    UidBaseType uid;
+
+  public:
+    Uid(UidBaseType uid) : uid(uid) {}
+    Uid &operator=(const Uid &rhs) = delete;
+
+    operator UidBaseType() const { return uid; }
+};
+
+class Guid : public Uid {
+  private:
+    UidBaseType generateGuid() {
+        static UidBaseType guidCnt = 0;
+        return ++guidCnt;
+    }
+
+  public:
+    Guid() : Uid(generateGuid()) {}
+    Guid(const Guid &rhs) : Uid(generateGuid()) {}
+};
+
+/**
+ * @brief Family unique ID. Cloned tensors shared the same FUID.
+ */
+class Fuid : public Uid {
+  private:
+    UidBaseType generateFuid() {
+        static UidBaseType fuidCnt = 0;
+        return ++fuidCnt;
+    }
+
+  public:
+    Fuid() : Uid(generateFuid()) {}
+    Fuid(const Fuid &fuid) : Uid(fuid) {}
+};
+
+class Object {
+  protected:
+    Guid guid;
+
+  public:
+    virtual ~Object(){};
+    virtual string toString() const = 0;
+    void print() { std::cout << toString() << std::endl; }
+    UidBaseType getGuid() const { return guid; }
+};
+
+inline std::ostream &operator<<(std::ostream &os, const Object &obj) {
+    os << obj.toString();
+    return os;
+}
+
+// Overload for Ref-wrapped Object
+template <typename T,
+          typename std::enable_if_t<std::is_base_of_v<Object, T>> * = nullptr>
+inline std::ostream &operator<<(std::ostream &os, const Ref<T> &obj) {
+    os << obj->toString();
+    return os;
+}
+
+} // namespace infini
diff --git a/include/core/op_type.h b/include/core/op_type.h
new file mode 100644
index 0000000..c084ae5
--- /dev/null
+++ b/include/core/op_type.h
@@ -0,0 +1,41 @@
+#pragma once
+#ifndef OP_TYPE_H
+#define OP_TYPE_H
+
+#include <string>
+#include <unordered_set>
+
+namespace infini
+{
+    struct OpType
+    {
+        using underlying_t = uint16_t;
+        enum : underlying_t
+        {
+            Unknown,
+            Add,
+            Cast,
+            Clip,
+            Concat,
+            Div,
+            Mul,
+            Relu,
+            Sub,
+            Transpose,
+
+        } type;
+
+        constexpr OpType(decltype(type) t) : type(t) {}
+        constexpr explicit OpType(underlying_t val) : type((decltype(type))val) {}
+        constexpr underlying_t underlying() const { return type; }
+
+        bool operator==(OpType others) const { return type == others.type; }
+        bool operator!=(OpType others) const { return type != others.type; }
+        bool operator<(OpType others) const { return type < others.type; }
+
+        const char *toString() const;
+    };
+
+} // namespace infini
+
+#endif // OP_TYPE_H
diff --git a/include/core/operator.h b/include/core/operator.h
new file mode 100644
index 0000000..96a030b
--- /dev/null
+++ b/include/core/operator.h
@@ -0,0 +1,88 @@
+#pragma once
+
+#include "core/op_type.h"
+#include "core/tensor.h"
+
+namespace infini {
+using KernelAttrs = std::tuple<Device, OpType::underlying_t>;
+
+class GraphObj;
+class OperatorObj : public Object {
+    friend class GraphObj;
+
+  protected:
+    OpType type;
+    TensorVec inputs;
+    TensorVec outputs;
+    vector<WRef<OperatorObj>> predecessors;
+    vector<WRef<OperatorObj>> successors;
+
+  public:
+    OperatorObj(OpType opType, TensorVec inputs, TensorVec outputs);
+    virtual optional<vector<Shape>> inferShape(const TensorVec &inputs) = 0;
+    virtual vector<DataType> inferDataType(const TensorVec &inputs) const;
+    /**
+     * @brief Constructs outputs (if requried) and check whether the operator is
+     * valid.
+     *
+     * @param graph If graph is not nullptr, outputs should be created in this
+     * function.
+     */
+    bool checkValid(GraphObj *graph);
+
+public: // getter and setter
+    const TensorVec &getInputs() const { return inputs; }
+    const TensorVec &getOutputs() const { return outputs; }
+    Tensor getInputs(size_t i) const { return inputs.at(i); }
+    Tensor getOutput() const {
+        IT_ASSERT(outputs.size() == 1, "Unimplemented");
+        return outputs[0];
+    }
+    Tensor getOutput(size_t i) const {
+        IT_ASSERT(i < outputs.size(), "Index exceeded");
+        return outputs.at(i);
+    }
+    OpVec getPredecessors() const { return wrefs_to_refs(predecessors); }
+    OpVec getSuccessors() const { return wrefs_to_refs(successors); }
+    OpType getOpType() const { return type; }
+    // HACK: set correct data type
+    DataType getDType() const { return getInputs(0)->getDType(); }
+    DataType getOutDType() const { return getOutput()->getDType(); }
+    virtual int numInputs() const = 0;
+    virtual int numOutputs() const = 0;
+
+    /**
+     * @brief Clone this operator and replace its inputs and outputs.
+     *
+     * @param newInputs
+     * @param newOutputs
+     * @return Operator
+     */
+    virtual Operator clone(const TensorVec &newInputs,
+                           const TensorVec &newOutputs) const = 0;
+
+  protected:
+    optional<vector<Shape>> inferShape();
+    vector<DataType> inferDataType() const;
+
+private:
+    void addPredecessors(const Operator &op) { predecessors.emplace_back(op); }
+    void addSuccessors(const Operator &op) { successors.emplace_back(op); }
+    void removePredecessors(const Operator &op);
+    void removeSuccessors(const Operator &op);
+    void replaceInput(Tensor t1, Tensor t2);
+};
+
+#define OP_CLONE(OpObj)                                                        \
+    virtual Operator clone(const TensorVec &newInputs,                         \
+                           const TensorVec &newOutputs) const override {       \
+        auto op = infini::make_ref<OpObj>(*this);                              \
+        op->inputs = newInputs;                                                \
+        op->outputs = newOutputs;                                              \
+        op->predecessors.clear();                                              \
+        op->successors.clear();                                                \
+        IT_ASSERT(op->checkValid(nullptr));                                    \
+        return op;                                                             \
+    }
+
+} // namespace infini
diff --git a/include/core/ref.h b/include/core/ref.h
new file mode 100644
index 0000000..3393f6e
--- /dev/null
+++ b/include/core/ref.h
@@ -0,0 +1,43 @@
+#pragma once
+#include "core/common.h"
+#include <functional>
+#include <memory>
+#include <type_traits>
+
+namespace infini {
+
+template <typename T> using Ref = std::shared_ptr<T>;
+template <typename T> using WRef = std::weak_ptr<T>;
+
+template <typename T> struct is_ref : std::false_type {};
+template <typename T> struct is_ref<Ref<T>> : std::true_type {};
+template <typename T> struct is_ref<WRef<T>> : std::true_type {};
+
+template <typename T, typename... Params> Ref<T> make_ref(Params &&...params) {
+    static_assert(is_ref<T>::value == false, "Ref should not be nested");
+    return std::make_shared<T>(std::forward<Params>(params)...);
+}
+
+template <class T, class U,
+          typename std::enable_if_t<std::is_base_of_v<U, T>> * = nullptr>
+Ref<T> as(const Ref<U> &ref) {
+    return std::dynamic_pointer_cast<T>(ref);
+}
+
+template <typename T>
+std::vector<WRef<T>> refs_to_wrefs(const std::vector<Ref<T>> &refs) {
+    std::vector<WRef<T>> wrefs;
+    for (const auto &ref : refs)
+        wrefs.emplace_back(ref);
+    return wrefs;
+}
+
+template <typename T>
+std::vector<Ref<T>> wrefs_to_refs(const std::vector<WRef<T>> &wrefs) {
+    std::vector<Ref<T>> refs;
+    for (const auto &wref : wrefs)
+        refs.emplace_back(wref);
+    return refs;
+}
+
+} // namespace infini
diff --git a/include/core/runtime.h b/include/core/runtime.h
new file mode 100644
index 0000000..1b64cd9
--- /dev/null
+++ b/include/core/runtime.h
@@ -0,0 +1,69 @@
+#pragma once
+#include "core/common.h"
+#include "core/op_type.h"
+#include "core/ref.h"
+
+namespace infini
+{
+  class TensorObj;
+  class OperatorObj;
+  class GraphObj;
+  class RuntimeObj;
+  class BlobObj;
+
+  using Tensor = Ref<TensorObj>;
+  using Operator = Ref<OperatorObj>;
+  using Graph = Ref<GraphObj>;
+  using Runtime = Ref<RuntimeObj>;
+  using Blob = Ref<BlobObj>;
+
+  using TensorVec = vector<Tensor>;
+  using OpVec = vector<Operator>;
+
+  enum class Device
+  {
+    CPU = 1
+  };
+
+  class RuntimeObj : public std::enable_shared_from_this<RuntimeObj>
+  {
+  protected:
+    Device device;
+
+  public:
+    explicit RuntimeObj(Device device)
+        : device(device) {}
+    RuntimeObj(RuntimeObj &other) = delete;
+    RuntimeObj &operator=(RuntimeObj const &) = delete;
+    virtual ~RuntimeObj() {}
+
+    virtual void run(const Graph &graph) const = 0;
+    virtual void *alloc(size_t size) = 0;
+    virtual void dealloc(void *ptr) = 0;
+
+    bool isCpu() const
+    {
+      return true;
+    }
+
+    virtual string toString() const = 0;
+  };
+
+  class NativeCpuRuntimeObj : public RuntimeObj
+  {
+  public:
+    NativeCpuRuntimeObj() : RuntimeObj(Device::CPU) {}
+
+    static Ref<NativeCpuRuntimeObj> &getInstance()
+    {
+      static Ref<NativeCpuRuntimeObj> instance =
+          make_ref<NativeCpuRuntimeObj>();
+      return instance;
+    }
+    void dealloc(void *ptr) override;
+    void run(const Graph &graph) const override;
+    void *alloc(size_t size) override;
+    string toString() const override;
+  };
+
+} // namespace infini
diff --git a/include/core/tensor.h b/include/core/tensor.h
new file mode 100644
index 0000000..557bd41
--- /dev/null
+++ b/include/core/tensor.h
@@ -0,0 +1,164 @@
+#pragma once
+#include "core/blob.h"
+#include "core/data_type.h"
+#include "core/object.h"
+#include "core/runtime.h"
+#include <cmath>
+#include <cstring>
+#include <fstream>
+
+namespace infini {
+    class GraphObj;
+    using ShapeElem = int;
+    using Shape = vector<ShapeElem>;
+    class TensorObj : public Object
+    {
+        friend class GraphObj;
+
+    protected:
+        int dim;
+
+        DataType dtype;
+        vector<WRef<OperatorObj>> targets;
+        WRef<OperatorObj> source;
+        Blob data;
+        Runtime runtime;
+
+    private:
+        Shape shape;
+        size_t _size; // Cache of Π(shape).
+        Fuid fuid;    // Cloned tensors share the same id. Tensors constructed from
+                      // scratch have a new id.
+
+    public:
+        TensorObj(Shape shape, DataType dtype, Runtime runtime);
+        virtual ~TensorObj() {}
+        string toString() const override;
+
+        size_t size() const { return _size; }
+        size_t getBytes() const { return _size * dtype.getSize(); }
+
+        Shape getDims() const { return shape; }
+        void setShape(Shape shape_);
+        size_t getRank() const { return shape.size(); }
+        UidBaseType getFuid() const { return fuid; }
+
+        void setData(
+            std::function<void(void *, size_t, DataType)> const &generator) const;
+
+        void setDataBlob(const Blob &blob);
+
+        void printData() const;
+        bool equalData(const Tensor &rhs, double relativeError = 1e-6) const;
+
+        template <typename T>
+        bool equalData(const vector<T> &dataVector)
+        {
+            IT_ASSERT(size() == dataVector.size());
+            IT_ASSERT(DataType::get<T>() == dtype.cpuTypeInt());
+            return equalDataImpl(getRawDataPtr<T *>(), dataVector.data(), size());
+        }
+
+        template <typename T>
+        T getRawDataPtr() const
+        {
+            static_assert(std::is_pointer_v<T>,
+                          "Raw data pointer has a type of pointer");
+            IT_ASSERT(data != nullptr);
+            return data->getPtr<T>();
+        }
+
+        DataType getDType() const { return dtype; }
+        Runtime getRuntime() const { return runtime; }
+
+        OpVec getTargets() const { return wrefs_to_refs(targets); }
+        Operator getSource() const { return source.lock(); }
+
+    private:
+        template <class T>
+        string dataToString() const
+        {
+            std::stringstream builder;
+            builder << "Tensor: " << guid << std::endl;
+
+            auto numDims = shape.size();
+            auto dimSzVec = vector<int>(numDims, 1);
+            auto ptr = data->getPtr<T *>();
+            dimSzVec[numDims - 1] = shape[numDims - 1];
+
+            for (int i = numDims - 1; i != 0; --i)
+                dimSzVec[i - 1] = dimSzVec[i] * shape[i - 1];
+
+            for (size_t i = 0, iEnd = size(); i < iEnd; ++i)
+            {
+                for (size_t j = 0; j < numDims; ++j)
+                    if (i % dimSzVec[j] == 0)
+                        builder << "[";
+
+                builder << ptr[i];
+                for (size_t j = 0; j < numDims; ++j)
+                    if ((int)i % dimSzVec[j] == dimSzVec[j] - 1)
+                        builder << "]";
+
+                if (i != size() - 1)
+                    builder << ", ";
+
+                auto column = (size_t)dimSzVec[numDims - 1];
+                if (i % column == column - 1)
+                    builder << std::endl;
+            }
+            return builder.str();
+        }
+
+        template <typename T>
+        bool equalDataImpl(const T *a, const T *b, size_t size,
+                           double relativeError = 1e-6) const
+        {
+            for (size_t i = 0; i < size; ++i)
+            {
+                if constexpr (std::is_integral_v<T>)
+                {
+                    if (a[i] != b[i])
+                        return false;
+                }
+                else if constexpr (std::is_floating_point_v<T>)
+                {
+                    if (std::min(fabs(a[i]), fabs(b[i])) == 0. &&
+                        fabs(a[i] - b[i]) > relativeError)
+                    {
+                        printf("Error on %lu: %f %f\n", i, a[i], b[i]);
+                        return false;
+                    }
+                    else if (std::min(fabs(a[i]), fabs(b[i])) != 0. &&
+                             fabs(a[i] - b[i]) /
+                                     std::max(fabs(a[i]), fabs(b[i])) >
+                                 relativeError)
+                    {
+                        printf("Error on %lu: %f %f\n", i, a[i], b[i]);
+                        return false;
+                    }
+                }
+                else
+                {
+                    static_assert(!sizeof(T), "Unsupported data type");
+                }
+            }
+            return true;
+        }
+
+        void addTarget(const Operator &op) { targets.emplace_back(op); }
+        void setSource(const Operator &op) { source = op; }
+        void removeTarget(const Operator &op)
+        {
+            for (auto itr = targets.begin(); itr != targets.end();)
+            {
+                if (itr->lock() == op)
+                    itr = targets.erase(itr);
+                else
+                    ++itr;
+            }
+        }
+
+    };
+
+} // namespace infini
diff --git a/include/operators/concat.h b/include/operators/concat.h
new file mode 100644
index 0000000..86287fd
--- /dev/null
+++ b/include/operators/concat.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "core/operator.h"
+
+namespace infini {
+/**
+ * @brief Concatenate several tensors into one. All the input tensors should
+ * have the same shape except for the concatenated dimension.
+ *
+ */
+class ConcatObj : public OperatorObj {
+    int dim;
+
+  public:
+    /**
+     * @brief Construct a new Concat object.
+     *
+     * @param graph The computation graph that this operator belongs to.
+     * @param inputs The input tensors to be concatenated.
+     * @param output Concatenated tensor.
+     * @param dim The dimension to concatenate on.
+     */
+    ConcatObj(GraphObj *graph, TensorVec inputs, Tensor output, int dim);
+    OP_CLONE(ConcatObj);
+
+    optional<vector<Shape>> inferShape(const TensorVec &inputs) override;
+
+    std::string toString() const override;
+    int numInputs() const override { return inputs.size(); }
+    int numOutputs() const override { return 1; }
+    int getDim() const { return dim; }
+};
+} // namespace infini
diff --git a/include/operators/element_wise.h b/include/operators/element_wise.h
new file mode 100644
index 0000000..4260b2d
--- /dev/null
+++ b/include/operators/element_wise.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "core/operator.h"
+
+namespace infini
+{
+  /**
+   * @brief Base class of **binary** element-wise operators.
+   * Unary operators like activations are not the derived classes of
+   * ElementWiseObj.
+   *
+   */
+  class ElementWiseObj : public OperatorObj
+  {
+  public:
+    /**
+     * @brief Construct a new ElementWise object
+     *
+     * @param type Operator type.
+     * @param graph The computation graph that this operator belongs to.
+     * @param input0 The first input tensor.
+     * @param input1 The second input tensor.
+     * @param output The output tensor.
+     */
+    ElementWiseObj(OpType type, GraphObj *graph, Tensor input0, Tensor input1,
+                   Tensor output);
+    optional<vector<Shape>> inferShape(const TensorVec &inputs) override;
+
+    std::string toString() const override;
+    int numInputs() const override { return 2; }
+    int numOutputs() const override { return 1; }
+    };
+
+#define DEFINE_ELEMENT_WISE_OBJ(prefix, type)                    \
+  class prefix##Obj : public ElementWiseObj                      \
+  {                                                              \
+  public:                                                        \
+    prefix##Obj(GraphObj *graph, Tensor input0, Tensor input1,   \
+                Tensor output)                                   \
+        : ElementWiseObj(type, graph, input0, input1, output) {} \
+    OP_CLONE(prefix##Obj);                                       \
+  };
+
+  DEFINE_ELEMENT_WISE_OBJ(Add, OpType::Add)
+  DEFINE_ELEMENT_WISE_OBJ(Sub, OpType::Sub)
+  DEFINE_ELEMENT_WISE_OBJ(Mul, OpType::Mul)
+  DEFINE_ELEMENT_WISE_OBJ(Div, OpType::Div)
+}; // namespace infini
diff --git a/include/operators/transpose.h b/include/operators/transpose.h
new file mode 100644
index 0000000..c32bbe5
--- /dev/null
+++ b/include/operators/transpose.h
@@ -0,0 +1,34 @@
+#pragma once
+#include "core/operator.h"
+
+namespace infini
+{
+  /**
+   * @brief Transpose the input tensor similar to numpy.transpose.
+   *
+   */
+  class TransposeObj : public OperatorObj
+  {
+  public:
+    /**
+     * @brief Construct a new TransposeObj object.
+     *
+     * @param graph The graph to which this operator belongs.
+     * @param input The input tensor.
+     * @param output The output tensor.
+     * @param permute The permutation of the dimensions.
+     */
+    TransposeObj(GraphObj *graph, Tensor input, Tensor output,
+                 vector<int> permute);
+    OP_CLONE(TransposeObj);
+    optional<vector<Shape>> inferShape(const TensorVec &inputs) override;
+
+    std::string toString() const override;
+    int numInputs() const override { return 1; }
+    int numOutputs() const override { return 1; }
+    std::vector<int> getPermute() const { return transposePermute; }
+
+  private:
+    vector<int> transposePermute;
+  };
+} // namespace infini
diff --git a/include/operators/unary.h b/include/operators/unary.h
new file mode 100644
index 0000000..83f3dd3
--- /dev/null
+++ b/include/operators/unary.h
@@ -0,0 +1,104 @@
+#pragma once
+#include "core/operator.h"
+
+namespace infini
+{
+  /**
+   * @brief The base class for unary operators.
+   *
+   */
+  class UnaryObj : public OperatorObj
+  {
+  public:
+    /**
+     * @brief Construct a new Unary object.
+     *
+     * @param type Operator type.
+     * @param graph The computation graph that this operator belongs to.
+     * @param input The input tensor.
+     * @param output The output tensor.
+     */
+    UnaryObj(OpType type, GraphObj *graph, Tensor input, Tensor output);
+    optional<vector<Shape>> inferShape(const TensorVec &inputs) override;
+
+    std::string toString() const override;
+    int numInputs() const override { return 1; }
+    int numOutputs() const override { return 1; }
+  };
+
+  class ClipObj : public OperatorObj
+  {
+  public:
+    ClipObj(GraphObj *graph, Tensor input, Tensor output,
+            std::optional<float> min, std::optional<float> max);
+    OP_CLONE(ClipObj);
+    optional<vector<Shape>> inferShape(const TensorVec &inputs) override;
+
+    std::string toString() const override;
+    std::optional<float> getMin() const { return minValue; };
+    std::optional<float> getMax() const { return maxValue; };
+    int numInputs() const override { return 1; }
+    int numOutputs() const override { return 1; }
+
+  private:
+    std::optional<float> minValue, maxValue;
+  };
+
+  enum class CastType
+  {
+    Float2Float16 = 0,
+    Float2Int64,
+    Float2Int32,
+    Float2Int16,
+    Float2Int8,
+    Float2BFloat16,
+    Int322Float,
+    Int322Int8,
+    Int322Int16,
+    Int322Int64,
+    Int162Float,
+    Int162Int32,
+    Int82Float,
+    Int82Int16,
+    Int82Int32,
+    Uint82Float,
+    Uint82Int32,
+    Uint82Int64,
+    Int642Int32,
+    Int642Uint32,
+    Int642Float,
+    Uint322Int64,
+    Float162Float,
+    BFloat162Float,
+    Float2Float,
+  };
+
+  class CastObj : public OperatorObj
+  {
+  public:
+    CastObj(GraphObj *graph, Tensor input, Tensor output, CastType type);
+    OP_CLONE(CastObj);
+    optional<vector<Shape>> inferShape(const TensorVec &inputs) override;
+    vector<DataType> inferDataType(const TensorVec &inputs) const override;
+
+    std::string toString() const override;
+    CastType getType() const { return castType; }
+    DataType getOutputDataType() const;
+    int numInputs() const override { return 1; }
+    int numOutputs() const override { return 1; }
+
+  private:
+    CastType castType;
+  };
+
+#define DEFINE_UNARY_OBJ(prefix, type)                        \
+  class prefix##Obj : public UnaryObj                         \
+  {                                                           \
+  public:                                                     \
+    prefix##Obj(GraphObj *graph, Tensor input, Tensor output) \
+        : UnaryObj(type, graph, input, output) {}             \
+    OP_CLONE(prefix##Obj);                                    \
+  };
+
+  DEFINE_UNARY_OBJ(Relu, OpType::Relu)
+}; // namespace infini
diff --git a/include/test.h b/include/test.h
new file mode 100644
index 0000000..cef5a3e
--- /dev/null
+++ b/include/test.h
@@ -0,0 +1,4 @@
+#pragma once
+#include "core/common.h"
+#include "utils/data_generator.h"
+#include "gtest/gtest.h"
diff --git a/include/utils/data_generator.h b/include/utils/data_generator.h
new file mode 100644
index 0000000..1b7d91a
--- /dev/null
+++ b/include/utils/data_generator.h
@@ -0,0 +1,59 @@
+#pragma once
+#include "core/common.h"
+#include <random>
+
+namespace infini {
+
+class DataGenerator {
+  private:
+    virtual void fill(uint32_t *data, size_t size) { IT_TODO_HALT(); }
+    virtual void fill(float *data, size_t size) { IT_TODO_HALT(); }
+
+public:
+    virtual ~DataGenerator() {}
+    void operator()(void *data, size_t size, DataType dataType) {
+        if (dataType == DataType::UInt32)
+            fill(reinterpret_cast<uint32_t *>(data), size);
+        else if (dataType == DataType::Float32)
+            fill(reinterpret_cast<float *>(data), size);
+        else
+            IT_TODO_HALT();
+    }
+};
+
+class IncrementalGenerator : public DataGenerator {
+  public:
+    virtual ~IncrementalGenerator() {}
+
+  private:
+    template <typename T> void fill(T *data, size_t size) {
+        for (size_t i = 0; i < size; i++) {
+            data[i] = i;
+        }
+    }
+
+    void fill(uint32_t *data, size_t size) override {
+        fill<uint32_t>(data, size);
+    }
+    void fill(float *data, size_t size) override { fill<float>(data, size); }
+};
+
+template <int val> class ValGenerator : public DataGenerator {
+  public:
+    virtual ~ValGenerator() {}
+
+  private:
+    template <typename T> void fill(T *data, size_t size) {
+        for (size_t i = 0; i < size; i++) {
+            data[i] = val;
+        }
+    }
+
+    void fill(uint32_t *data, size_t size) override {
+        fill<uint32_t>(data, size);
+    }
+    void fill(float *data, size_t size) override { fill<float>(data, size); }
+};
+typedef ValGenerator<1> OneGenerator;
+typedef ValGenerator<0> ZeroGenerator;
+} // namespace infini
diff --git a/include/utils/exception.h b/include/utils/exception.h
new file mode 100644
index 0000000..d7bb433
--- /dev/null
+++ b/include/utils/exception.h
@@ -0,0 +1,22 @@
+#pragma once
+#include <stdexcept>
+#include <string>
+
+namespace infini {
+
+class Exception : public std::runtime_error {
+  protected:
+    std::string info;
+
+  public:
+    Exception(const std::string &msg);
+
+    Exception &operator<<(const std::string &str) {
+        info += str;
+        return *this;
+    }
+
+    const char *what() const noexcept override { return info.c_str(); }
+};
+
+} // namespace infini
diff --git a/include/utils/operator_utils.h b/include/utils/operator_utils.h
new file mode 100644
index 0000000..e3a2373
--- /dev/null
+++ b/include/utils/operator_utils.h
@@ -0,0 +1,26 @@
+#pragma once
+#ifndef OPERATOR_UTIL_H
+#define OPERATOR_UTIL_H
+
+#include "core/operator.h"
+#include "core/tensor.h"
+
+#include <numeric>
+
+namespace infini {
+
+// Launch a broadcast shape based on the shape of input A and B
+Shape infer_broadcast(const Shape &A, const Shape &B);
+// Launch the real axis based on rank and current axis
+int get_real_axis(const int &axis, const int &rank);
+// Locate the index with size from Shape
+Shape locate_index(size_t inputN, const Shape &shape);
+// Delocate the ShapeIndex from Shape with broadcast
+size_t delocate_index(const Shape &shapeIndex, const Shape &shape,
+                      const Shape &stride);
+// Convert KernelAttrs to a string representation
+std::string get_kernel_attrs_str(const KernelAttrs &kernelAttrs);
+
+} // namespace infini
+
+#endif
diff --git a/src/core/allocator.cc b/src/core/allocator.cc
new file mode 100644
index 0000000..ff593ae
--- /dev/null
+++ b/src/core/allocator.cc
@@ -0,0 +1,69 @@
+#include "core/allocator.h"
+#include <utility>
+
+namespace infini
+{
+    Allocator::Allocator(Runtime runtime) : runtime(runtime)
+    {
+        used = 0;
+        peak = 0;
+        ptr = nullptr;
+
+        // 'alignment' defaults to sizeof(uint64_t), because it is the length of
+        // the longest data type currently supported by the DataType field of
+        // the tensor
+        alignment = sizeof(uint64_t);
+    }
+
+    Allocator::~Allocator()
+    {
+        if (this->ptr != nullptr)
+        {
+            runtime->dealloc(this->ptr);
+        }
+    }
+
+    size_t Allocator::alloc(size_t size)
+    {
+        IT_ASSERT(this->ptr == nullptr);
+        // pad the size to the multiple of alignment
+        size = this->getAlignedSize(size);
+
+        // =================================== 作业 ===================================
+        // TODO: 设计一个算法来分配内存,返回起始地址偏移量
+        // =================================== 作业 ===================================
+
+        return 0;
+    }
+
+    void Allocator::free(size_t addr, size_t size)
+    {
+        IT_ASSERT(this->ptr == nullptr);
+        size = getAlignedSize(size);
+
+        // =================================== 作业 ===================================
+        // TODO: 设计一个算法来回收内存
+        // =================================== 作业 ===================================
+    }
+
+    void *Allocator::getPtr()
+    {
+        if (this->ptr == nullptr)
+        {
+            this->ptr = runtime->alloc(this->peak);
+            printf("Allocator really alloc: %p %lu bytes\n", this->ptr, peak);
+        }
+        return this->ptr;
+    }
+
+    size_t Allocator::getAlignedSize(size_t size)
+    {
+        return ((size - 1) / this->alignment + 1) * this->alignment;
+    }
+
+    void Allocator::info()
+    {
+        std::cout << "Used memory: " << this->used
+                  << ", peak memory: " << this->peak << std::endl;
+    }
+}
diff --git a/src/core/data_type.cc b/src/core/data_type.cc
new file mode 100644
index 0000000..3825c9c
--- /dev/null
+++ b/src/core/data_type.cc
@@ -0,0 +1,22 @@
+#include "core/data_type.h"
+
+namespace infini {
+// Move implementation here to avoid compile time error on some platform
+// to be consistent with onnx
+// https://github.com/onnx/onnx/blob/aeb21329122b96df1d3ef33b500a35ca140b1431/onnx/onnx.proto#L484
+const DataType DataType::Undefine(0);
+const DataType DataType::Float32(1);
+const DataType DataType::UInt8(2);
+const DataType DataType::Int8(3);
+const DataType DataType::UInt16(4);
+const DataType DataType::Int16(5);
+const DataType DataType::Int32(6);
+const DataType DataType::Int64(7);
+const DataType DataType::String(8);
+const DataType DataType::Bool(9);
+const DataType DataType::Float16(10);
+const DataType DataType::Double(11);
+const DataType DataType::UInt32(12);
+const DataType DataType::UInt64(13);
+const DataType DataType::BFloat16(16);
+} // namespace infini
diff --git a/src/core/graph.cc b/src/core/graph.cc
new file mode 100644
index 0000000..345395e
--- /dev/null
+++ b/src/core/graph.cc
@@ -0,0 +1,322 @@
+#include "core/graph.h"
+#include <algorithm>
+#include <numeric>
+#include <queue>
+
+namespace infini
+{
+
+    void GraphObj::addOperatorAndConnect(const Operator &op)
+    {
+        sorted = false;
+        ops.push_back(op);
+        for (auto &input : op->getInputs())
+        {
+            if (input)
+            {
+                input->addTarget(op);
+                if (auto pred = input->getSource())
+                {
+                    pred->addSuccessors(op);
+                    op->addPredecessors(pred);
+                }
+            }
+        }
+        for (auto &output : op->getOutputs())
+        {
+            if (output)
+            {
+                output->setSource(op);
+                for (auto &succ : output->getTargets())
+                {
+                    succ->addPredecessors(op);
+                    op->addSuccessors(succ);
+                }
+            }
+        }
+    }
+
+    string GraphObj::toString() const
+    {
+        std::ostringstream oss;
+        oss << "Graph Tensors:\n";
+        for (const auto &tensor : tensors)
+            oss << tensor << "\n";
+
+        oss << "Graph operators:\n";
+        for (const auto &op : ops)
+        {
+            vector<UidBaseType> preds, succs;
+            for (auto &o : op->getPredecessors())
+                preds.emplace_back(o->getGuid());
+            for (auto &o : op->getSuccessors())
+                succs.emplace_back(o->getGuid());
+            oss << "OP " << op->getGuid();
+            oss << ", pred " << vecToString(preds);
+            oss << ", succ " << vecToString(succs);
+            oss << ", " << op << "\n";
+        }
+        return oss.str();
+    }
+
+    bool GraphObj::topo_sort()
+    {
+        if (this->sorted)
+        {
+            return true;
+        }
+        std::vector<Operator> sorted;
+        std::unordered_set<OperatorObj *> flags;
+        sorted.reserve(ops.size());
+        flags.reserve(ops.size());
+        while (sorted.size() < ops.size())
+        {
+            // Any node is move to sorted in this loop.
+            auto modified = false;
+            for (auto const &op : ops)
+            {
+                if (auto const &inputs = op->getInputs();
+                    flags.find(op.get()) == flags.end() &&
+                    std::all_of(inputs.begin(), inputs.end(),
+                                [&flags](auto const &input)
+                                {
+                                    auto ptr = input->getSource().get();
+                                    return !ptr || flags.find(ptr) != flags.end();
+                                }))
+                {
+                    modified = true;
+                    sorted.emplace_back(op);
+                    flags.insert(op.get());
+                }
+            }
+            if (!modified)
+            {
+                return false;
+            }
+        }
+        this->ops = std::move(sorted);
+        return this->sorted = true;
+    }
+
+    void GraphObj::optimize()
+    {
+        for (auto &op : ops)
+        {
+            switch (op->getOpType().underlying())
+            {
+            default:
+                break;
+            }
+        }
+    }
+
+    Tensor GraphObj::getTensor(int fuid) const
+    {
+        for (auto tensor : tensors)
+        {
+            if (tensor->getFuid() == fuid)
+            {
+                return tensor;
+            }
+        }
+        return nullptr;
+    }
+
+    void GraphObj::shape_infer()
+    {
+        for (auto &op : ops)
+        {
+            auto ans = op->inferShape();
+            IT_ASSERT(ans.has_value());
+            auto oldOutputs = op->getOutputs();
+            IT_ASSERT(ans.value().size() == oldOutputs.size());
+            // replace the old outputshape and size with new one
+            for (int i = 0; i < (int)ans.value().size(); ++i)
+            {
+                auto newShape = ans.value()[i];
+                auto oldShape = oldOutputs[i]->getDims();
+                auto fuid = oldOutputs[i]->getFuid();
+                if (newShape != oldShape)
+                {
+                    auto tensor = this->getTensor(fuid);
+                    tensor->setShape(newShape);
+                }
+            }
+        }
+    }
+
+    void GraphObj::dataMalloc()
+    {
+        // topological sorting first
+        IT_ASSERT(topo_sort() == true);
+        // count the number of times all tensors are used
+        std::unordered_map<TensorObj *, size_t> tensorToRefCount;
+        // record the memory address offsets of all tensors to be allocated
+        std::unordered_map<TensorObj *, size_t> tensorToOffset;
+
+        // record all constant tensors, including weight tensors and input tensors
+        std::unordered_set<TensorObj *> constTensor;
+        for (auto &tensor : tensors)
+        {
+            if (tensor.get()->getSource() == nullptr)
+            {
+                // allocate memory for all constant tensors first, and this memory
+                // will not be reused later
+                constTensor.insert(tensor.get());
+                tensorToOffset[tensor.get()] = allocator.alloc(tensor->getBytes());
+            }
+            else
+            {
+                tensorToRefCount[tensor.get()] = tensor->getTargets().size();
+            }
+        }
+        // traverse in topological order and simulate memory allocation
+        for (auto &op : ops)
+        {
+            // memory should be allocated for the output first
+            auto outputs = op->getOutputs();
+            for (auto &tensor : outputs)
+            {
+                tensorToOffset[tensor.get()] = allocator.alloc(tensor->getBytes());
+            }
+            auto inputs = op->getInputs();
+            for (auto &tensor : inputs)
+            {
+                if (constTensor.find(tensor.get()) == constTensor.end())
+                {
+                    auto tensorIter = tensorToRefCount.find(tensor.get());
+                    IT_ASSERT(tensorIter != tensorToRefCount.end());
+                    tensorToRefCount[tensor.get()] -= 1;
+                    if (tensorToRefCount[tensor.get()] == 0)
+                    {
+                        // indicate that this tensor will no longer be used and
+                        // perform memory free
+                        tensorToRefCount.erase(tensor.get());
+                        allocator.free(tensorToOffset[tensor.get()],
+                                       tensor->getBytes());
+                    }
+                }
+            }
+        }
+
+        // perform actual memory allocation
+        for (auto &tensor : tensors)
+        {
+            IT_ASSERT(tensorToOffset.find(tensor.get()) != tensorToOffset.end());
+            tensor->setDataBlob(make_ref<BlobObj>(
+                tensor->runtime, static_cast<uint8_t *>(allocator.getPtr()) +
+                                     tensorToOffset[tensor.get()]));
+        }
+
+        allocator.info();
+    }
+
+    Tensor GraphObj::addTensor(Shape dim, DataType dtype)
+    {
+        return tensors.emplace_back(make_ref<TensorObj>(dim, dtype, runtime));
+    }
+
+    Tensor GraphObj::addTensor(const Tensor &tensor)
+    {
+        IT_ASSERT(tensor->getRuntime() == runtime,
+                  std::string("Tensor runtime mismatch: cannot add a tenosr in ") +
+                      tensor->getRuntime()->toString() + " to " +
+                      runtime->toString());
+        tensors.emplace_back(tensor);
+        return tensor;
+    }
+
+    TensorVec GraphObj::addTensor(const TensorVec &tensors)
+    {
+        for (auto &t : tensors)
+            addTensor(t);
+        return tensors;
+    }
+
+    void GraphObj::deleteConnection(Tensor tensor, Operator op)
+    {
+        // if op is target
+        IT_ASSERT(std::find(tensor->getTargets().begin(),
+                            tensor->getTargets().end(),
+                            op) != tensor->getTargets().end());
+        tensor->removeTarget(op);
+        if (tensor->getSource())
+        {
+            tensor->getSource()->removeSuccessors(op);
+            op->removePredecessors(tensor->getSource());
+        }
+    }
+
+    // add op as a target
+    void GraphObj::addConnection(Tensor tensor, Operator op)
+    {
+        tensor->addTarget(op);
+        if (tensor->getSource())
+        {
+            tensor->getSource()->addSuccessors(op);
+            op->addPredecessors(tensor->getSource());
+        }
+    }
+
+    void GraphObj::replaceConnection(Tensor oldTensor, Tensor newTensor,
+                                     Operator op)
+    {
+        // op is a target of old tensor
+        IT_ASSERT(std::find(oldTensor->getTargets().begin(),
+                            oldTensor->getTargets().end(),
+                            op) != oldTensor->getTargets().end());
+        addConnection(newTensor, op);
+        deleteConnection(oldTensor, op);
+        op->replaceInput(oldTensor, newTensor);
+    }
+
+    // tensor's "source" and "target" must be in "ops".
+    // tensor has no "source" and no "target" must not exist.
+    // "inputs" or "outputs" of operators must be in "tensors"
+    // "predecessors" and "successors" of an operator of "ops" must be in "ops".
+    bool GraphObj::checkValid() const
+    {
+        for (auto tensor : tensors)
+        {
+            IT_ASSERT(!(tensor->getTargets().size() == 0 &&
+                        nullptr == tensor->getSource()));
+            for (auto op : tensor->getTargets())
+            {
+                IT_ASSERT(std::find(ops.begin(), ops.end(), op) != ops.end());
+            }
+            auto op = tensor->getSource();
+            IT_ASSERT(!(op && std::find(ops.begin(), ops.end(), op) == ops.end()));
+        }
+        for (auto op : ops)
+        {
+            for (auto tensor : op->getInputs())
+            {
+                IT_ASSERT(std::find(tensors.begin(), tensors.end(), tensor) !=
+                          tensors.end());
+            }
+            for (auto tensor : op->getOutputs())
+            {
+                IT_ASSERT(std::find(tensors.begin(), tensors.end(), tensor) !=
+                          tensors.end());
+            }
+            for (auto pre : op->getPredecessors())
+            {
+                IT_ASSERT(std::find(ops.begin(), ops.end(), pre) != ops.end());
+            }
+            for (auto suc : op->getSuccessors())
+            {
+                IT_ASSERT(std::find(ops.begin(), ops.end(), suc) != ops.end());
+            }
+        }
+        std::set<UidBaseType> s;
+        // check whether two tensors with the same FUID exist
+        for (auto tensor : tensors)
+        {
+            int cnt = s.count(tensor->getFuid());
+            IT_ASSERT(cnt == 0, std::to_string(tensor->getFuid()));
+            s.insert(tensor->getFuid());
+        }
+        return true;
+    }
+
+} // namespace infini
\ No newline at end of file
diff --git a/src/core/op_type.cc b/src/core/op_type.cc
new file mode 100644
index 0000000..5b62a71
--- /dev/null
+++ b/src/core/op_type.cc
@@ -0,0 +1,31 @@
+#include "core/op_type.h"
+
+namespace infini
+{
+    const char *OpType::toString() const
+    {
+#define CASE(NAME)     \
+    case OpType::NAME: \
+        return #NAME
+
+        switch (type)
+        {
+            CASE(Unknown);
+            CASE(Add);
+            CASE(Sub);
+            CASE(Mul);
+            CASE(Div);
+            CASE(Cast);
+            CASE(Clip);
+            CASE(Relu);
+            CASE(Transpose);
+            CASE(Concat);
+
+        default:
+            return "Unknown";
+        }
+
+#undef CASE
+    }
+
+} // namespace infini
diff --git a/src/core/operator.cc b/src/core/operator.cc
new file mode 100644
index 0000000..a70ca48
--- /dev/null
+++ b/src/core/operator.cc
@@ -0,0 +1,85 @@
+#include "core/operator.h"
+#include "core/graph.h"
+
+namespace infini
+{
+
+    OperatorObj::OperatorObj(OpType opType, TensorVec inputs, TensorVec outputs)
+        : type(opType), inputs(inputs), outputs(outputs) {}
+
+    void OperatorObj::removePredecessors(const Operator &op)
+    {
+        for (auto it = predecessors.begin(); it != predecessors.end();)
+        {
+            if (it->lock() == op)
+                it = predecessors.erase(it);
+            else
+                ++it;
+        }
+    }
+
+    void OperatorObj::removeSuccessors(const Operator &op)
+    {
+        for (auto it = successors.begin(); it != successors.end();)
+        {
+            if (it->lock() == op)
+                it = successors.erase(it);
+            else
+                ++it;
+        }
+    }
+
+    void OperatorObj::replaceInput(Tensor t1, Tensor t2)
+    {
+        for (auto itr = inputs.begin(); itr != inputs.end(); ++itr)
+        {
+            if (*itr == t1)
+            {
+                *itr = t2;
+            }
+        }
+    }
+
+    bool OperatorObj::checkValid(GraphObj *graph)
+    {
+        auto optShapes = inferShape();
+        if (!optShapes) // shape inference failed
+            return false;
+
+        const vector<Shape> &shapes = *optShapes;
+        if (shapes.size() != outputs.size())
+            return false;
+        if (graph)
+        { // if graph != nullptr, outputs should be created
+            auto dataTypes = inferDataType();
+            for (size_t i = 0; i < outputs.size(); i++)
+            {
+                IT_ASSERT(!outputs[i], "Find empty output while operator creation");
+                outputs[i] = graph->addTensor(shapes[i], dataTypes[i]);
+            }
+        }
+        else
+        { // if outputs have been created, check their shapes
+            for (size_t i = 0; i < shapes.size(); ++i)
+            {
+                if (shapes[i] != outputs[i]->getDims())
+                    return false;
+            }
+        }
+        return true;
+    }
+
+    optional<vector<Shape>> OperatorObj::inferShape() { return inferShape(inputs); }
+
+    vector<DataType> OperatorObj::inferDataType(const TensorVec &inputs) const
+    {
+        auto dataType = inputs[0]->getDType();
+        return vector(numOutputs(), dataType);
+    }
+
+    vector<DataType> OperatorObj::inferDataType() const
+    {
+        return inferDataType(inputs);
+    }
+
+} // namespace infini
diff --git a/src/core/runtime.cc b/src/core/runtime.cc
new file mode 100644
index 0000000..bd88d90
--- /dev/null
+++ b/src/core/runtime.cc
@@ -0,0 +1,36 @@
+#include "core/runtime.h"
+#include "core/blob.h"
+#include "core/kernel.h"
+#include "core/graph.h"
+#include "core/kernel.h"
+#include <chrono>
+#include <cstring>
+#include <memory>
+namespace infini
+{
+    void NativeCpuRuntimeObj::run(const Graph &graph) const
+    {
+        const auto &kernelRegistry = KernelRegistry::getInstance();
+
+        for (auto &op : graph->getOperators())
+        {
+            auto kernelAttrs = KernelAttrs{device, op->getOpType().underlying()};
+            Kernel *kernel = kernelRegistry.getKernel(kernelAttrs);
+            kernel->compute(op, this);
+        }
+    }
+
+    string NativeCpuRuntimeObj::toString() const { return "CPU Runtime"; }
+
+    void NativeCpuRuntimeObj::dealloc(void *ptr)
+    {
+        return free(ptr);
+    }
+
+    void *NativeCpuRuntimeObj::alloc(size_t size)
+    {
+        return calloc((size + sizeof(uint64_t) - 1) / sizeof(uint64_t),
+                      sizeof(uint64_t));
+    }
+
+} // namespace infini
diff --git a/src/core/tensor.cc b/src/core/tensor.cc
new file mode 100644
index 0000000..db54a2d
--- /dev/null
+++ b/src/core/tensor.cc
@@ -0,0 +1,116 @@
+#include "core/tensor.h"
+#include "core/blob.h"
+#include "core/operator.h"
+#include "core/runtime.h"
+#include <cstring>
+#include <numeric>
+
+namespace infini {
+
+    TensorObj::TensorObj(Shape shape_, DataType dtype, Runtime runtime)
+        : dim(shape_.size()), dtype(dtype), runtime(runtime), shape(std::move(shape_)),
+          _size(std::accumulate(shape.begin(), shape.end(), 1, std::multiplies{})) {}
+
+    string TensorObj::toString() const
+    {
+        // Convert data pointer to string
+        std::stringstream ss;
+        if (data != nullptr)
+            ss << data->getPtr<void *>();
+        else
+            ss << "nullptr data";
+        string ret = "Tensor " + std::to_string(guid) + ", Fuid " +
+                     std::to_string(fuid) + ", shape " + vecToString(shape) +
+                     ", dtype " + dtype.toString() + ", " + runtime->toString() +
+                     ", " + ss.str() + "\n";
+        vector<UidBaseType> targetGuids;
+        for (const auto &op : targets)
+            targetGuids.emplace_back(op.lock()->getGuid());
+        if (auto o = source.lock())
+            ret += ", source " + std::to_string(o->getGuid());
+        else
+            ret += ", source None";
+        ret += ", targets " + vecToString(targetGuids);
+        return ret;
+    }
+
+void TensorObj::setShape(Shape shape_) {
+    shape = shape_;
+    size_t size = std::accumulate(shape.begin(), shape.end(), 1,
+                                  [](auto acc, auto x) { return acc * x; });
+    _size = size;
+}
+
+void TensorObj::printData() const {
+    IT_ASSERT(data != nullptr);
+    if (!runtime->isCpu())
+        IT_TODO_HALT();
+
+#define TRY_PRINT(N)                                                           \
+    if (dtype == DataType(N))                                                  \
+        std::cout << dataToString<DT<N>::t>() << std::endl;
+
+    TRY_PRINT(0)           // fmt: new line
+    else TRY_PRINT(1)      //
+        else TRY_PRINT(2)  //
+        else TRY_PRINT(3)  //
+        else TRY_PRINT(4)  //
+        else TRY_PRINT(5)  //
+        else TRY_PRINT(6)  //
+        else TRY_PRINT(7)  //
+        else TRY_PRINT(8)  //
+        else TRY_PRINT(9)  //
+        else TRY_PRINT(10) //
+        else TRY_PRINT(11) //
+        else TRY_PRINT(12) //
+        else TRY_PRINT(13) //
+        else TRY_PRINT(16) //
+        else IT_TODO_HALT();
+
+#undef TRY_PRINT
+}
+
+bool TensorObj::equalData(const Tensor &rhs, double relativeError) const {
+    IT_ASSERT(data != nullptr);
+    IT_ASSERT(rhs->data != nullptr);
+    IT_ASSERT(getDType() == rhs->getDType());
+    IT_ASSERT(runtime->isCpu());
+    IT_ASSERT(rhs->getRuntime()->isCpu());
+    if (size() != rhs->size())
+        return false;
+
+#define TEST_EQUAL(N)                                                          \
+    if (dtype == DataType(N))                                                  \
+        return equalDataImpl(getRawDataPtr<DT<N>::t *>(),                      \
+                             rhs->getRawDataPtr<DT<N>::t *>(), size(),         \
+                             relativeError);
+
+    TEST_EQUAL(0)           // fmt: new line
+    else TEST_EQUAL(1)      //
+        else TEST_EQUAL(2)  //
+        else TEST_EQUAL(3)  //
+        else TEST_EQUAL(4)  //
+        else TEST_EQUAL(5)  //
+        else TEST_EQUAL(6)  //
+        else TEST_EQUAL(7)  //
+        else TEST_EQUAL(8)  //
+        else TEST_EQUAL(9)  //
+        else TEST_EQUAL(10) //
+        else TEST_EQUAL(11) //
+        else TEST_EQUAL(12) //
+        else TEST_EQUAL(13) //
+        else TEST_EQUAL(16) //
+        else IT_TODO_HALT();
+
+#undef TEST_EQUAL
+}
+
+void TensorObj::setData(
+    const std::function<void(void *, size_t, DataType)> &generator) const {
+    IT_ASSERT(data != nullptr);
+    generator(getRawDataPtr<void *>(), size(), dtype);
+}
+
+void TensorObj::setDataBlob(const Blob &blob) { this->data = blob; }
+
+}; // namespace infini
diff --git a/src/kernels/cpu/concat.cc b/src/kernels/cpu/concat.cc
new file mode 100644
index 0000000..6e061c7
--- /dev/null
+++ b/src/kernels/cpu/concat.cc
@@ -0,0 +1,64 @@
+#include "operators/concat.h"
+#include "core/kernel.h"
+
+namespace infini {
+
+class NaiveConcat : public CpuKernelWithoutConfig {
+    template <typename T>
+    void doCompute(const Operator &_op, const RuntimeObj *context) const {
+        auto op = as<ConcatObj>(_op);
+        auto inputs = op->getInputs(), outputs = op->getOutputs();
+        auto dim = op->getDim();
+        auto output = outputs[0];
+        std::vector<Shape> iDims;
+        for (auto input : inputs)
+            iDims.emplace_back(input->getDims());
+        const auto &outDim = output->getDims();
+        size_t blockOffsetInner = 1;
+        for (size_t i = outDim.size() - 1; i > (size_t)dim; --i)
+            blockOffsetInner *= outDim[i];
+        size_t blockOffset = outDim[dim] * blockOffsetInner;
+        for (size_t i = 0; i < inputs.size(); ++i) {
+            auto input = inputs[i];
+            auto dimOffset = 0;
+            auto iDim = iDims[i];
+            for (size_t j = 0; j < i; ++j)
+                dimOffset += iDims[j][dim];
+            size_t localBlockOffset = 1;
+            for (size_t i = iDim.size() - 1;
+                 i >= (size_t)dim && i != (size_t)-1; --i)
+                localBlockOffset *= iDim[i];
+            auto innerOffset = blockOffsetInner * dimOffset;
+            auto inSize = input->size();
+            auto inPtr = input->getRawDataPtr<T *>(),
+                 outPtr = output->getRawDataPtr<T *>();
+#pragma omp parallel for
+            for (size_t iOffset = 0; iOffset < inSize; ++iOffset) {
+                auto oOffset = iOffset % localBlockOffset + innerOffset +
+                               iOffset / localBlockOffset * blockOffset;
+                outPtr[oOffset] = inPtr[iOffset];
+            }
+        }
+    }
+
+    void compute(const Operator &_op,
+                 const RuntimeObj *context) const override {
+#define CASE(N)                                                                \
+    case N:                                                                    \
+        doCompute<DT<N>::t>(_op, context)
+
+        int dataTypeIdx = _op->getDType().getIndex();
+        switch (dataTypeIdx) {
+            CASE(1); // DataType::Float32
+            break;
+            CASE(12); // DataType::UInt32
+            break;
+        default:
+            IT_TODO_HALT();
+        }
+    }
+};
+
+REGISTER_KERNEL(Device::CPU, OpType::Concat, NaiveConcat, "ConcatNaive_CPU");
+
+} // namespace infini
diff --git a/src/kernels/cpu/element_wise.cc b/src/kernels/cpu/element_wise.cc
new file mode 100644
index 0000000..af03c7a
--- /dev/null
+++ b/src/kernels/cpu/element_wise.cc
@@ -0,0 +1,119 @@
+#include "operators/element_wise.h"
+#include "core/kernel.h"
+#include "utils/operator_utils.h"
+
+namespace infini
+{
+    class NativeElementWise : public CpuKernelWithoutConfig
+    {
+        template <typename T>
+        static T addCompute(T val0, T val1)
+        {
+            return val0 + val1;
+        }
+
+        template <typename T>
+        static T subCompute(T val0, T val1)
+        {
+            return val0 - val1;
+        }
+
+        template <typename T>
+        static T mulCompute(T val0, T val1)
+        {
+            return val0 * val1;
+        }
+
+        template <typename T>
+        static T divCompute(T val0, T val1)
+        {
+            return (T)(val0 / val1);
+        }
+
+        template <typename T>
+        void doCompute(const Operator &_op, const RuntimeObj *context) const
+        {
+            auto op = as<ElementWiseObj>(_op);
+            T *inptr0 = op->getInputs(0)->getRawDataPtr<T *>();
+            T *inptr1 = op->getInputs(1)->getRawDataPtr<T *>();
+            T *outptr = op->getOutput()->getRawDataPtr<T *>();
+
+            auto shapeA = op->getInputs(0)->getDims();
+            auto shapeB = op->getInputs(1)->getDims();
+            auto shapeC = op->getOutput()->getDims();
+            auto rank = op->getOutput()->getRank();
+            Shape a(rank, 1);
+            Shape b(rank, 1);
+            std::copy(shapeA.begin(), shapeA.end(),
+                      a.begin() + (rank - shapeA.size()));
+            std::copy(shapeB.begin(), shapeB.end(),
+                      b.begin() + (rank - shapeB.size()));
+            auto getStride = [&](const Shape &shape)
+            {
+                int p = 1;
+                Shape stride(rank);
+                for (auto i = rank; i > 0; --i)
+                {
+                    stride[i - 1] = p;
+                    p = p * shape[i - 1];
+                }
+                return stride;
+            };
+            Shape strideA = getStride(a);
+            Shape strideB = getStride(b);
+
+            auto n = op->getOutput()->size();
+            T (*_doCompute)
+            (T val0, T val1);
+            switch (op->getOpType().underlying())
+            {
+            case OpType::Add:
+                _doCompute = addCompute<T>;
+                break;
+            case OpType::Sub:
+                _doCompute = subCompute<T>;
+                break;
+            case OpType::Mul:
+                _doCompute = mulCompute<T>;
+                break;
+            case OpType::Div:
+                _doCompute = divCompute<T>;
+                break;
+            default:
+                IT_TODO_HALT();
+            }
+
+            for (size_t i = 0; i < n; ++i)
+            {
+                auto shapeIndexC = locate_index(i, shapeC);
+                auto indexA = delocate_index(shapeIndexC, a, strideA);
+                auto indexB = delocate_index(shapeIndexC, b, strideB);
+                outptr[i] = _doCompute(inptr0[indexA], inptr1[indexB]);
+            }
+        }
+
+        void compute(const Operator &_op,
+                     const RuntimeObj *context) const override
+        {
+#define CASE(N) \
+    case N:     \
+        doCompute<DT<N>::t>(_op, context)
+
+            int dataTypeIdx = _op->getDType().getIndex();
+            switch (dataTypeIdx)
+            {
+                CASE(1); // DataType::Float32
+                break;
+                CASE(12); // DataType::UInt32
+                break;
+            default:
+                IT_TODO_HALT();
+            }
+        }
+    };
+
+    REGISTER_KERNEL(Device::CPU, OpType::Add, NativeElementWise, "addNaive_CPU");
+    REGISTER_KERNEL(Device::CPU, OpType::Sub, NativeElementWise, "subNaive_CPU");
+    REGISTER_KERNEL(Device::CPU, OpType::Mul, NativeElementWise, "mulNaive_CPU");
+    REGISTER_KERNEL(Device::CPU, OpType::Div, NativeElementWise, "divNaive_CPU");
+}; // namespace infini
diff --git a/src/kernels/cpu/transpose.cc b/src/kernels/cpu/transpose.cc
new file mode 100644
index 0000000..46292d4
--- /dev/null
+++ b/src/kernels/cpu/transpose.cc
@@ -0,0 +1,60 @@
+#include "operators/transpose.h"
+#include "core/kernel.h"
+
+namespace infini {
+
+inline Shape idx2Pos(const Shape &shape, size_t idx) {
+    Shape pos = Shape(shape.size(), 0);
+    auto rest = idx, curDimId = shape.size() - 1;
+    while (rest > 0) {
+        pos[curDimId] = rest % shape[curDimId];
+        rest /= shape[curDimId];
+        curDimId--;
+    }
+    return pos;
+}
+
+class NaiveTranspose : public CpuKernelWithoutConfig {
+    template <typename T>
+    void doCompute(const Operator &_op, const RuntimeObj *context) const {
+        auto op = as<TransposeObj>(_op);
+        auto inputs = op->getInputs(), outputs = op->getOutputs();
+        const auto &inDim = inputs[0]->getDims();
+        const auto &perm = op->getPermute();
+
+        size_t inSize = inputs[0]->size();
+        auto inPtr = inputs[0]->getRawDataPtr<T *>(),
+             outPtr = outputs[0]->getRawDataPtr<T *>();
+        // #pragma omp parallel for
+        for (size_t inIdx = 0; inIdx < inSize; ++inIdx) {
+            auto posInput = idx2Pos(inDim, inIdx);
+            int outIdx = 0;
+            for (size_t j = 0, jEnd = perm.size(); j < jEnd; ++j) {
+                outIdx = outIdx * inDim[perm[j]] + posInput[perm[j]];
+            }
+            outPtr[outIdx] = inPtr[inIdx];
+        }
+    }
+
+    void compute(const Operator &_op,
+                 const RuntimeObj *context) const override {
+#define CASE(N)                                                                \
+    case N:                                                                    \
+        doCompute<DT<N>::t>(_op, context)
+
+        int dataTypeIdx = _op->getDType().getIndex();
+        switch (dataTypeIdx) {
+            CASE(1); // DataType::Float32
+            break;
+            CASE(12); // DataType::UInt32
+            break;
+        default:
+            IT_TODO_HALT();
+        }
+    }
+};
+
+REGISTER_KERNEL(Device::CPU, OpType::Transpose, NaiveTranspose,
+                "TransposeNaive_CPU");
+
+} // namespace infini
diff --git a/src/kernels/cpu/unary.cc b/src/kernels/cpu/unary.cc
new file mode 100644
index 0000000..7e60a4d
--- /dev/null
+++ b/src/kernels/cpu/unary.cc
@@ -0,0 +1,106 @@
+#include "operators/unary.h"
+#include "core/constants.h"
+#include "core/kernel.h"
+
+namespace infini
+{
+    class NativeUnary : public CpuKernelWithoutConfig
+    {
+        template <typename T>
+        static T reluCompute(T val)
+        {
+            return std::max(T(0), val);
+        }
+
+        template <typename T>
+        void doCompute(const Operator &_op, const RuntimeObj *context) const
+        {
+            auto op = as<UnaryObj>(_op);
+            T *inptr = op->getInputs(0)->getRawDataPtr<T *>();
+            T *outptr = op->getOutput()->getRawDataPtr<T *>();
+
+            auto outDim = op->getOutput()->getDims();
+            auto n = op->getOutput()->size();
+
+            T (*_doCompute)
+            (T val);
+            switch (op->getOpType().underlying())
+            {
+            case OpType::Relu:
+                _doCompute = reluCompute<T>;
+                break;
+            default:
+                IT_TODO_HALT();
+            }
+
+            for (size_t offset = 0; offset < n; offset++)
+            {
+                outptr[offset] = _doCompute(inptr[offset]);
+            }
+        }
+
+        void compute(const Operator &_op,
+                     const RuntimeObj *context) const override
+        {
+#define CASE(N) \
+    case N:     \
+        doCompute<DT<N>::t>(_op, context)
+
+            int dataTypeIdx = _op->getDType().getIndex();
+            switch (dataTypeIdx)
+            {
+                CASE(1); // DataType::Float32
+                break;
+                CASE(12); // DataType::UInt32
+                break;
+            default:
+                IT_TODO_HALT();
+            }
+        }
+    };
+
+    class Clip : public CpuKernelWithoutConfig
+    {
+        template <typename T>
+        void doCompute(const Operator &_op, const RuntimeObj *context) const
+        {
+            auto op = as<ClipObj>(_op);
+            T *inptr = op->getInputs(0)->getRawDataPtr<T *>();
+            T *outptr = op->getOutput()->getRawDataPtr<T *>();
+            auto minValue = op->getMin();
+            auto maxValue = op->getMax();
+
+            auto n = op->getOutput()->size();
+            for (size_t offset = 0; offset < n; offset++)
+            {
+                auto val = *inptr++;
+                *outptr++ = (minValue && val < *minValue)   ? *minValue
+                            : (maxValue && val > *maxValue) ? *maxValue
+                                                            : val;
+            }
+        }
+
+        void compute(const Operator &_op,
+                     const RuntimeObj *context) const override
+        {
+#define CASE(N) \
+    case N:     \
+        doCompute<DT<N>::t>(_op, context)
+
+            int dataTypeIdx = _op->getDType().getIndex();
+            switch (dataTypeIdx)
+            {
+                CASE(1); // DataType::Float32
+                break;
+                CASE(12); // DataType::UInt32
+                break;
+            default:
+                IT_TODO_HALT();
+            }
+        }
+    };
+
+    REGISTER_KERNEL(Device::CPU, OpType::Relu, NativeUnary, "reluNaive_CPU");
+    REGISTER_KERNEL(Device::CPU, OpType::Clip, Clip, "Clip_CPU");
+
+}; // namespace infini
diff --git a/src/operators/concat.cc b/src/operators/concat.cc
new file mode 100644
index 0000000..d196330
--- /dev/null
+++ b/src/operators/concat.cc
@@ -0,0 +1,38 @@
+#include "operators/concat.h"
+#include "utils/operator_utils.h"
+
+namespace infini {
+ConcatObj::ConcatObj(GraphObj *graph, TensorVec inputs, Tensor output, int _dim)
+    : OperatorObj(OpType::Concat, inputs, {output}) {
+    int rank = inputs[0]->getRank();
+    dim = get_real_axis(_dim, rank);
+    IT_ASSERT(checkValid(graph));
+}
+
+optional<vector<Shape>> ConcatObj::inferShape(const TensorVec &inputs) {
+    Shape dims = inputs[0]->getDims();
+    auto rank = inputs[0]->getRank();
+
+    // =================================== 作业 ===================================
+    // TODO:修改 dims,返回正确的 concat 后的 shape
+    // REF: https://onnx.ai/onnx/operators/onnx__Concat.html#concat-13
+    // =================================== 作业 ===================================
+
+    return {{dims}};
+}
+
+std::string ConcatObj::toString() const {
+    std::ostringstream os;
+    os << "Concat[" << getGuid() << "]";
+    os << "(";
+    for (auto input : inputs)
+        os << vecToString(input->getDims()) << ",";
+    os << "dim=" << dim << ",";
+    os << "input=";
+    for (auto input : inputs)
+        os << input->getGuid() << ",";
+    os << "output=" << outputs[0]->getGuid() << ")";
+    return os.str();
+}
+
+} // namespace infini
diff --git a/src/operators/element_wise.cc b/src/operators/element_wise.cc
new file mode 100644
index 0000000..c1b4ef1
--- /dev/null
+++ b/src/operators/element_wise.cc
@@ -0,0 +1,33 @@
+#include "operators/element_wise.h"
+#include "utils/operator_utils.h"
+
+namespace infini
+{
+    ElementWiseObj::ElementWiseObj(OpType type, GraphObj *graph, Tensor input0,
+                                   Tensor input1, Tensor output)
+        : OperatorObj(type, {input0, input1}, {output})
+    {
+        IT_ASSERT(checkValid(graph));
+    }
+
+    optional<vector<Shape>> ElementWiseObj::inferShape(const TensorVec &inputs)
+    {
+        const auto A = inputs[0], B = inputs[1];
+        auto res = infer_broadcast(A->getDims(), B->getDims());
+        return {{res}};
+    }
+
+    std::string ElementWiseObj::toString() const
+    {
+        std::ostringstream os;
+        os << type.toString() << "[" << getGuid() << "]";
+        os << "(";
+        os << vecToString(inputs[0]->getDims()) << ",";
+        os << vecToString(inputs[1]->getDims()) << ",";
+        os << "input0=" << inputs[0]->getGuid() << ",";
+        os << "input1=" << inputs[1]->getGuid() << ",";
+        os << "output=" << outputs[0]->getGuid() << ")";
+        return os.str();
+    }
+
+}; // namespace infini
diff --git a/src/operators/transpose.cc b/src/operators/transpose.cc
new file mode 100644
index 0000000..f5e9659
--- /dev/null
+++ b/src/operators/transpose.cc
@@ -0,0 +1,50 @@
+#include "operators/transpose.h"
+
+namespace infini
+{
+    TransposeObj::TransposeObj(GraphObj *graph, Tensor input, Tensor output,
+                               vector<int> permute)
+        : OperatorObj(OpType::Transpose, {input}, {output})
+    {
+        auto rank = input->getRank();
+        if (permute.empty())
+        {
+            for (size_t i = 0; i < rank; ++i)
+            {
+                transposePermute[i] = i;
+            }
+        }
+        else
+        {
+            IT_ASSERT(rank == permute.size());
+            transposePermute = std::move(permute);
+        }
+        IT_ASSERT(checkValid(graph));
+    }
+
+    optional<vector<Shape>> TransposeObj::inferShape(const TensorVec &inputs)
+    {
+        const auto A = inputs[0];
+        auto input_dim = A->getDims();
+        auto output_dim = input_dim;
+        int rank = A->getRank();
+
+        // =================================== 作业 ===================================
+        // TODO:修改 output_dim,返回正确的 transpose 后的 shape
+        // REF: https://onnx.ai/onnx/operators/onnx__Transpose.html#transpose-21
+        // =================================== 作业 ===================================
+
+        return {{}};
+    }
+
+    std::string TransposeObj::toString() const
+    {
+        std::ostringstream os;
+        os << type.toString() << "[" << getGuid() << "]";
+        os << "(";
+        os << vecToString(inputs[0]->getDims()) << ",";
+        os << "input=" << inputs[0]->getGuid() << ",";
+        os << "output=" << outputs[0]->getGuid() << ")";
+        return os.str();
+    }
+}; // namespace infini
diff --git a/src/operators/unary.cc b/src/operators/unary.cc
new file mode 100644
index 0000000..e773506
--- /dev/null
+++ b/src/operators/unary.cc
@@ -0,0 +1,148 @@
+#include "operators/unary.h"
+
+namespace infini
+{
+    UnaryObj::UnaryObj(OpType type, GraphObj *graph, Tensor input, Tensor output)
+        : OperatorObj(type, {input}, {output})
+    {
+        IT_ASSERT(checkValid(graph));
+    }
+
+    optional<vector<Shape>> UnaryObj::inferShape(const TensorVec &inputs)
+    {
+        const auto A = inputs[0];
+        return {{A->getDims()}};
+    }
+
+    std::string UnaryObj::toString() const
+    {
+        std::ostringstream os;
+        os << type.toString() << "[" << getGuid() << "]";
+        os << "(";
+        os << vecToString(inputs[0]->getDims()) << ",";
+        os << "input=" << inputs[0]->getGuid() << ",";
+        os << "output=" << outputs[0]->getGuid() << ")";
+        return os.str();
+    }
+
+    ClipObj::ClipObj(GraphObj *graph, Tensor input, Tensor output,
+                     std::optional<float> min, std::optional<float> max)
+        : OperatorObj(OpType::Clip, {input}, {output}), minValue(min),
+          maxValue(max)
+    {
+        IT_ASSERT(checkValid(graph));
+    }
+
+    optional<vector<Shape>> ClipObj::inferShape(const TensorVec &inputs)
+    {
+        // =================================== 作业 ===================================
+        // TODO:返回经过 clip 操作后的 shape
+        // REF: https://onnx.ai/onnx/operators/onnx__Clip.html#clip-13
+        // =================================== 作业 ===================================
+        return {{}};
+    }
+
+    std::string ClipObj::toString() const
+    {
+        std::ostringstream os;
+        os << type.toString() << "[" << getGuid() << "]";
+        os << "(";
+        os << vecToString(inputs[0]->getDims()) << ",";
+        os << "input=" << inputs[0]->getGuid() << ",";
+        os << "output=" << outputs[0]->getGuid() << ")";
+        return os.str();
+    }
+
+    CastObj::CastObj(GraphObj *graph, Tensor input, Tensor output, CastType type)
+        : OperatorObj(OpType::Cast, {input}, {output}), castType(type)
+    {
+        IT_ASSERT(checkValid(graph));
+    }
+
+    vector<DataType> CastObj::inferDataType(const TensorVec &inputs) const
+    {
+        // =================================== 作业 ===================================
+        // TODO:返回经过 cast 操作后, 输出 tensor 的数目和数据类型
+        // REF_FILE: src/core/operator.cc
+        // REF: https://onnx.ai/onnx/operators/onnx__Cast.html#cast-21
+        // =================================== 作业 ===================================
+        return {};
+    }
+
+    optional<vector<Shape>> CastObj::inferShape(const TensorVec &inputs)
+    {
+        // =================================== 作业 ===================================
+        // TODO:返回经过 cast 操作后的 shape
+        // REF: https://onnx.ai/onnx/operators/onnx__Cast.html#cast-21
+        // =================================== 作业 ===================================
+        return {{}};
+    }
+
+    std::string CastObj::toString() const
+    {
+        std::ostringstream os;
+        os << type.toString() << "[" << getGuid() << "]";
+        os << "(";
+        os << "output=" << outputs[0]->getGuid() << ")";
+        return os.str();
+    }
+
+    DataType CastObj::getOutputDataType() const
+    {
+        switch (castType)
+        {
+        case CastType::Float2Float16:
+            return DataType::Float16;
+        case CastType::Float2Int64:
+            return DataType::Int64;
+        case CastType::Float2Int32:
+            return DataType::Int32;
+        case CastType::Float2Int16:
+            return DataType::Int16;
+        case CastType::Float2Int8:
+            return DataType::Int8;
+        case CastType::Int322Float:
+            return DataType::Float32;
+        case CastType::Int322Int8:
+            return DataType::Int8;
+        case CastType::Int322Int16:
+            return DataType::Int16;
+        case CastType::Int162Float:
+            return DataType::Float32;
+        case CastType::Int162Int32:
+            return DataType::Int32;
+        case CastType::Int82Float:
+            return DataType::Float32;
+        case CastType::Int82Int16:
+            return DataType::Int16;
+        case CastType::Int82Int32:
+            return DataType::Int32;
+        case CastType::Uint82Float:
+            return DataType::Float32;
+        case CastType::Uint82Int32:
+            return DataType::Int32;
+        case CastType::Uint82Int64:
+            return DataType::Int64;
+        case CastType::Int322Int64:
+            return DataType::Int64;
+        case CastType::Int642Int32:
+            return DataType::Int32;
+        case CastType::Int642Uint32:
+            return DataType::UInt32;
+        case CastType::Int642Float:
+            return DataType::Float32;
+        case CastType::Uint322Int64:
+            return DataType::Int64;
+        case CastType::Float162Float:
+            return DataType::Float32;
+        case CastType::BFloat162Float:
+            return DataType::Float32;
+        case CastType::Float2BFloat16:
+            return DataType::BFloat16;
+        case CastType::Float2Float:
+            return DataType::Float32;
+        default:
+            IT_TODO_HALT();
+        }
+    }
+}; // namespace infini
diff --git a/src/utils/exception.cc b/src/utils/exception.cc
new file mode 100644
index 0000000..228a39a
--- /dev/null
+++ b/src/utils/exception.cc
@@ -0,0 +1,5 @@
+#include "utils/exception.h"
+
+namespace infini {
+Exception::Exception(const std::string &msg) : std::runtime_error(msg) {}
+} // namespace infini
diff --git a/src/utils/operator_utils.cc b/src/utils/operator_utils.cc
new file mode 100644
index 0000000..edbd2c8
--- /dev/null
+++ b/src/utils/operator_utils.cc
@@ -0,0 +1,69 @@
+#include "utils/operator_utils.h"
+#include "core/runtime.h"
+
+namespace infini {
+
+Shape infer_broadcast(const Shape &A, const Shape &B) {
+
+    // =================================== 作业 ===================================
+    // TODO:对 A 和 B 进行双向广播,返回广播后的形状。
+    // REF: https://github.com/onnx/onnx/blob/main/docs/Broadcasting.md
+    // =================================== 作业 ===================================
+    
+    return {};
+}
+
+int get_real_axis(const int &axis, const int &rank) {
+    IT_ASSERT(rank >= 1);
+    IT_ASSERT(axis >= -rank && axis <= (rank - 1));
+    int newAxis;
+    if (axis < 0) {
+        newAxis = rank + axis;
+    } else {
+        newAxis = axis;
+    }
+    return newAxis;
+}
+
+Shape locate_index(size_t inputN, const Shape &shape) {
+    Shape ans(shape.size());
+    auto i = ans.rbegin();
+    auto j = shape.rbegin(), ej = shape.rend();
+    while (j != ej) {
+        auto div = std::div(inputN, *j++);
+        *i++ = div.rem;
+        inputN = div.quot;
+    }
+    return ans;
+}
+
+size_t delocate_index(const Shape &shapeIndex, const Shape &shape,
+                      const Shape &stride) {
+    size_t ans = 0;
+    Shape index(shapeIndex.size());
+    IT_ASSERT(shapeIndex.size() == shape.size());
+    IT_ASSERT(shape.size() == stride.size());
+    for (size_t i = 0; i < shape.size(); ++i) {
+        index[i] = shapeIndex[i] % shape[i];
+        ans += index[i] * stride[i];
+    }
+    return ans;
+}
+
+std::string device_to_str(Device device) {
+    std::string deviceStr;
+    switch (device) {
+    case Device::CPU:
+        return "CPU";
+    default:
+        IT_TODO_HALT();
+    }
+}
+
+std::string get_kernel_attrs_str(const KernelAttrs &kernelAttrs) {
+    std::string deviceStr = device_to_str(std::get<0>(kernelAttrs));
+    std::string opStr = OpType(std::get<1>(kernelAttrs)).toString();
+    return deviceStr + ", " + opStr;
+}
+
+} // namespace infini
diff --git a/test/core/test_allocator.cc b/test/core/test_allocator.cc
new file mode 100644
index 0000000..0515edc
--- /dev/null
+++ b/test/core/test_allocator.cc
@@ -0,0 +1,74 @@
+#include "core/graph.h"
+#include "core/kernel.h"
+#include "core/runtime.h"
+#include "operators/unary.h"
+
+#include "test.h"
+
+namespace infini
+{
+    TEST(Allocator, testAlloc)
+    {
+        Shape shape = Shape{1, 2, 2, 3};
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        Tensor a = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor b = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor c = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor d = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Allocator allocator = Allocator(runtime);
+        // allocate a->b->c
+        size_t offsetA = allocator.alloc(a->getBytes());
+        size_t offsetB = allocator.alloc(b->getBytes());
+        size_t offsetC = allocator.alloc(c->getBytes());
+        // free b, then allocate d
+        allocator.free(offsetB, b->getBytes());
+        size_t offsetD = allocator.alloc(d->getBytes());
+        // expected to be a->d->c
+        EXPECT_EQ(offsetB, offsetD);
+        ASSERT_FALSE(offsetA == 0 && offsetB == 0 && offsetC == 0 && offsetD == 0);
+    }
+
+    TEST(Allocator, testAllocWithEndFreeBlock)
+    {
+        Shape shape = Shape{1, 2, 2, 3};
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        Tensor a = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor b = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor c = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor d =
+            make_ref<TensorObj>(Shape{2, 2, 2, 3}, DataType::Float32, runtime);
+        Allocator allocator = Allocator(runtime);
+        // allocate a->b->c
+        allocator.alloc(a->getBytes());
+        allocator.alloc(b->getBytes());
+        size_t offsetC = allocator.alloc(c->getBytes());
+        allocator.info();
+        // free c, then allocate d
+        allocator.free(offsetC, c->getBytes());
+        size_t offsetD = allocator.alloc(d->getBytes());
+        allocator.info();
+        // expected to be a->b->d, with no free block between b and c
+        EXPECT_EQ(offsetC, offsetD);
+    }
+
+    TEST(Allocator, testGetPtr)
+    {
+        Shape shape = Shape{1, 2, 2, 3};
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        Tensor a = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor b = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor c = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Tensor d = make_ref<TensorObj>(shape, DataType::Float32, runtime);
+        Allocator allocator = Allocator(runtime);
+        // allocate a->b->c->d
+        allocator.alloc(a->getBytes());
+        allocator.alloc(b->getBytes());
+        allocator.alloc(c->getBytes());
+        allocator.alloc(d->getBytes());
+        // multiple calls to the getPtr() function should return the same pointer
+        void *ptr1 = allocator.getPtr();
+        void *ptr2 = allocator.getPtr();
+        EXPECT_EQ(ptr1, ptr2);
+    }
+
+} // namespace infini
diff --git a/test/kernels/nativecpu/test_nativecpu_concat.cc b/test/kernels/nativecpu/test_nativecpu_concat.cc
new file mode 100644
index 0000000..fc87fb1
--- /dev/null
+++ b/test/kernels/nativecpu/test_nativecpu_concat.cc
@@ -0,0 +1,28 @@
+#include "core/graph.h"
+#include "core/runtime.h"
+#include "operators/concat.h"
+
+#include "test.h"
+
+namespace infini {
+
+TEST(Concat, NativeCpu) {
+    Runtime runtime = NativeCpuRuntimeObj::getInstance();
+    Graph g = make_ref<GraphObj>(runtime);
+
+    auto t1 = g->addTensor({2, 2, 3, 1}, DataType::Float32);
+    auto t2 = g->addTensor({2, 2, 1, 1}, DataType::Float32);
+    auto t3 = g->addTensor({2, 2, 2, 1}, DataType::Float32);
+    auto op = g->addOp<ConcatObj>(TensorVec{t1, t2, t3}, nullptr, 2);
+    g->dataMalloc();
+    t1->setData(IncrementalGenerator());
+    t2->setData(OneGenerator());
+    t3->setData(OneGenerator());
+
+    runtime->run(g);
+    EXPECT_TRUE(op->getOutput()->equalData(
+        vector<float>{0, 1, 2, 1, 1, 1, 3, 4,  5,  1, 1, 1,
+                      6, 7, 8, 1, 1, 1, 9, 10, 11, 1, 1, 1}));
+}
+
+} // namespace infini
diff --git a/test/kernels/nativecpu/test_nativecpu_elementwise.cc b/test/kernels/nativecpu/test_nativecpu_elementwise.cc
new file mode 100644
index 0000000..c6ef191
--- /dev/null
+++ b/test/kernels/nativecpu/test_nativecpu_elementwise.cc
@@ -0,0 +1,44 @@
+#include "core/graph.h"
+#include "core/runtime.h"
+#include "operators/element_wise.h"
+
+#include "test.h"
+
+namespace infini {
+
+using ExpectOutput = vector<float>;
+template <class T>
+void testElementWiseNativeCpu(
+    const std::function<void(void *, size_t, DataType)> &generator1,
+    const std::function<void(void *, size_t, DataType)> &generator2,
+    const Shape &shape1, const Shape &shape2, const ExpectOutput &ansVec) {
+    Runtime runtime = NativeCpuRuntimeObj::getInstance();
+    Graph g = make_ref<GraphObj>(runtime);
+    auto t1 = g->addTensor(shape1, DataType::Float32);
+    auto t2 = g->addTensor(shape2, DataType::Float32);
+
+    auto op = g->addOp<T>(t1, t2, nullptr);
+    g->dataMalloc();
+    t1->setData(generator1);
+    t2->setData(generator2);
+
+    runtime->run(g);
+    EXPECT_TRUE(op->getOutput()->equalData(ansVec));
+}
+
+TEST(ElementWise, NativeCpu) {
+    testElementWiseNativeCpu<AddObj>(
+        IncrementalGenerator(), IncrementalGenerator(), Shape{1, 2, 2, 3, 1},
+        Shape{2, 1, 1}, ExpectOutput{0, 1, 2, 4, 5, 6, 6, 7, 8, 10, 11, 12});
+    testElementWiseNativeCpu<MulObj>(
+        IncrementalGenerator(), IncrementalGenerator(), Shape{1, 2, 2, 3, 1},
+        Shape{2, 1, 1}, ExpectOutput{0, 0, 0, 3, 4, 5, 0, 0, 0, 9, 10, 11});
+    testElementWiseNativeCpu<SubObj>(
+        IncrementalGenerator(), IncrementalGenerator(), Shape{1, 2, 2, 3, 1},
+        Shape{2, 1, 1}, ExpectOutput{0, 1, 2, 2, 3, 4, 6, 7, 8, 8, 9, 10});
+    testElementWiseNativeCpu<DivObj>(
+        IncrementalGenerator(), OneGenerator(), Shape{1, 2, 2, 3, 1},
+        Shape{2, 1, 1}, ExpectOutput{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
+}
+
+} // namespace infini
diff --git a/test/kernels/nativecpu/test_nativecpu_transpose.cc b/test/kernels/nativecpu/test_nativecpu_transpose.cc
new file mode 100644
index 0000000..501d402
--- /dev/null
+++ b/test/kernels/nativecpu/test_nativecpu_transpose.cc
@@ -0,0 +1,27 @@
+#include "core/graph.h"
+#include "core/kernel.h"
+#include "core/runtime.h"
+#include "operators/transpose.h"
+
+#include "test.h"
+
+namespace infini {
+
+TEST(Transpose, NativeCpu) {
+    Runtime runtime = NativeCpuRuntimeObj::getInstance();
+    Graph g = make_ref<GraphObj>(runtime);
+
+    Shape permute = {0, 2, 1, 3};
+    auto input = g->addTensor({1, 2, 3, 4}, DataType::Float32);
+    auto op = g->addOp<TransposeObj>(input, nullptr, permute);
+    g->dataMalloc();
+    input->setData(IncrementalGenerator());
+
+    runtime->run(g);
+
+    EXPECT_TRUE(op->getOutput(0)->equalData(vector<float>{0, 1, 2, 3, 12, 13, 14, 15,
+                                                          4, 5, 6, 7, 16, 17, 18, 19,
+                                                          8, 9, 10, 11, 20, 21, 22, 23}));
+}
+
+} // namespace infini
diff --git a/test/operators/test_cast.cc b/test/operators/test_cast.cc
new file mode 100644
index 0000000..3177751
--- /dev/null
+++ b/test/operators/test_cast.cc
@@ -0,0 +1,23 @@
+#include "core/graph.h"
+#include "core/kernel.h"
+#include "core/runtime.h"
+#include "operators/unary.h"
+
+#include "test.h"
+
+namespace infini
+{
+
+    TEST(Cast, ShapeInference)
+    {
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({2}, DataType::Float32);
+            auto op = g->addOp<CastObj>(i0, nullptr, CastType::Float2Float16);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2}));
+            EXPECT_EQ(op->getOutDType(), (DataType::Float16));
+        }
+    }
+
+} // namespace infini
diff --git a/test/operators/test_clip.cc b/test/operators/test_clip.cc
new file mode 100644
index 0000000..bd4e07f
--- /dev/null
+++ b/test/operators/test_clip.cc
@@ -0,0 +1,23 @@
+#include "core/graph.h"
+#include "core/kernel.h"
+#include "core/runtime.h"
+#include "operators/unary.h"
+
+#include "test.h"
+
+namespace infini {
+
+    TEST(Clip, ShapeInference)
+    {
+        // Runtime
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        Graph g = make_ref<GraphObj>(runtime);
+        Tensor i0 = g->addTensor({1, 2, 2, 3}, DataType::Float32);
+        float min = 1.0;
+        float max = 4.0;
+        auto op = g->addOp<ClipObj>(i0, nullptr, min, max);
+        EXPECT_EQ(op->getOutput()->getDims(), (Shape{1, 2, 2, 3}));
+        EXPECT_EQ(op->getOutDType(), (DataType::Float32));
+    }
+
+} // namespace infini
diff --git a/test/operators/test_concat.cc b/test/operators/test_concat.cc
new file mode 100644
index 0000000..8984b9f
--- /dev/null
+++ b/test/operators/test_concat.cc
@@ -0,0 +1,16 @@
+#include "core/graph.h"
+#include "core/runtime.h"
+#include "operators/concat.h"
+#include "test.h"
+
+namespace infini {
+TEST(Concat, ShapeInfer) {
+    Runtime runtime = NativeCpuRuntimeObj::getInstance();
+    Graph g = make_ref<GraphObj>(runtime);
+    auto t1 = g->addTensor({1, 3, 2, 4}, DataType::Float32);
+    auto t2 = g->addTensor({1, 3, 2, 5}, DataType::Float32);
+
+    auto op = g->addOp<ConcatObj>(TensorVec{t1, t2}, nullptr, 3);
+    EXPECT_EQ(op->getOutput()->getDims(), (Shape{1, 3, 2, 9}));
+}
+} // namespace infini
diff --git a/test/operators/test_element_wise.cc b/test/operators/test_element_wise.cc
new file mode 100644
index 0000000..f4fdd66
--- /dev/null
+++ b/test/operators/test_element_wise.cc
@@ -0,0 +1,66 @@
+#include "core/graph.h"
+#include "core/kernel.h"
+#include "core/runtime.h"
+#include "operators/element_wise.h"
+
+#include "test.h"
+
+namespace infini {
+
+    TEST(ElementWise, ShapeInference)
+    {
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({2, 3, 3, 4}, DataType::UInt32);
+            Tensor i1 = g->addTensor({2, 3, 3, 4}, DataType::UInt32);
+            auto op = g->addOp<AddObj>(i0, i1, nullptr);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 3, 3, 4}));
+        }
+    }
+
+    TEST(ElementWise, Broadcasting)
+    {
+        Runtime runtime = NativeCpuRuntimeObj::getInstance();
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({2, 3, 4, 5}, DataType::UInt32);
+            Tensor i1 = g->addTensor({}, DataType::UInt32);
+            auto op = g->addOp<AddObj>(i0, i1, nullptr);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 3, 4, 5}));
+        }
+
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({2, 3, 4, 5}, DataType::UInt32);
+            Tensor i1 = g->addTensor({5}, DataType::UInt32);
+            auto op = g->addOp<AddObj>(i0, i1, nullptr);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 3, 4, 5}));
+        }
+
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({4, 5}, DataType::UInt32);
+            Tensor i1 = g->addTensor({2, 3, 4, 5}, DataType::UInt32);
+            auto op = g->addOp<AddObj>(i0, i1, nullptr);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 3, 4, 5}));
+        }
+
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({1, 4, 5}, DataType::UInt32);
+            Tensor i1 = g->addTensor({2, 3, 1, 1}, DataType::UInt32);
+            auto op = g->addOp<AddObj>(i0, i1, nullptr);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 3, 4, 5}));
+        }
+
+        {
+            Graph g = make_ref<GraphObj>(runtime);
+            Tensor i0 = g->addTensor({3, 4, 5}, DataType::UInt32);
+            Tensor i1 = g->addTensor({2, 1, 1, 1}, DataType::UInt32);
+            auto op = g->addOp<AddObj>(i0, i1, nullptr);
+            EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 3, 4, 5}));
+        }
+    }
+
+} // namespace infini
diff --git a/test/operators/test_transpose.cc b/test/operators/test_transpose.cc
new file mode 100644
index 0000000..1c12b79
--- /dev/null
+++ b/test/operators/test_transpose.cc
@@ -0,0 +1,32 @@
+#include "core/graph.h"
+#include "core/kernel.h"
+#include "core/runtime.h"
+#include "operators/transpose.h"
+
+#include "test.h"
+
+namespace infini {
+
+TEST(Transpose, ShapeInference) {
+    Runtime runtime = NativeCpuRuntimeObj::getInstance();
+    {
+        Graph g = make_ref<GraphObj>(runtime);
+        Tensor i = g->addTensor({1, 2, 3, 4}, DataType::Float32);
+        auto op = g->addOp<TransposeObj>(i, nullptr, Shape{0, 1, 2, 3});
+        EXPECT_EQ(op->getOutput()->getDims(), (Shape{1, 2, 3, 4}));
+    }
+    {
+        Graph g = make_ref<GraphObj>(runtime);
+        Tensor i = g->addTensor({1, 2, 3, 4}, DataType::Float32);
+        auto op = g->addOp<TransposeObj>(i, nullptr, Shape{0, 2, 1, 3});
+        EXPECT_EQ(op->getOutput()->getDims(), (Shape{1, 3, 2, 4}));
+    }
+    {
+        Graph g = make_ref<GraphObj>(runtime);
+        Tensor i = g->addTensor({2, 3, 4}, DataType::Float32);
+        auto op = g->addOp<TransposeObj>(i, nullptr, Shape{0, 2, 1});
+        EXPECT_EQ(op->getOutput()->getDims(), (Shape{2, 4, 3}));
+    }
+}
+
+} // namespace infini