text: #ifndef Corrade_TestSuite_Tester_h
  #define Corrade_TestSuite_Tester_h
  /*
      This file is part of Corrade.
  
      Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
                  2017, 2018, 2019 Vladimír Vondruš <mosra@centrum.cz>
  
      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.
  */
  
  /** @file
   * @brief Class @ref Corrade::TestSuite::Tester, macros @ref CORRADE_TEST_MAIN(), @ref CORRADE_VERIFY(), @ref CORRADE_COMPARE(), @ref CORRADE_COMPARE_AS(), @ref CORRADE_COMPARE_WITH(), @ref CORRADE_EXPECT_FAIL(), @ref CORRADE_EXPECT_FAIL_IF(), @ref CORRADE_SKIP(), @ref CORRADE_ITERATION(), @ref CORRADE_BENCHMARK()
   */
  
  #include <initializer_list>
  
  #include "Corrade/Containers/Pointer.h"
  #include "Corrade/TestSuite/Comparator.h"
  #include "Corrade/TestSuite/Compare/FloatingPoint.h"
  #include "Corrade/TestSuite/visibility.h"
  #include "Corrade/Utility/Debug.h"
  #include "Corrade/Utility/Macros.h"
  #include "Corrade/Utility/StlForwardString.h"
  
  #ifdef CORRADE_TARGET_EMSCRIPTEN
  #include <cstdlib>
  #endif
  
  namespace Corrade { namespace TestSuite {
  
  namespace Implementation {
      /* First try to convert the actual type to expected, if that fails, try
         std::common_type */
      template<class Actual, class Expected, bool = std::is_convertible<Actual, Expected>::value> struct CommonType {
          typedef Expected Type;
      };
      template<class Actual, class Expected> struct CommonType<Actual, Expected, false> {
          typedef typename std::common_type<Actual, Expected>::type Type;
      };
  }
  
  /**
  @brief Base class for tests and benchmarks
  
  Supports colored output, instanced (or data-driven) tests, repeated tests (e.g.
  for testing race conditions) and benchmarks, which can either use one of the
  builtin measurement functions (such as wall time, CPU time or CPU cycle count)
  or any user-provided custom measurement function (for example measuring
  allocations, memory usage, GPU timings etc.). In addition, the behavior of the
  test execution can be configured  via many command-line and environment
  options.
  
  Make sure to first go through the @ref testsuite tutorial for initial overview
  and step-by-step introduction. Below is a more detailed description of all
  provided functionality.
  
  @section TestSuite-Tester-basic Basic testing workflow
  
  A test starts with deriving the @ref Tester class. The test cases are
  parameter-less @cpp void @ce member functions that are added using @ref addTests()
  in the constructor and the @cpp main() @ce function is created using
  @ref CORRADE_TEST_MAIN(). The goal is to have as little boilerplate as
  possible, thus the test usually  consists of only one `*.cpp` file with no
  header and the derived type is a @cpp struct @ce to avoid having to write
  @cpp public @ce keywords. It's also advised to wrap everything except the
  @ref CORRADE_TEST_MAIN() macro in an unnamed namespace, as that will make the
  compiler tell you about accidentally unused test cases or variables.
  
  @snippet testsuite-basic.cpp 0
  
  The above gives the following output:
  
  @include testsuite-basic.ansi
  
  Actual testing is done via various @ref CORRADE_VERIFY(), @ref CORRADE_COMPARE(),
  @ref CORRADE_COMPARE_AS() and other macros. If some comparison in given test
  case fails, a @cb{.ansi} [1;31mFAIL @ce with concrete file, line and
  additional diagnostic is printed to the output and the test case is exited
  without executing the remaining statements. Otherwise, if all comparisons in
  given test case pass, an @cb{.ansi} [1;39mOK @ce is printed. The main
  difference between these macros is the kind of diagnostic output they print
  when comparison fails --- for example a simple expression failure reported by
  @ref CORRADE_VERIFY() is enough when checking for non-@cpp nullptr @ce value,
  but for comparing two strings you may want to use @ref CORRADE_COMPARE() so you
  can not only see that they differ, but also *how* they differ.
  
  Additionally there are @ref CORRADE_SKIP(), @ref CORRADE_EXPECT_FAIL() and
  @ref CORRADE_EXPECT_FAIL_IF() control flow helpers that allow you to say for
  example that a particular test was skipped due to missing functionality on
  given platform (printing a @cb{.ansi} [1;39mSKIP @ce on output and exiting the
  test case right after the statement) or documenting that some algorithm
  produces incorrect result due to a bug, printing an @cb{.ansi} [1;33mXFAIL @ce.
  Passing a test while failure is expected is treated as an error
  (@cb{.ansi} [1;31mXPASS @ce), which can be helpful to ensure the assumptions
  in the tests don't get stale. Expected failures can be also disabled globally
  via a command-line option `--no-xfail` or via environment variable,
  @ref TestSuite-Tester-command-line "see below".
  
  The only reason why those are macros and not member functions is the ability to
  gather class/function/file/line/expression information via the preprocessor for
  printing the test output and exact location of possible test failure. If none
  of these macros is encountered when running the test case, the test case is
  reported as invalid, with @cb{.ansi} [1;33m? @ce on output.
  
  The test cases are numbered on the output and those numbers can be used on the
  command-line to whitelist/blacklist the test cases with `--only`/`--skip`,
  randomly reorder them using `--shuffle` and more,
  @ref TestSuite-Tester-command-line "see below" for details. In total, when all
  test cases pass, the executable exits with `0` return code, in case of failure
  or invalid test case it exits with `1` to make it possible to run the tests in
  batch (such as CMake CTest). By default, after a failure, the testing continues
  with the other test cases, you can abort after first failure using
  `--abort-on-fail` command-line option.
  
  Useful but not immediately obvious is the possibility to use templated member
  functions as test cases, for example when testing a certain algorithm on
  different data types:
  
  @snippet testsuite-templated.cpp 0
  
  And the corresponding output:
  
  @include testsuite-templated.ansi
  
  This works with all `add*()` functions though please note that current C++11
  compilers (at least GCC and Clang) are not able to properly detect class type
  when passing only templated functions to it, so you may need to specify the
  type explicitly. Also, there is no easy and portable way to get function name
  with template parameters so by default it will be just the function name, but
  you can call @ref setTestCaseName() to specify a full name.
  
  @section TestSuite-Tester-instanced Instanced tests
  
  Often you have an algorithm which you need to test on a variety of inputs or
  corner cases. One solution is to use a for-cycle inside the test case to test
  on all inputs, but then the diagnostic on error will not report which input is
  to blame. Another solution is to duplicate the test case multiple times for all
  the different inputs, but that becomes a maintenance nightmare pretty quickly.
  Making the function with a non-type template parameter is also a solution, but
  that's not possible to do for all types and with huge input sizes it is often
  not worth the increased compilation times. Fortunately, there is an
  @ref addInstancedTests() that comes for the rescue:
  
  @snippet testsuite-instanced.cpp 0
  
  Corresponding output:
  
  @include testsuite-instanced.ansi
  
  The tester class just gives you an instance index via @ref testCaseInstanceId()
  and it's up to you whether you use it as an offset to some data array or
  generate an input using it, the above example is just a hint how one might use
  it. Each instance is printed to the output separately and if one instance
  fails, it doesn't stop the other instances from being executed. Similarly to
  the templated tests, @ref setTestCaseDescription() allows you to set a
  human-readable description of given instance. If not called, the instances are
  just numbered in the output.
  
  @section TestSuite-Tester-iteration-annotations Testing in a loop
  
  While instanced tests are usually the go-to solution when testing on a larger
  set of data, sometimes you need to loop over a few values and check them one by
  one. When such test fails, it's often hard to know which particular value
  caused the failure. To fix that, you can use the @ref CORRADE_ITERATION() macro
  to annotate current iteration in case of a failure. It works with any type
  printable via @ref Utility::Debug and handles nested loops as well. Silly
  example:
  
  @snippet testsuite-iteration.cpp 0
  
  On failure, the iteration value(s) will be printed next to the file/line info:
  
  @include testsuite-iteration.ansi
  
  This macro isn't limited to just loops, it can be used to provide more context
  to just any check. See also @ref Compare::Container for a convenient way of
  comparing container contents.
  
  @section TestSuite-Tester-repeated Repeated tests
  
  A complementary feature to instanced tests are repeated tests using
  @ref addRepeatedTests(), useful for example to repeatedly call one function
  10000 times to increase probability of potential race conditions. The
  difference from instanced tests is that all repeats are treated as executing
  the same code and thus only the overall result is reported in the output. Also
  unlike instanced tests, if a particular repeat fails, no further repeats are
  executed. The test output contains number of executed repeats after the test
  case name, prefixed by @cb{.ansi} [1;39m@ @ce. Example of testing race
  conditions with multiple threads accessing the same variable:
  
  @snippet testsuite-repeated.cpp 0
  
  Depending on various factors, here is one possible output:
  
  @include testsuite-repeated.ansi
  
  Similarly to @ref testCaseInstanceId() there is @ref testCaseRepeatId() which
  gives repeat index. Use with care, however, as the repeated tests are assumed
  to execute the same code every time. On
  @ref TestSuite-Tester-command-line "the command line" it is possible to
  increase repeat count via `--repeat-every`. In addition there is `--repeat-all`
  which behaves as like all `add*()` functions in the constructor were called
  multiple times in a loop. Combined with `--shuffle` this can be used to run the
  test cases multiple times in a random order to uncover potential unwanted
  interactions and order-dependent bugs.
  
  It's also possible to combine instanced and repeated tests using
  @ref addRepeatedInstancedTests().
  
  @section TestSuite-Tester-advanced-comparisons Advanced comparisons
  
  While the diagnostic provided by @ref CORRADE_COMPARE() is definitely better
  than just knowing that something failed, the @ref CORRADE_COMPARE_AS() and
  @ref CORRADE_COMPARE_WITH() macros allow for advanced comparison features in
  specialized cases. The @ref Compare namespace contains various builtin
  comparators, some of which are listed below. It's also possible to implement
  custom comparators for your own use cases --- see the @ref Comparator class for
  details.
  
  <ul>
  <li>
  @ref Compare::Container and @ref Compare::SortedContainer can be used for
  convenient comparison of large containers. Compared to plain
  @ref CORRADE_COMPARE() Its diagnostic will show where exactly the containers
  differ, which becomes useful with large data sizes:
  
  @snippet TestSuite.cpp Compare-Container
  </li>
  <li>
  @ref Compare::File, @ref Compare::FileToString and @ref Compare::StringToFile
  allow you to compare files without having to manually read them:
  
  @snippet TestSuite.cpp Compare-File
  </li>
  <li>
  @ref Compare::Less, @ref Compare::Around and others from the
  @ref Corrade/TestSuite/Compare/Numeric.h header allow you to do numeric
  comparisons that again provide better failure reporting compared to checking an
  expression result with @ref CORRADE_VERIFY():
  
  @snippet TestSuite.cpp Compare-around-just-one
  </li>
  <li>
  Finally, [Magnum](https://magnum.graphics) has a
  @m_class{m-doc-external} [DebugTools::CompareImage](https://doc.magnum.graphics/magnum/classMagnum_1_1DebugTools_1_1CompareImage.html)
  that's able to fuzzy-compare two images pixel-by-pixel and visualize the
  difference as an ASCII art directly in the console.
  </li>
  </ul>
  
  @section TestSuite-Tester-save-diagnostic Saving diagnostic files
  
  On comparison failure, it's sometimes desirable to inspect the generated data
  with an external tool. Or, in case the expected test data need to be updated,
  it's easier to copy over the generated data to the original file than applying
  changes manually. To make this easier without needing to add file-saving to the
  test itself, pass a path to the `--save-diagnostic`
  @ref TestSuite-Tester-command-line "command-line option". Comparators that
  operate with files (such as @ref Compare::File or @ref Compare::StringToFile)
  will then use this path to save the actual data under the same filename as the
  expected file, notifying you about the operation with a
  @cb{.ansi} [1;32mSAVED @ce message:
  
  @include testsuite-save-diagnostic.ansi
  
  Note that this functionality is not restricted to just saving the actual
  compared data (or to comparison failures) --- third-party comparators can use
  it for generating diffs or providing further diagnostic meant to be viewed
  externally. See the @ref TestSuite-Comparator-save-diagnostic "Comparator"
  class for further information.
  
  @section TestSuite-Tester-benchmark Benchmarks
  
  Besides verifying code correctness, it's possible to measure code performance.
  Unlike correctness tests, the benchmark results are hard to reason about using
  only automated means, so there are no macros for verifying benchmark results
  and instead the measured values are just printed to the output for users to
  see. Benchmarks can be added using @ref addBenchmarks(), the actual benchmark
  loop is marked by @ref CORRADE_BENCHMARK() and the results are printed to
  output with @cb{.ansi} [1;39mBENCH @ce identifier. Example benchmark comparing
  performance of inverse square root implementations:
  
  @snippet testsuite-benchmark.cpp 0
  
  Note that it's not an error to add one test/benchmark multiple times --- here
  it is used to have the same code benchmarked with different timers. Possible
  output:
  
  @include testsuite-benchmark.ansi
  
  The number passed to @ref addBenchmarks() is equivalent to repeat count passed
  to @ref addRepeatedTests() and specifies measurement sample count. The number
  passed to @ref CORRADE_BENCHMARK() is number of iterations of the inner loop in
  one sample measurement to amortize the overhead and error caused by clock
  precision --- the faster the measured code is the more iterations it needs. The
  measured value is then divided by that number to represent cost of a single
  iteration. The @ref testCaseRepeatId() returns current sample index and can be
  used to give some input variation to the test. By default the benchmarks
  measure wall clock time, see @ref BenchmarkType for other types of builtin
  benchmarks. The default benchmark type can be also overriden
  @ref TestSuite-Tester-command-line "on the command-line" via `--benchmark`.
  
  It's possible to use all @ref CORRADE_VERIFY(), @ref CORRADE_COMPARE() etc.
  verification macros inside the benchmark to check pre/post-conditions. If one
  of them fails, the benchmark is treated on output just like failing test, with
  no benchmark results being printed out. Keep in mind, however, that those
  macros have some overhead, so try to not use them inside the benchmark loop.
  
  The benchmark output is calculated from all samples except the first discarded
  samples. By default that's one sample, `--benchmark-discard` and `--repeat-every`
  @ref TestSuite-Tester-command-line "command-line options" can be used to
  override how many samples are taken and how many of them are discarded at
  first. In the output, the used sample count and sample size is printed after
  test case name, prefixed with `@`. The output contains mean value and a sample
  standard deviation, calculated as: @f[
      \begin{array}{rcl}
          \bar{x} & = & \dfrac{1}{N} \sum\limits_{i=1}^N x_i \\ \\
          \sigma_x & = & \sqrt{\dfrac{1}{N-1} \sum\limits_{i=1}^N \left( x_i - \bar{x} \right)^2}
      \end{array}
  @f]
  
  Different benchmark type have different units, time values are displayed in
  `ns`, `µs`, `ms` and `s`, dimensionless count is suffixed by `k`, `M` or `G`
  indicating thousands, millions and billions, instructions with `I`, `kI`, `MI`
  and `GI`, cycles with `C`, `kC`, `MC` and `GC` and memory in `B`, `kB`, `MB`
  and `GB`. In case of memory the prefixes are multiples of 1024 instead of 1000.
  For easier visual recognition of the values, by default the sample standard
  deviation is colored yellow if it is larger than 5% of the absolute value of
  the mean and red if it is larger than 25% of the absolute value of the mean.
  This can be overriden @ref TestSuite-Tester-command-line "on the command-line"
  via `--benchmark-yellow` and `--benchmark-red`.
  
  It's possible to have instanced benchmarks as well, see
  @ref addInstancedBenchmarks().
  
  @section TestSuite-Tester-benchmark-custom Custom benchmarks
  
  It's possible to specify a custom pair of functions for intiating the benchmark
  and returning the result using @ref addCustomBenchmarks(). The benchmark end
  function returns an unsigned 64-bit integer indicating measured amount in units
  given by @ref BenchmarkUnits. To further describe the value being measured you
  can call @ref setBenchmarkName() in the benchmark begin function. Contrived
  example of benchmarking number of copies when using @ref std::vector::push_back():
  
  @snippet testsuite-benchmark-custom.cpp 0
  
  Running the benchmark shows that calling @ref std::vector::push_back() "push_back()"
  for 10 thousand elements actually causes the copy constructor to be called 26
  thousand times:
  
  @include testsuite-benchmark-custom.ansi
  
  @section TestSuite-Tester-setup-teardown Specifying setup/teardown routines
  
  While the common practice in C++ is to use RAII for resource lifetime
  management, sometimes you may need to execute arbitrary code at the beginning
  and end of each test case. For this, all @ref addTests(),
  @ref addInstancedTests(), @ref addRepeatedTests(), @ref addRepeatedInstancedTests(),
  @ref addBenchmarks(), @ref addInstancedBenchmarks(), @ref addCustomBenchmarks()
  and @ref addCustomInstancedBenchmarks() have an overload that is additionally
  taking a pair of parameter-less @cpp void @ce functions for setup and teardown.
  Both functions are called before and after each test case run, independently on
  whether the test case passed or failed.
  
  @section TestSuite-Tester-command-line Command-line options
  
  Command-line options that make sense to be set globally for multiple test cases
  are also configurable via environment variables for greater flexibility when
  for example running the tests in a batch via `ctest`.
  
  Usage:
  
  @code{.shell-session}
  ./my-test [-h|--help] [-c|--color on|off|auto] [--skip "N1 N2..."]
      [--skip-tests] [--skip-benchmarks] [--only "N1 N2..."] [--shuffle]
      [--repeat-every N] [--repeat-all N] [--abort-on-fail] [--no-xfail]
      [--save-diagnostic PATH] [--verbose] [--benchmark TYPE]
      [--benchmark-discard N] [--benchmark-yellow N] [--benchmark-red N]
  @endcode
  
  Arguments:
  
  -   `-h`, `--help` --- display this help message and exit
  -   `-c`, `--color on|off|auto` --- colored output (environment:
      `CORRADE_TEST_COLOR`, default: `auto`). The `auto` option enables color
      output in case an interactive terminal is detected. Note that on Windows it
      is possible to output colors only directly to an interactive terminal
      unless @ref CORRADE_UTILITY_USE_ANSI_COLORS is defined.
  -   `--skip "N1 N2..."` --- skip test cases with given numbers
  -   `--skip-tests` --- skip all tests (environment:
      `CORRADE_TEST_SKIP_TESTS=ON|OFF`)
  -   `--skip-benchmarks` --- skip all benchmarks (environment:
      `CORRADE_TEST_SKIP_BENCHMARKS=ON|OFF`)
  -   `--only "N1 N2..."` --- run only test cases with given numbers
  -   `--shuffle` --- randomly shuffle test case order (environment:
      `CORRADE_TEST_SHUFFLE=ON|OFF`)
  -   `--repeat-every N` --- repeat every test case N times (environment:
      `CORRADE_TEST_REPEAT_EVERY`, default: `1`)
  -   `--repeat-all N` --- repeat all test cases N times (environment:
      `CORRADE_TEST_REPEAT_ALL`, default: `1`)
  -   `--abort-on-fail` --- abort after first failure (environment:
      `CORRADE_TEST_ABORT_ON_FAIL=ON|OFF`)
  -   `--no-xfail` --- disallow expected failures (environment:
      `CORRADE_TEST_NO_XFAIL=ON|OFF`)
  -   `--save-diagnostic PATH` --- save diagnostic files to given path
      (environment: `CORRADE_TEST_SAVE_DIAGNOSTIC`)
  -   `-v`, `--verbose` --- enable verbose output (environment:
      `CORRADE_TEST_VERBOSE`)
  -   `--benchmark TYPE` --- default benchmark type (environment:
      `CORRADE_TEST_BENCHMARK`). Supported benchmark types:
      -   `wall-time` --- wall time spent
      -   `cpu-time` --- CPU time spent
      -   `cpu-cycles` --- CPU cycles spent (x86 only, gives zero result
          elsewhere)
  -   `--benchmark-discard N` --- discard first N measurements of each benchmark
      (environment: `CORRADE_TEST_BENCHMARK_DISCARD`, default: `1`)
  -   `--benchmark-yellow N` --- deviation threshold for marking benchmark yellow
      (environment: `CORRADE_TEST_BENCHMARK_YELLOW`, default: `0.05`)
  -   `--benchmark-red N` --- deviation threshold for marking benchmark red
      (environment: `CORRADE_TEST_BENCHMARK_RED`, default: `0.25`)
  
  @section TestSuite-Tester-running Compiling and running tests
  
  In general, just compiling the executable and linking it to the TestSuite
  library is enough, no further setup is needed. When running, the test produces
  output to standard output / standard error and exits with non-zero code in case
  of a test failure.
  
  @subsection TestSuite-Tester-running-cmake Using CMake
  
  If you are using CMake, there's a convenience @ref corrade-cmake-add-test "corrade_add_test()"
  CMake macro that creates the executable, links `Corrade::TestSuite` library to
  it and adds it to CTest. Besides that it is able to link other arbitrary
  libraries to the executable and specify a list of files that the tests used. It
  provides additional useful features on various platforms:
  
  -   On Windows, the macro links the test executable to the @ref main "Corrade::Main"
      library for ANSI color support, UTF-8 argument parsing and UTF-8 output
      encoding.
  -   If compiling for Emscripten, using @ref corrade-cmake-add-test "corrade_add_test()"
      makes CTest run the resulting `*.js` file via Node.js. Also it is able to
      bundle all files specified in `FILES` into the virtual Emscripten
      filesystem, making it easy to run file-based tests on this platform; all
      environment options are passed through as well. The macro also creates a
      runner for manual testing in a browser, see
      @ref TestSuite-Tester-running-emscripten-browser "below" for more
      information.
  -   If Xcode projects are generated via CMake and @ref CORRADE_TESTSUITE_TARGET_XCTEST
      is enabled, @ref corrade-cmake-add-test "corrade_add_test()" makes the test
      executables in a way compatible with XCTest, making it easy to run them
      directly from Xcode. Running the tests via `ctest` will also use XCTest.
  -   If building for Android, using @ref corrade-cmake-add-test "corrade_add_test()"
      will make CTest upload the test executables and all files specified in `FILES`
      onto the device or emulator via `adb`, run it there with all environment
      options passed through as well and transfers test results back to the host.
      @attention If a test fails, the executable and all files it references is
          kept in `/data/local/tmp` to make it possible to debug / re-run the
          test directly. Note that in the extreme case this may cause the
          internal storage to get filled over time. Rebooting the device or
          doing system cleanup will wipe the temp directory.
  
  .
  
  Example of using the @ref corrade-cmake-add-test "corrade_add_test()" macro is
  below. The test executable will get built from the specified source with the
  libJPEG library linked and the `*.jpg` files will be available on desktop,
  Emscripten and Android in path specified in `JPEG_TEST_DIR` that was saved into
  the `configure.h` file inside current build directory:
  
  @snippet testsuite.cmake 0
  
  @subsection TestSuite-Tester-running-android Manually running the tests on Android
  
  If not using CMake CTest, Android tests can be run manually. When you have
  developer-enabled Android device connected or Android emulator running, you can
  use ADB to upload the built test to device temp directory and run it there:
  
  @code{.sh}
  adb push <path-to-the-test-build>/MyTest /data/local/tmp
  adb shell /data/local/tmp/MyTest
  @endcode
  
  You can also use @cb{.sh} adb shell @ce to log directly into the device shell
  and continue from there. All @ref TestSuite-Tester-command-line "command-line arguments"
  are supported.
  
  @note Keep in mind that older versions of ADB and Android do not correctly
      propagate the exit code to caller, which may result in your test failures
      being silently ignored. See [Android Issue 3254](http://web.archive.org/web/20160806094132/https://code.google.com/p/android/issues/detail?id=3254)
      for possible workarounds. The @ref corrade-cmake-add-test "corrade_add_test()"
      CMake macro also works around this issue.
  
  @subsection TestSuite-Tester-running-emscripten Manually running the tests on Emscripten
  
  When not using CMake CTest, Emscripten tests can be run directly using Node.js.
  Emscripten sideloads the WebAssembly or asm.js binary files from current
  working directory, so it's needed to @cb{.sh} cd @ce into the test build
  directory first:
  
  @code{.sh}
  cd <test-build-directory>
  node MyTest.js
  @endcode
  
  See also the `--embed-files` [emcc option](https://kripken.github.io/emscripten-site/docs/porting/files/packaging_files.html)
  for a possibility to bundle test files with the executable.
  
  @subsection TestSuite-Tester-running-emscripten-browser Running Emscripten tests in a browser
  
  Besides running tests using Node.js, it's possible to run each test case
  manually in a browser. Browsers require the executables to be accessed via a
  webserver --- if you have Python installed, you can simply start serving the
  contents of your build directory using the following command:
  
  @code{.sh}
  cd <test-build-directory>
  python -m http.server
  @endcode
  
  The webserver is then available at http://localhost:8000. It supports directory
  listing, so you can navigate to each test case runner HTML file (look for e.g.
  `MyTest.html`). Unfortunately it's at the moment not possible to run all
  browser tests in a batch or automate the process in any other way.
  */
  class CORRADE_TESTSUITE_EXPORT Tester {
      public:
          /**
           * @brief Tester configuration
           *
           * @see @ref Tester::Tester()
           */
          class CORRADE_TESTSUITE_EXPORT TesterConfiguration {
              public:
                  explicit TesterConfiguration() noexcept;
  
                  /** @brief Copy constructor */
                  TesterConfiguration(const TesterConfiguration&);
  
                  /** @brief Move constructor */
                  TesterConfiguration(TesterConfiguration&&) noexcept;
  
                  ~TesterConfiguration();
  
                  /** @brief Copy assignment */
                  TesterConfiguration& operator=(const TesterConfiguration&);
  
                  /** @brief Move assignment */
                  TesterConfiguration& operator=(TesterConfiguration&&) noexcept;
  
                  /** @brief Skipped argument prefixes */
                  Containers::ArrayView<const std::string> skippedArgumentPrefixes() const;
  
                  /**
                   * @brief Set skipped argument prefixes
                   *
                   * Useful to allow passing command-line arguments elsewhere
                   * without having the tester complaining about them.
                   * @see @ref arguments()
                   */
                  TesterConfiguration& setSkippedArgumentPrefixes(std::initializer_list<std::string> prefixes);
  
                  #if defined(__linux__) || defined(DOXYGEN_GENERATING_OUTPUT)
                  /** @brief Where to check for active CPU scaling governor */
                  std::string cpuScalingGovernorFile() const;
  
                  /**
                   * @brief Set where to check for active CPU scaling governor
                   *
                   * Running benchmarks on a system with dynamic CPU scaling
                   * makes the measurements very noisy. If that's detected, a
                   * warning is printed on output. Defaults to
                   * `/sys/devices/system/cpu/cpu{}/cpufreq/scaling_governor`,
                   * where `{}` is replaced with CPU ID; if the file doesn't
                   * exist, no check is done.
                   * @partialsupport Available only on Linux.
                   */
                  TesterConfiguration& setCpuScalingGovernorFile(const std::string& filename);
                  #endif
  
              private:
                  friend Tester;
  
                  /* Don't want to include any vector or array here because we
                     don't need it in public APIs anyway. */
                  struct Data;
                  Containers::Pointer<Data> _data;
          };
  
          /**
           * @brief Alias for debug output
           *
           * For convenient debug output inside test cases (instead of using
           * the fully qualified name):
           *
           * @snippet TestSuite.cpp Tester-Debug
           *
           * @see @ref Warning, @ref Error
           */
          typedef Corrade::Utility::Debug Debug;
  
          /**
           * @brief Alias for warning output
           *
           * See @ref Debug for more information.
           */
          typedef Corrade::Utility::Warning Warning;
  
          /**
           * @brief Alias for error output
           *
           * See @ref Debug for more information.
           */
          typedef Corrade::Utility::Error Error;
  
          /**
           * @brief Benchmark type
           *
           * @see @ref TestSuite-Tester-benchmark, @ref addBenchmarks(),
           *      @ref addInstancedBenchmarks()
           */
          enum class BenchmarkType {
              /* 0 reserved for test cases */
  
              /**
               * Default. Equivalent to @ref BenchmarkType::WallTime, but can be
               * overriden on command-line using the `--benchmark` option.
               */
              Default = 1,
  
              /**
               * Wall time. Suitable for measuring events in microseconds and up.
               * While the reported time is in nanoseconds, the actual timer
               * granularity may differ from platform to platform. To measure
               * shorter events, increase number of iterations passed to
               * @ref CORRADE_BENCHMARK() to amortize the error or use a
               * different benchmark type.
               */
              WallTime = 2,
  
              /**
               * CPU time. Suitable for measuring most events (microseconds and
               * up). While the reported time is in nanoseconds, the actual timer
               * granularity may differ from platform to platform (for example on
               * Windows the CPU clock is reported in multiples of 100 ns). To
               * measure shorter events, increase number of iterations passed to
               * @ref CORRADE_BENCHMARK() to amortize the error or use a
               * different clock.
               * @partialsupport On @ref CORRADE_TARGET_WINDOWS_RT "Windows RT"
               *      gives zero result.
               */
              CpuTime = 3,
  
              /**
               * CPU cycle count. Suitable for measuring sub-millisecond events,
               * but note that on newer architectures the cycle counter frequency
               * is constant and thus measured value is independent on CPU
               * frequency, so it in fact measures time and not the actual cycles
               * spent. See for example
               * https://randomascii.wordpress.com/2011/07/29/rdtsc-in-the-age-of-sandybridge/
               * for more information.
               * @partialsupport Supported only on @ref CORRADE_TARGET_X86 "x86"
               *      and GCC/Clang or MSVC (using RDTSC), on other platforms
               *      gives zero result.
               */
              CpuCycles = 4
          };
  
          /**
           * @brief Custom benchmark units
           *
           * Unit of measurements outputted from custom benchmarks.
           * @see @ref TestSuite-Tester-benchmark-custom,
           *      @ref addCustomBenchmarks(), @ref addCustomInstancedBenchmarks()
           */
          enum class BenchmarkUnits {
              /* Values should not overlap with BenchmarkType */
  
              Nanoseconds = 100,      /**< Time in nanoseconds */
              Cycles = 101,           /**< Processor cycle count */
              Instructions = 102,     /**< Processor instruction count */
              Bytes = 103,            /**< Memory (in bytes) */
              Count = 104             /**< Generic count */
          };
  
          /**
           * @brief Constructor
           * @param configuration     Optional configuration
           */
          explicit Tester(const TesterConfiguration& configuration = TesterConfiguration{});
  
          /**
           * @brief Command-line arguments
           *
           * Populated by @ref CORRADE_TEST_MAIN().
           */
          std::pair<int&, char**> arguments() { return {*_argc, _argv}; }
  
          /**
           * @brief Add test cases
           *
           * Adds one or more test cases to be executed. It's not an error to
           * call this function multiple times or add one test case more than
           * once.
           * @see @ref TestSuite-Tester-basic, @ref addInstancedTests()
           */
          template<class Derived> void addTests(std::initializer_list<void(Derived::*)()> tests) {
              addRepeatedTests<Derived>(tests, 1);
          }
  
          /**
           * @brief Add repeated test cases
           *
           * Unlike the above function repeats each of the test cases until it
           * fails or @p repeatCount is reached. Useful for stability or resource
           * leak checking. Each test case appears in the output log only once.
           * It's not an error to call this function multiple times or add a
           * particular test case more than once --- in that case it will appear
           * in the output log once for each occurence in the list.
           * @see @ref TestSuite-Tester-repeated, @ref addInstancedTests(),
           *      @ref addRepeatedInstancedTests()
           */
          template<class Derived> void addRepeatedTests(std::initializer_list<void(Derived::*)()> tests, std::size_t repeatCount) {
              addRepeatedTests<Derived>(tests, repeatCount, nullptr, nullptr);
          }
  
          /**
           * @brief Add test cases with explicit setup and teardown functions
           * @param tests         List of test cases to run
           * @param setup         Setup function
           * @param teardown      Teardown function
           *
           * In addition to the behavior of @ref addTests() above, the @p setup
           * function is called before every test case in the list and the
           * @p teardown function is called after every test case in the list,
           * regardless of whether it passed, failed or was skipped. Using
           * verification macros in @p setup or @p teardown function is not
           * allowed. It's not an error to call this function multiple times or
           * add one test case more than once.
           * @see @ref TestSuite-Tester-basic,
           *      @ref TestSuite-Tester-setup-teardown, @ref addInstancedTests()
           */
          template<class Derived> void addTests(std::initializer_list<void(Derived::*)()> tests, void(Derived::*setup)(), void(Derived::*teardown)()) {
              addRepeatedTests<Derived>(tests, 1, setup, teardown);
          }
  
          /**
           * @brief Add repeated test cases with explicit setup and teardown functions
           *
           * Unlike the above function repeats each of the test cases until it
           * fails or @p repeatCount is reached. Useful for stability or resource
           * leak checking. The @p setup and @p teardown functions are called
           * again for each repeat of each test case. Each test case appears in
           * the output log only once. It's not an error to call this function
           * multiple times or add a particular test case more than once --- in
           * that case it will appear in the output log once for each occurence
           * in the list.
           * @see @ref TestSuite-Tester-repeated,
           *      @ref TestSuite-Tester-setup-teardown, @ref addInstancedTests(),
           *      @ref addRepeatedInstancedTests()
           */
          template<class Derived> void addRepeatedTests(std::initializer_list<void(Derived::*)()> tests, std::size_t repeatCount, void(Derived::*setup)(), void(Derived::*teardown)()) {
              for(auto test: tests)
                  addTestCaseInternal({~std::size_t{}, repeatCount, static_cast<TestCase::Function>(test), static_cast<TestCase::Function>(setup), static_cast<TestCase::Function>(teardown)});
          }
  
          /**
           * @brief Add instanced test cases
           *
           * Unlike @ref addTests(), this function runs each of the test cases
           * @p instanceCount times. Useful for data-driven tests. Each test case
           * appears in the output once for each instance. It's not an error to
           * call this function multiple times or add one test case more than
           * once --- in that case it will appear once for each instance of each
           * occurence in the list.
           * @see @ref TestSuite-Tester-instanced, @ref testCaseInstanceId(),
           *      @ref setTestCaseDescription()
           */
          template<class Derived> void addInstancedTests(std::initializer_list<void(Derived::*)()> tests, std::size_t instanceCount) {
              addRepeatedInstancedTests<Derived>(tests, 1, instanceCount);
          }
  
          /**
           * @brief Add repeated instanced test cases
           *
           * Unlike the above function repeats each of the test case instances
           * until it fails or @p repeatCount is reached. Useful for stability or
           * resource leak checking. Each test case appears in the output once
           * for each instance. It's not an error to call this function multiple
           * times or add one test case more than once --- in that case it will
           * appear once for each instance of each occurence in the list.
           * @see @ref TestSuite-Tester-repeated,
           *      @ref TestSuite-Tester-instanced, @ref addInstancedTests(),
           *      @ref addRepeatedInstancedTests()
           */
          template<class Derived> void addRepeatedInstancedTests(std::initializer_list<void(Derived::*)()> tests, std::size_t repeatCount, std::size_t instanceCount) {
              addRepeatedInstancedTests<Derived>(tests, repeatCount, instanceCount, nullptr, nullptr);
          }
  
          /**
           * @brief Add instanced test cases with explicit setup and teardown functions
           * @param tests         List of test cases to run
           * @param instanceCount Instance count
           * @param setup         Setup function
           * @param teardown      Teardown function
           *
           * In addition to the behavior of @ref addInstancedTests() above, the
           * @p setup function is called before every instance of every test case
           * in the list and the @p teardown function is called after every
           * instance of every test case in the list, regardless of whether it
           * passed, failed or was skipped. Using verification macros in @p setup
           * or @p teardown function is not allowed. It's not an error to call
           * this function multiple times or add one test case more than once ---
           * in that case it will appear once for each instance of each occurence
           * in the list.
           * @see @ref TestSuite-Tester-instanced,
           *      @ref TestSuite-Tester-setup-teardown
           */
          template<class Derived> void addInstancedTests(std::initializer_list<void(Derived::*)()> tests, std::size_t instanceCount, void(Derived::*setup)(), void(Derived::*teardown)()) {
              addRepeatedInstancedTests<Derived>(tests, 1, instanceCount, setup, teardown);
          }
  
          /**
           * @brief Add repeated instanced test cases with explicit setup and teardown functions
           *
           * Unlike the above function repeats each of the test case instances
           * until it fails or @p repeatCount is reached. Useful for stability or
           * resource leak checking. The @p setup and @p teardown functions are
           * called again for each repeat of each instance of each test case. The
           * test case appears in the output once for each instance. It's not an
           * error to call this function multiple times or add one test case more
           * than once --- in that case it will appear once for each instance of
           * each occurence in the list.
           * @see @ref TestSuite-Tester-repeated,
           *      @ref TestSuite-Tester-instanced,
           *      @ref TestSuite-Tester-setup-teardown, @ref addInstancedTests(),
           *      @ref addRepeatedInstancedTests()
           */
          template<class Derived> void addRepeatedInstancedTests(std::initializer_list<void(Derived::*)()> tests, std::size_t repeatCount, std::size_t instanceCount, void(Derived::*setup)(), void(Derived::*teardown)()) {
              for(auto test: tests) for(std::size_t i = 0; i != instanceCount; ++i)
                  addTestCaseInternal({i, repeatCount, static_cast<TestCase::Function>(test), static_cast<TestCase::Function>(setup), static_cast<TestCase::Function>(teardown)});
          }
  
          /**
           * @brief Add benchmarks
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param benchmarkType     Benchmark type
           *
           * For each added benchmark measures the time spent executing code
           * inside a statement or block denoted by @ref CORRADE_BENCHMARK(). It
           * is possible to use all verification macros inside the benchmark. The
           * @p batchCount parameter specifies how many batches will be run to
           * make the measurement more precise, while the batch size parameter
           * passed to @ref CORRADE_BENCHMARK() specifies how many iterations
           * will be done in each batch to minimize overhead. It's not an error
           * to call this function multiple times or add one benchmark more than
           * once.
           * @see @ref TestSuite-Tester-benchmark, @ref addInstancedBenchmarks()
           */
          template<class Derived> void addBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, BenchmarkType benchmarkType = BenchmarkType::Default) {
              addBenchmarks<Derived>(benchmarks, batchCount, nullptr, nullptr, benchmarkType);
          }
  
          /**
           * @brief Add benchmarks with explicit setup and teardown functions
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param setup             Setup function
           * @param teardown          Teardown function
           * @param benchmarkType     Benchmark type
           *
           * In addition to the behavior of @ref addBenchmarks() above, the
           * @p setup function is called before every batch of every benchmark in
           * the list and the @p teardown function is called after every batch of
           * every benchmark in the list, regardless of whether it passed, failed
           * or was skipped. Using verification macros in @p setup or @p teardown
           * function is not allowed. It's not an error to call this function
           * multiple times or add one benchmark more than once.
           * @see @ref TestSuite-Tester-benchmark,
           *      @ref TestSuite-Tester-setup-teardown,
           *      @ref addInstancedBenchmarks()
           */
          template<class Derived> void addBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) {
              addCustomBenchmarks<Derived>(benchmarks, batchCount, setup, teardown, nullptr, nullptr, BenchmarkUnits(int(benchmarkType)));
          }
  
          /**
           * @brief Add custom benchmarks
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param benchmarkBegin    Benchmark begin function
           * @param benchmarkEnd      Benchmark end function
           * @param benchmarkUnits    Benchmark units
           *
           * Unlike the above functions uses user-supplied measurement functions.
           * The @p benchmarkBegin parameter starts the measurement, the
           * @p benchmarkEnd parameter ends the measurement and returns measured
           * value, which is in @p units. It's not an error to call this function
           * multiple times or add one benchmark more than once.
           * @see @ref TestSuite-Tester-benchmark-custom,
           *      @ref addCustomInstancedBenchmarks()
           */
          template<class Derived> void addCustomBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, void(Derived::*benchmarkBegin)(), std::uint64_t(Derived::*benchmarkEnd)(), BenchmarkUnits benchmarkUnits) {
              addCustomBenchmarks<Derived>(benchmarks, batchCount, nullptr, nullptr, static_cast<TestCase::BenchmarkBegin>(benchmarkBegin), static_cast<TestCase::BenchmarkEnd>(benchmarkEnd), benchmarkUnits);
          }
  
          /**
           * @brief Add custom benchmarks with explicit setup and teardown functions
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param setup             Setup function
           * @param teardown          Teardown function
           * @param benchmarkBegin    Benchmark begin function
           * @param benchmarkEnd      Benchmark end function
           * @param benchmarkUnits    Benchmark units
           *
           * In addition to the behavior of @ref addCustomBenchmarks() above, the
           * @p setup function is called before every batch of every benchmark in
           * the list and the @p teardown function is called after every batch of
           * every benchmark in the list, regardless of whether it passed, failed
           * or was skipped. Using verification macros in @p setup or @p teardown
           * function is not allowed. It's not an error to call this function
           * multiple times or add one benchmark more than once.
           * @see @ref TestSuite-Tester-benchmark-custom,
           *      @ref TestSuite-Tester-setup-teardown,
           *      @ref addCustomInstancedBenchmarks()
           */
          template<class Derived> void addCustomBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, void(Derived::*setup)(), void(Derived::*teardown)(), void(Derived::*benchmarkBegin)(), std::uint64_t(Derived::*benchmarkEnd)(), BenchmarkUnits benchmarkUnits) {
              for(auto benchmark: benchmarks)
                  addTestCaseInternal({~std::size_t{}, batchCount, static_cast<TestCase::Function>(benchmark), static_cast<TestCase::Function>(setup), static_cast<TestCase::Function>(teardown), static_cast<TestCase::BenchmarkBegin>(benchmarkBegin), static_cast<TestCase::BenchmarkEnd>(benchmarkEnd), TestCaseType(int(benchmarkUnits))});
          }
  
          /**
           * @brief Add instanced benchmarks
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param instanceCount     Instance count
           * @param benchmarkType     Benchmark type
           *
           * Unlike @ref addBenchmarks(), this function runs each of the
           * benchmarks @p instanceCount times. Useful for data-driven tests.
           * Each test case appears in the output once for each instance. It's
           * not an error to call this function multiple times or add one
           * benchmark more than once --- in that case it will appear once for
           * each instance of each occurence in the list.
           * @see @ref TestSuite-Tester-benchmark,
           *      @ref TestSuite-Tester-instanced, @ref testCaseInstanceId(),
           *      @ref setTestCaseDescription()
           */
          template<class Derived> void addInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, BenchmarkType benchmarkType = BenchmarkType::Default) {
              addInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, nullptr, nullptr, benchmarkType);
          }
  
          /**
           * @brief Add instanced benchmarks with explicit setup and teardown functions
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param instanceCount     Instance count
           * @param setup             Setup function
           * @param teardown          Teardown function
           * @param benchmarkType     Benchmark type
           *
           * In addition to the behavior of above function, the @p setup function
           * is called before every instance of every batch of every benchmark in
           * the list and the @p teardown function is called after every instance
           * of every batch of every benchmark in the list, regardless of whether
           * it passed, failed or was skipped. Using verification macros in
           * @p setup or @p teardown function is not allowed. It's not an error
           * to call this function multiple times or add one benchmark more than
           * once --- in that case it will appear once for each instance of each
           * occurence in the list.
           * @see @ref TestSuite-Tester-benchmark,
           *      @ref TestSuite-Tester-instanced,
           *      @ref TestSuite-Tester-setup-teardown
           */
          template<class Derived> void addInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) {
              addCustomInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, setup, teardown, nullptr, nullptr, BenchmarkUnits(int(benchmarkType)));
          }
  
          /**
           * @brief Add custom instanced benchmarks
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param instanceCount     Instance count
           * @param benchmarkBegin    Benchmark begin function
           * @param benchmarkEnd      Benchmark end function
           * @param benchmarkUnits    Benchmark units
           *
           * Unlike the above functions uses user-supplied measurement functions.
           * The @p benchmarkBegin parameter starts the measurement, the
           * @p benchmarkEnd parameter ends the measurement and returns measured
           * value, which is in @p units. It's not an error to call this function
           * multiple times or add one benchmark more than once --- in that case
           * it will appear once for each instance of each occurence in the list.
           * @see @ref TestSuite-Tester-benchmark-custom,
           *      @ref TestSuite-Tester-instanced
           */
          template<class Derived> void addCustomInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, void(Derived::*benchmarkBegin)(), std::uint64_t(Derived::*benchmarkEnd)(), BenchmarkUnits benchmarkUnits) {
              addCustomInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, nullptr, nullptr, benchmarkBegin, benchmarkEnd, benchmarkUnits);
          }
  
          /**
           * @brief Add custom instanced benchmarks with explicit setup and teardown functions
           * @param benchmarks        List of benchmarks to run
           * @param batchCount        Batch count
           * @param instanceCount     Batch count
           * @param setup             Setup function
           * @param teardown          Teardown function
           * @param benchmarkBegin    Benchmark begin function
           * @param benchmarkEnd      Benchmark end function
           * @param benchmarkUnits    Benchmark units
           *
           * In addition to the behavior of @ref addCustomBenchmarks() above, the
           * @p setup function is called before every batch of every benchmark in
           * the list and the @p teardown function is called after every batch of
           * every benchmark in the list, regardless of whether it passed, failed
           * or was skipped. Using verification macros in @p setup or @p teardown
           * function is not allowed. It's not an error to call this function
           * multiple times or add one benchmark more than once --- in that case
           * it will appear once for each instance of each occurence in the list.
           * @see @ref TestSuite-Tester-benchmark-custom,
           *      @ref TestSuite-Tester-instanced,
           *      @ref TestSuite-Tester-setup-teardown
           */
          template<class Derived> void addCustomInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, void(Derived::*setup)(), void(Derived::*teardown)(), void(Derived::*benchmarkBegin)(), std::uint64_t(Derived::*benchmarkEnd)(), BenchmarkUnits benchmarkUnits) {
              for(auto benchmark: benchmarks) for(std::size_t i = 0; i != instanceCount; ++i)
                  addTestCaseInternal({i, batchCount, static_cast<TestCase::Function>(benchmark), static_cast<TestCase::Function>(setup), static_cast<TestCase::Function>(teardown), static_cast<TestCase::BenchmarkBegin>(benchmarkBegin), static_cast<TestCase::BenchmarkEnd>(benchmarkEnd), TestCaseType(int(benchmarkUnits))});
          }
  
          /**
           * @brief Test case ID
           *
           * Returns ID of the test case that is currently executing, starting
           * from `1`.  Expects that this function is called from within a test
           * case or its corresponding setup/teardown function.
           */
          std::size_t testCaseId() const;
  
          /**
           * @brief Test case instance ID
           *
           * Returns instance ID of the instanced test case that is currently
           * executing, starting from `0`. Expects that this function is called
           * from within an instanced test case or its corresponding
           * setup/teardown function.
           * @see @ref addInstancedTests()
           */
          std::size_t testCaseInstanceId() const;
  
          /**
           * @brief Test case repeat ID
           *
           * Returns repeat ID of the repeated test case that is currently
           * executing, starting from `0`. Expects that this function is called
           * from within a repeated test case or its corresponding setup/teardown
           * function.
           * @see @ref addRepeatedTests()
           */
          std::size_t testCaseRepeatId() const;
  
          /**
           * @brief Set custom test name
           *
           * By default the test name is gathered together with test filename by
           * the @ref CORRADE_TEST_MAIN() macro and is equivalent to
           * fully-qualified class name.
           * @see @ref setTestCaseName(), @ref setTestCaseTemplateName(),
           *      @ref setTestCaseDescription()
           */
          void setTestName(const std::string& name);
          void setTestName(std::string&& name); /**< @overload */
          void setTestName(const char* name); /**< @overload */
  
          /**
           * @brief Set custom test case name
           *
           * By default the test case name is gathered in the check macros and is
           * equivalent to the following:
           *
           * @snippet TestSuite.cpp Tester-setTestCaseName
           *
           * @see @ref setTestCaseTemplateName(), @ref setTestName(),
           *      @ref setTestCaseDescription(), @ref CORRADE_FUNCTION
           */
          void setTestCaseName(const std::string& name);
          void setTestCaseName(std::string&& name); /**< @overload */
          void setTestCaseName(const char* name); /**< @overload */
  
          /**
           * @brief Set test case template name
           * @m_since{2019,10}
           *
           * Useful to distinguish different specializations of the same templated
           * test case. Equivalent to the following called from inside the test
           * case:
           *
           * @snippet TestSuite.cpp Tester-setTestCaseTemplateName
           *
           * @see @ref setTestCaseName(), @ref setTestName(),
           *      @ref setTestCaseDescription(), @ref CORRADE_FUNCTION
           */
          void setTestCaseTemplateName(const std::string& name);
  
          /**
           * @overload
           * @m_since{2019,10}
           */
          void setTestCaseTemplateName(std::string&& name);
  
          /**
           * @overload
           * @m_since{2019,10}
           */
          void setTestCaseTemplateName(const char* name);
  
          /**
           * @brief Set test case description
           *
           * Additional text displayed after the test case name. By default
           * the description is empty for non-instanced test cases and instance
           * ID for instanced test cases.
           * @see @ref setTestName(), @ref setTestCaseName(),
           *      @ref setTestCaseTemplateName()
           */
          void setTestCaseDescription(const std::string& description);
          void setTestCaseDescription(std::string&& description); /**< @overload */
          void setTestCaseDescription(const char* description); /**< @overload */
  
          /**
           * @brief Set benchmark name
           *
           * In case of @ref addCustomBenchmarks() and @ref addCustomInstancedBenchmarks()
           * provides the name for the unit measured, for example @cpp "wall time" @ce.
           */
          void setBenchmarkName(const std::string& name);
          void setBenchmarkName(std::string&& name); /**< @overload */
          void setBenchmarkName(const char* name); /**< @overload */
  
      protected:
          ~Tester();
  
      #ifdef DOXYGEN_GENERATING_OUTPUT
      private:
      #else
      public:
      #endif
          /* Called from CORRADE_TEST_MAIN(). argc is grabbed via a mutable
             reference and argv is grabbed as non-const in order to allow the
             users modifying the argument list (and GLUT requires that) */
          static void registerArguments(int& argc, char** argv);
  
          /* Overload needed for testing */
          static void registerArguments(int& argc, const char** argv) {
              registerArguments(argc, const_cast<char**>(argv));
          }
  
          /* Called from all CORRADE_*() macros */
          static Tester& instance();
  
          /* Called from CORRADE_TEST_MAIN() */
          int exec();
  
          /* Overload needed for testing */
          int exec(Tester* previousTester, std::ostream* logOutput, std::ostream* errorOutput);
  
          /* Compare two identical types without explicit type specification */
          template<class T> void compare(const char* actual, const T& actualValue, const char* expected, const T& expectedValue) {
              compareAs<T, T, T>(actual, actualValue, expected, expectedValue);
          }
  
          /* Compare two different types without explicit type specification */
          template<class Actual, class Expected> void compare(const char* actual, const Actual& actualValue, const char* expected, const Expected& expectedValue) {
              compareAs<typename Implementation::CommonType<Actual, Expected>::Type, Actual, Expected>(actual, actualValue, expected, expectedValue);
          }
  
          /* Compare two different types with explicit templated type
             specification (e.g. Compare::Containers). This allows the user to
             call only `CORRADE_COMPARE_AS(a, b, Compare::Containers)` without
             explicitly specifying the type, e.g.
             `CORRADE_COMPARE_AS(a, b, Compare::Containers<std::vector<int>>)` */
          template<template<class> class T, class Actual, class Expected> void compareAs(const char* actual, const Actual& actualValue, const char* expected, const Expected& expectedValue) {
              compareAs<T<typename Implementation::CommonType<Actual, Expected>::Type>, Actual, Expected>(actual, actualValue, expected, expectedValue);
          }
  
          /* Compare two different types with explicit type specification */
          template<class T, class U, class V> void compareAs(const char* actual, const U& actualValue, const char* expected, const V& expectedValue) {
              compareWith(Comparator<T>(), actual, actualValue, expected, expectedValue);
          }
  
          /* Compare two different types with explicit comparator specification */
          template<class T, class U, class V> void compareWith(Comparator<T>& comparator, const char* actual, const U& actualValue, const char* expected, const V& expectedValue);
          template<class T, class U, class V> void compareWith(Comparator<T>&& comparator, const char* actual, const U& actualValue, const char* expected, const V& expectedValue) {
              return compareWith<T, U, V>(comparator, actual, actualValue, expected, expectedValue);
          }
  
          template<class T> void verify(const char* expression, T&& value);
  
          /* Called from CORRADE_TEST_MAIN() */
          void registerTest(const char* filename, const char* name, bool isDebugBuild = false);
  
          /* Called from CORRADE_SKIP() */
          CORRADE_NORETURN void skip(const std::string& message);
          CORRADE_NORETURN void skip(const char* message);
  
          class CORRADE_TESTSUITE_EXPORT ExpectedFailure {
              public:
                  explicit ExpectedFailure(const std::string& message, bool enabled = true);
                  explicit ExpectedFailure(std::string&& message, bool enabled = true);
                  explicit ExpectedFailure(const char* message, bool enabled = true);
  
                  /* For types with explicit bool conversion */
                  template<class T> explicit ExpectedFailure(const std::string& message, T&& enabled): ExpectedFailure{message, enabled ? true : false} {}
                  template<class T> explicit ExpectedFailure(std::string&& message, T&& enabled): ExpectedFailure{message, enabled ? true : false} {}
                  template<class T> explicit ExpectedFailure(const char* message, T&& enabled): ExpectedFailure{message, enabled ? true : false} {}
  
                  ~ExpectedFailure();
          };
  
          class CORRADE_TESTSUITE_EXPORT IterationPrinter {
              public:
                  IterationPrinter();
                  ~IterationPrinter();
  
                  Debug debug();
  
              private:
                  friend Tester;
                  struct Data;
  
                  /* There's a std::ostringstream inside (yes, ew); don't want
                     that in a header */
                  Containers::Pointer<Data> _data;
          };
  
          /* Called from all CORRADE_*() verification/skip/xfail macros through
             _CORRADE_REGISTER_TEST_CASE() */
          void registerTestCase(const char* name, int line);
  
      private:
          class Exception {};
          class SkipException {};
  
          enum class TestCaseType {
              Test = 0,
              DefaultBenchmark = int(BenchmarkType::Default),
              WallTimeBenchmark = int(BenchmarkType::WallTime),
              CpuTimeBenchmark = int(BenchmarkType::CpuTime),
              CpuCyclesBenchmark = int(BenchmarkType::CpuCycles),
              CustomTimeBenchmark = int(BenchmarkUnits::Nanoseconds),
              CustomCycleBenchmark = int(BenchmarkUnits::Cycles),
              CustomInstructionBenchmark = int(BenchmarkUnits::Instructions),
              CustomMemoryBenchmark = int(BenchmarkUnits::Bytes),
              CustomCountBenchmark = int(BenchmarkUnits::Count)
          };
  
          struct TestCase {
              typedef void (Tester::*Function)();
              typedef void (Tester::*BenchmarkBegin)();
              typedef std::uint64_t (Tester::*BenchmarkEnd)();
  
              /*implicit*/ TestCase(std::size_t instanceId, std::size_t repeatCount, Function test, Function setup, Function teardown): instanceId{instanceId}, repeatCount{repeatCount}, test{test}, setup{setup}, teardown{teardown}, benchmarkBegin{}, benchmarkEnd{}, type{TestCaseType::Test} {}
  
              /*implicit*/ TestCase(std::size_t instanceId, std::size_t repeatCount, Function test, Function setup, Function teardown, BenchmarkBegin benchmarkBegin, BenchmarkEnd benchmarkEnd, TestCaseType type): instanceId{instanceId}, repeatCount{repeatCount}, test{test}, setup{setup}, teardown{teardown}, benchmarkBegin{benchmarkBegin}, benchmarkEnd{benchmarkEnd}, type{type} {}
  
              std::size_t instanceId, repeatCount;
              Function test, setup, teardown;
              BenchmarkBegin benchmarkBegin;
              BenchmarkEnd benchmarkEnd;
              TestCaseType type;
          };
  
      #ifndef DOXYGEN_GENERATING_OUTPUT
      public:
      #endif
          class CORRADE_TESTSUITE_EXPORT BenchmarkRunner {
              public:
                  explicit BenchmarkRunner(TestCase::BenchmarkBegin begin, TestCase::BenchmarkEnd end): _instance(Tester::instance()), _end{end} {
                      (_instance.*begin)();
                  }
  
                  ~BenchmarkRunner();
  
                  const char* begin() const { return nullptr; }
                  const char* end() const;
  
              private:
                  /* Caching the instance here to avoid potentially slow global
                     variable access */
                  Tester& _instance;
                  TestCase::BenchmarkEnd _end;
          };
  
          /* Called from CORRADE_BENCHMARK() */
          BenchmarkRunner createBenchmarkRunner(std::size_t batchSize);
  
      private:
          /* Need to preserve as much unique name as possible here, just `State`
             would cause conflicts with user-defined State types */
          struct TesterState;
  
          static int* _argc;
          static char** _argv;
  
          CORRADE_TESTSUITE_LOCAL void printTestCaseLabel(Debug& out, const char* status, Debug::Color statusColor, Debug::Color labelColor);
          CORRADE_TESTSUITE_LOCAL void printFileLineInfo(Debug& out);
          void verifyInternal(const char* expression, bool value);
          void printComparisonMessageInternal(ComparisonStatusFlags flags, const char* actual, const char* expected, void(*printer)(void*, ComparisonStatusFlags, Debug&, const char*, const char*), void(*saver)(void*, ComparisonStatusFlags, Debug&, const std::string&), void* comparator);
  
          void wallTimeBenchmarkBegin();
          std::uint64_t wallTimeBenchmarkEnd();
  
          void cpuTimeBenchmarkBegin();
          std::uint64_t cpuTimeBenchmarkEnd();
  
          void cpuCyclesBenchmarkBegin();
          std::uint64_t cpuCyclesBenchmarkEnd();
  
          void addTestCaseInternal(const TestCase& testCase);
  
          Containers::Pointer<TesterState> _state;
  };
  
  #ifndef DOXYGEN_GENERATING_OUTPUT
  /* Done here because CORRADE_IS_DEBUG_BUILD is defined by the buildsystem when
     compiling the test (as opposed to defined when compiling this library) */
  #ifdef CORRADE_IS_DEBUG_BUILD
  #define _CORRADE_TESTSUITE_IS_DEBUG_BUILD true
  #else
  #define _CORRADE_TESTSUITE_IS_DEBUG_BUILD false
  #endif
  #endif
  
  /** @hideinitializer
  @brief Create `main()` function for given @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass
  
  Populates @ref Corrade::TestSuite::Tester::arguments() "TestSuite::Tester::arguments()",
  instantiates @p Class, executes the test cases and returns from @cpp main() @ce
  with code based on the test results. This macro has to be used outside of any
  namespace.
  */
  #ifdef CORRADE_TESTSUITE_TARGET_XCTEST
  /* Needs to have a separate definiton to silence the -Wmissing-prototypes
     warning */
  #define CORRADE_TEST_MAIN(Class)                                            \
      int CORRADE_VISIBILITY_EXPORT corradeTestMain(int, char**);             \
      int corradeTestMain(int argc, char** argv) {                            \
          Corrade::TestSuite::Tester::registerArguments(argc, argv);          \
          Class t;                                                            \
          t.registerTest(__FILE__, #Class, _CORRADE_TESTSUITE_IS_DEBUG_BUILD); \
          return t.exec();                                                    \
      }
  #else
  #define CORRADE_TEST_MAIN(Class)                                            \
      int main(int argc, char** argv) {                                       \
          Corrade::TestSuite::Tester::registerArguments(argc, argv);          \
          Class t;                                                            \
          t.registerTest(__FILE__, #Class, _CORRADE_TESTSUITE_IS_DEBUG_BUILD); \
          return t.exec();                                                    \
      }
  #endif
  
  /** @hideinitializer
  @brief Verify an expression in a test case
  
  If the expression is not true, the expression is printed and execution of given
  test case is terminated. Example usage:
  
  @snippet TestSuite.cpp CORRADE_VERIFY
  
  It is possible to use @ref CORRADE_VERIFY() also on objects with
  @cpp explicit operator bool() @ce without doing explicit conversion (e.g. using
  @cpp !! @ce), for example:
  
  @snippet TestSuite.cpp CORRADE_VERIFY-explicit
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible to
  also call it in a helper function or lambda called from inside a test case,
  however note that the very first call to a `CORRADE_*()` macro captures the
  caller function name for the test output, which may not be desired when being
  in a helper function or a lambda. To circumvent that, either call a dummy
  @cpp CORRADE_VERIFY(true) @ce at the top of your test case, or explicitly call
  @ref Corrade::TestSuite::Tester::setTestCaseName() "setTestCaseName()" with
  either a hardcoded name or e.g. @ref CORRADE_FUNCTION.
  @see @ref CORRADE_COMPARE(), @ref CORRADE_COMPARE_AS()
  */
  #define CORRADE_VERIFY(expression)                                          \
      do {                                                                    \
          Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
          Corrade::TestSuite::Tester::instance().verify(#expression, expression); \
      } while(false)
  
  /** @hideinitializer
  @brief Compare two values in a test case
  
  If the values are not the same, they are printed for comparison and execution
  of given test case is terminated. Example usage:
  
  @snippet TestSuite.cpp CORRADE_COMPARE
  
  Comparison of floating-point types is by default done as a fuzzy-compare, see
  @ref Corrade::TestSuite::Comparator<float> "TestSuite::Comparator<float>" and
  @ref Corrade::TestSuite::Comparator<double> "TestSuite::Comparator<double>" for
  details.
  
  Note that this macro is usable only if the type passed to it is printable via
  @ref Corrade::Utility::Debug "Utility::Debug". It is meant to be called in a
  test case in a @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass.
  It's possible to also call it in a helper function or lambda called from inside
  a test case with some caveats. See @ref CORRADE_VERIFY() for details.
  @see @ref CORRADE_COMPARE_AS()
  */
  #define CORRADE_COMPARE(actual, expected)                                   \
      do {                                                                    \
          Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
          Corrade::TestSuite::Tester::instance().compare(#actual, actual, #expected, expected); \
      } while(false)
  
  /** @hideinitializer
  @brief Compare two values in a test case with explicitly specified type
  
  Casts the values to a specified typ first and then continues the same as
  @ref CORRADE_COMPARE(). If the values are not the same, they are printed for
  comparison and execution of given test case is terminated. Example usage:
  
  @snippet TestSuite.cpp CORRADE_COMPARE_AS
  
  Note that this macro is usable only if the type passed to it is printable via
  @ref Corrade::Utility::Debug "Utility::Debug" and is convertible to given type.
  @ref CORRADE_COMPARE_AS() and @ref CORRADE_COMPARE_WITH() can be also used for
  advanced comparisons with custom comparators, see
  @ref TestSuite-Tester-advanced-comparisons for more information.
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible
  to also call it in a helper function or lambda called from inside a test case
  with some caveats. See @ref CORRADE_VERIFY() for details.
  @see @ref CORRADE_VERIFY(),
      @ref Corrade::TestSuite::Comparator "TestSuite::Comparator"
  */
  #ifdef DOXYGEN_GENERATING_OUTPUT
  #define CORRADE_COMPARE_AS(actual, expected, Type...)
  #else
  #define CORRADE_COMPARE_AS(actual, expected, ...)                           \
      do {                                                                    \
          Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
          Corrade::TestSuite::Tester::instance().compareAs<__VA_ARGS__>(#actual, actual, #expected, expected); \
      } while(false)
  #endif
  
  /** @hideinitializer
  @brief Compare two values in a test case with explicitly specified comparator
  
  A variant of @ref CORRADE_COMPARE_AS() that takes a comparator instance instead
  of type, useful when you need to pass additional parameters to the comparator.
  See @ref TestSuite-Tester-advanced-comparisons for a high-level introduction
  and an example. If the comparison fails, a comparator-specific diagnostic is
  printed and execution of given test case is terminated. Example usage:
  
  @snippet TestSuite.cpp CORRADE_COMPARE_WITH
  
  Note that this macro is usable only if the type passed to it is compatible with
  given comparator, and in some cases the comparator may require the type to also
  be printable with @ref Corrade::Utility::Debug "Utility::Debug".
  
  This macro is meant to be called in a test case in
  a @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible
  to also call it in a helper function or lambda called from inside a test case
  with some caveats. See @ref CORRADE_VERIFY() for details.
  @see @ref CORRADE_VERIFY(), @ref CORRADE_COMPARE(), ,
      @ref Corrade::TestSuite::Comparator "TestSuite::Comparator"
  */
  #define CORRADE_COMPARE_WITH(actual, expected, comparatorInstance)          \
      do {                                                                    \
          Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
          Corrade::TestSuite::Tester::instance().compareWith((comparatorInstance).comparator(), #actual, actual, #expected, expected); \
      } while(false)
  
  /** @hideinitializer
  @brief Expect failure in a test case in all following checks in the same scope
  @param message Message which will be printed into output as indication of
      expected failure
  
  Expects failure in all following @ref CORRADE_VERIFY(), @ref CORRADE_COMPARE()
  and @ref CORRADE_COMPARE_AS() checks in the same scope. In most cases it will
  be until the end of the function, but you can limit the scope by placing
  relevant checks in a separate block. If any check following the macro in the
  same scope passes, an error will be printed to output.
  
  @snippet TestSuite.cpp CORRADE_EXPECT_FAIL
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible to
  also call it in a helper function or lambda called from inside a test case with
  some caveats. See @ref CORRADE_VERIFY() for details.
  @see @ref CORRADE_EXPECT_FAIL_IF()
  */
  #define CORRADE_EXPECT_FAIL(message)                                        \
      Corrade::TestSuite::Tester::ExpectedFailure _CORRADE_HELPER_PASTE(expectedFailure, __LINE__){message}
  
  /** @hideinitializer
  @brief Conditionally expect failure in a test case in all following checks in the same scope
  @param message      Message which will be printed into output as indication of
      expected failure
  @param condition    The failure is expected only if the condition evaluates to
      @cpp true @ce
  
  With @ref CORRADE_EXPECT_FAIL() it's not possible to write code such as this,
  because the scope of expected failure will end at the end of the @cpp if @ce
  block:
  
  @snippet TestSuite.cpp CORRADE_EXPECT_FAIL_IF-wrong
  
  The solution is to use @cpp CORRADE_EXPECT_FAIL_IF() @ce:
  
  @snippet TestSuite.cpp CORRADE_EXPECT_FAIL_IF
  
  Similarly to @ref CORRADE_VERIFY(), it is possible to use
  @ref CORRADE_EXPECT_FAIL_IF() also on objects with @cpp explicit operator bool @ce
  without doing explicit conversion (e.g. using @cpp !! @ce).
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible to
  also call it in a helper function or lambda called from inside a test case with
  some caveats. See @ref CORRADE_VERIFY() for details.
  */
  #define CORRADE_EXPECT_FAIL_IF(condition, message)                          \
      Corrade::TestSuite::Tester::ExpectedFailure _CORRADE_HELPER_PASTE(expectedFailure, __LINE__)(message, condition)
  
  /** @hideinitializer
  @brief Skip a test case
  @param message Message which will be printed into output as indication of
      skipped test
  
  Skips all following checks in given test case. Useful for e.g. indicating that
  given feature can't be tested on given platform:
  
  @snippet TestSuite.cpp CORRADE_SKIP
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible to
  also call it in a helper function or lambda called from inside a test case with
  some caveats. See @ref CORRADE_VERIFY() for details.
  */
  #define CORRADE_SKIP(message)                                               \
      do {                                                                    \
          Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
          Corrade::TestSuite::Tester::instance().skip(message); \
      } while(false)
  
  /** @hideinitializer
  @brief Annotate an iteration in a test case
  @param ...      Value to print in a failure diagnostic
  @m_since_latest
  
  Annotates loop iterations in order to provide clearer failure diagnostics next
  to the file/line info. Doesn't print anything if there was no failure. Applies
  to all following @ref CORRADE_VERIFY(), @ref CORRADE_COMPARE() etc. checks in
  the same scope, multiple calls in the same scope (or nested scopes) are joined
  together. See @ref TestSuite-Tester-iteration-annotations for an example.
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible to
  also call it in a helper function or lambda called from inside a test case with
  some caveats. See @ref CORRADE_VERIFY() for details.
  */
  #define CORRADE_ITERATION(...)                                              \
      Corrade::TestSuite::Tester::IterationPrinter _CORRADE_HELPER_PASTE(iterationPrinter, __LINE__); \
      do {                                                                    \
          Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
          _CORRADE_HELPER_PASTE(iterationPrinter, __LINE__).debug() << __VA_ARGS__; \
      } while(false)
  
  /** @hideinitializer
  @brief Run a benchmark in a test case
  
  Benchmarks the following block or expression by measuring @p batchSize
  iterations of given block. Desired use is in conjunction with
  @ref Corrade::TestSuite::Tester::addBenchmarks() "TestSuite::Tester::addBenchmarks()"
  and friends, see @ref TestSuite-Tester-benchmark for an introduction and an
  example. Only one such loop can be in a function to achieve proper result.
  Please note that there need to be additional measures in order to prevent the
  optimizer from removing the benchmark code such as assigning to a
  @cpp volatile @ce variable or combining all the results to a variable, which is
  then being used outside of the loop.
  
  @snippet TestSuite.cpp CORRADE_BENCHMARK
  
  The resulting measured value is divided by @p batchSize to represent cost of
  one iteration.
  
  This macro is meant to be called in a test case in a
  @ref Corrade::TestSuite::Tester "TestSuite::Tester" subclass. It's possible to
  also call it in a helper function or lambda called from inside a test case with
  some caveats. See @ref CORRADE_VERIFY() for details.
  */
  #ifndef _MSC_VER
  #define CORRADE_BENCHMARK(batchSize)                                        \
      Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
      for(CORRADE_UNUSED auto&& _CORRADE_HELPER_PASTE(benchmarkIteration, __func__): Corrade::TestSuite::Tester::instance().createBenchmarkRunner(batchSize))
  #else
  /* MSVC warns about the benchmarkIteration variable being set but unused, no
     way around that except than disabling the warning */
  #define CORRADE_BENCHMARK(batchSize)                                        \
      Corrade::TestSuite::Tester::instance().registerTestCase(CORRADE_FUNCTION, __LINE__); \
      for(                                                                    \
          __pragma(warning(push)) __pragma(warning(disable: 4189))            \
          CORRADE_UNUSED auto&& _CORRADE_HELPER_PASTE(benchmarkIteration, __func__): Corrade::TestSuite::Tester::instance().createBenchmarkRunner(batchSize) \
          __pragma(warning(pop))                                              \
      )
  #endif
  
  template<class T, class U, class V> void Tester::compareWith(Comparator<T>& comparator, const char* actual, const U& actualValue, const char* expected, const V& expectedValue) {
      /* Store (references to) possibly implicitly-converted values,
         otherwise the implicit conversion would when passing them to operator(),
         causing dead memory access later in printErrorMessage() */
      const typename Implementation::ComparatorTraits<T, typename std::decay<U>::type, typename std::decay<V>::type>::ActualType& actualValueInExpectedActualType = actualValue;
      const typename Implementation::ComparatorTraits<T, typename std::decay<U>::type, typename std::decay<V>::type>::ExpectedType& expectedValueInExpectedExpectedType = expectedValue;
  
      /* Compare and then print the message, if needed */
      ComparisonStatusFlags status =
          #ifdef CORRADE_BUILD_DEPRECATED
          Implementation::comparisonStatusFlags(
          #endif
              comparator(actualValueInExpectedActualType, expectedValueInExpectedExpectedType)
          #ifdef CORRADE_BUILD_DEPRECATED
          )
          #endif
          ;
  
      printComparisonMessageInternal(status, actual, expected,
          [](void* comparator, ComparisonStatusFlags flags, Debug& out, const char* actual, const char* expected) {
              #ifndef CORRADE_BUILD_DEPRECATED
              static_cast<Comparator<T>*>(comparator)->printMessage(flags, out, actual, expected);
              #else
              Implementation::printMessage<Comparator<T>>(*static_cast<Comparator<T>*>(comparator), flags, out, actual, expected);
              #endif
          }, Implementation::diagnosticSaver<T>(), &comparator);
  }
  
  template<class T> void Tester::verify(const char* expression, T&& value) {
      if(value) verifyInternal(expression, true);
      else verifyInternal(expression, false);
  }
  
  }}
  
  #endif
  