diff --git a/LICENSE b/LICENSE index 2229a83..cafc20d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2021 Martin Ankerl +Copyright (c) 2019-2022 Martin Ankerl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/CODE_OF_CONDUCT.html b/docs/CODE_OF_CONDUCT.html index c1e8508..c03b4c0 100644 --- a/docs/CODE_OF_CONDUCT.html +++ b/docs/CODE_OF_CONDUCT.html @@ -31,7 +31,7 @@
- v4.3.6 + v4.3.7
@@ -314,7 +314,7 @@

Attribution -

© Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

+

© Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

Built with Sphinx using a diff --git a/docs/_static/basic.css b/docs/_static/basic.css index 912859b..bf18350 100644 --- a/docs/_static/basic.css +++ b/docs/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -731,8 +731,9 @@ dl.glossary dt { .classifier:before { font-style: normal; - margin: 0.5em; + margin: 0 0.5em; content: ":"; + display: inline-block; } abbr, acronym { @@ -756,6 +757,7 @@ span.pre { -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; + white-space: nowrap; } div[class*="highlight-"] { diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js index 8cbf1b1..e1bfd70 100644 --- a/docs/_static/doctools.js +++ b/docs/_static/doctools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for all documentation. * - * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -154,9 +154,7 @@ var Documentation = { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); - if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { - this.initOnKeyListeners(); - } + this.initOnKeyListeners(); }, /** @@ -264,6 +262,16 @@ var Documentation = { hideSearchWords : function() { $('#searchbox .highlight-link').fadeOut(300); $('span.highlighted').removeClass('highlighted'); + var url = new URL(window.location); + url.searchParams.delete('highlight'); + window.history.replaceState({}, '', url); + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar : function() { + $('input[name=q]').first().focus(); }, /** @@ -288,27 +296,54 @@ var Documentation = { }, initOnKeyListeners: function() { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) + return; + $(document).keydown(function(event) { var activeElementType = document.activeElement.tagName; // don't navigate when in search box, textarea, dropdown or button if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' - && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey - && !event.shiftKey) { - switch (event.keyCode) { - case 37: // left - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; - } - break; - case 39: // right - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; - } - break; + && activeElementType !== 'BUTTON') { + if (event.altKey || event.ctrlKey || event.metaKey) + return; + + if (!event.shiftKey) { + switch (event.key) { + case 'ArrowLeft': + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) + break; + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 'ArrowRight': + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) + break; + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + case 'Escape': + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) + break; + Documentation.hideSearchWords(); + return false; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case '/': + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) + break; + Documentation.focusSearchBar(); + return false; } } }); diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js index 2fa8c97..724e382 100644 --- a/docs/_static/documentation_options.js +++ b/docs/_static/documentation_options.js @@ -8,5 +8,7 @@ var DOCUMENTATION_OPTIONS = { LINK_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, }; \ No newline at end of file diff --git a/docs/_static/language_data.js b/docs/_static/language_data.js index 863704b..ebe2f03 100644 --- a/docs/_static/language_data.js +++ b/docs/_static/language_data.js @@ -5,7 +5,7 @@ * This script contains the language-specific data used by searchtools.js, * namely the list of stopwords, stemmer, scorer and splitter. * - * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/docs/_static/pygments.css b/docs/_static/pygments.css index 582d5c3..08bec68 100644 --- a/docs/_static/pygments.css +++ b/docs/_static/pygments.css @@ -5,22 +5,22 @@ td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5 span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #f8f8f8; } -.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ .highlight .err { border: 1px solid #FF0000 } /* Error */ .highlight .k { color: #008000; font-weight: bold } /* Keyword */ .highlight .o { color: #666666 } /* Operator */ -.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ -.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ -.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ -.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #9C6500 } /* Comment.Preproc */ +.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gr { color: #E40000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #00A000 } /* Generic.Inserted */ -.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gi { color: #008400 } /* Generic.Inserted */ +.highlight .go { color: #717171 } /* Generic.Output */ .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ @@ -33,15 +33,15 @@ span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: .highlight .kt { color: #B00040 } /* Keyword.Type */ .highlight .m { color: #666666 } /* Literal.Number */ .highlight .s { color: #BA2121 } /* Literal.String */ -.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .na { color: #687822 } /* Name.Attribute */ .highlight .nb { color: #008000 } /* Name.Builtin */ .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ .highlight .no { color: #880000 } /* Name.Constant */ .highlight .nd { color: #AA22FF } /* Name.Decorator */ -.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0000FF } /* Name.Function */ -.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nl { color: #767600 } /* Name.Label */ .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #19177C } /* Name.Variable */ @@ -58,11 +58,11 @@ span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #BA2121 } /* Literal.String.Double */ -.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ .highlight .sx { color: #008000 } /* Literal.String.Other */ -.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ .highlight .s1 { color: #BA2121 } /* Literal.String.Single */ .highlight .ss { color: #19177C } /* Literal.String.Symbol */ .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ diff --git a/docs/_static/searchtools.js b/docs/_static/searchtools.js index 58ff35c..0a44e85 100644 --- a/docs/_static/searchtools.js +++ b/docs/_static/searchtools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -172,10 +172,6 @@ var Search = { } // stem the word var word = stemmer.stemWord(tmp[i].toLowerCase()); - // prevent stemmer from cutting word smaller than two chars - if(word.length < 3 && tmp[i].length >= 3) { - word = tmp[i]; - } var toAppend; // select the correct list if (word[0] == '-') { @@ -276,7 +272,7 @@ var Search = { setTimeout(function() { displayNextItem(); }, 5); - } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) { + } else if (DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY) { $.ajax({url: requestUrl, dataType: "text", complete: function(jqxhr, textstatus) { @@ -293,7 +289,7 @@ var Search = { }, 5); }}); } else { - // no source available, just display title + // just display title Search.output.append(listItem); setTimeout(function() { displayNextItem(); @@ -328,7 +324,9 @@ var Search = { var results = []; for (var prefix in objects) { - for (var name in objects[prefix]) { + for (var iMatch = 0; iMatch != objects[prefix].length; ++iMatch) { + var match = objects[prefix][iMatch]; + var name = match[4]; var fullname = (prefix ? prefix + '.' : '') + name; var fullnameLower = fullname.toLowerCase() if (fullnameLower.indexOf(object) > -1) { @@ -342,7 +340,6 @@ var Search = { } else if (parts[parts.length - 1].indexOf(object) > -1) { score += Scorer.objPartialMatch; } - var match = objects[prefix][name]; var objname = objnames[match[1]][2]; var title = titles[match[0]]; // If more than one term searched for, we require other words to be diff --git a/docs/comparison.html b/docs/comparison.html index ef839e3..86333d1 100644 --- a/docs/comparison.html +++ b/docs/comparison.html @@ -32,7 +32,7 @@
- v4.3.6 + v4.3.7
@@ -334,7 +334,7 @@

Sourcecode10// g++ -O2 main.cpp -Lgit/benchmark/build/src -lbenchmark -lpthread -o m 11void ComparisonFast(benchmark::State& state) { 12 uint64_t x = 1; -13 for (auto _ : state) { +13 for (auto _ : state) { 14 x += x; 15 } 16 benchmark::DoNotOptimize(x); @@ -342,7 +342,7 @@

Sourcecode18BENCHMARK(ComparisonFast); 19 20void ComparisonSlow(benchmark::State& state) { -21 for (auto _ : state) { +21 for (auto _ : state) { 22 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 23 } 24} @@ -351,7 +351,7 @@

Sourcecode27void ComparisonFluctuating(benchmark::State& state) { 28 std::random_device dev; 29 std::mt19937_64 rng(dev()); -30 for (auto _ : state) { +30 for (auto _ : state) { 31 // each run, perform a random number of rng calls 32 auto iterations = rng() & UINT64_C(0xff); 33 for (uint64_t i = 0; i < iterations; ++i) { @@ -410,8 +410,8 @@

Sourcecode 9 10NONIUS_PARAM(X, UINT64_C(1)) 11 -12template <typename Fn> -13struct volatilize_fn { +12template <typename Fn> +13struct volatilize_fn { 14 Fn fn; 15 auto operator()() const -> decltype(fn()) { 16 volatile auto x = fn(); @@ -419,8 +419,8 @@

Sourcecode18 } 19}; 20 -21template <typename Fn> -22auto volatilize(Fn&& fn) -> volatilize_fn<typename std::decay<Fn>::type> { +21template <typename Fn> +22auto volatilize(Fn&& fn) -> volatilize_fn<typename std::decay<Fn>::type> { 23 return {std::forward<Fn>(fn)}; 24} 25 @@ -504,7 +504,7 @@

Sourcecode13PICOBENCH_SUITE("ComparisonFast"); 14static void ComparisonFast(picobench::state& state) { 15 uint64_t x = 1; -16 for (auto _ : state) { +16 for (auto _ : state) { 17 x += x; 18 } 19 state.set_result(x); @@ -513,7 +513,7 @@

Sourcecode22 23PICOBENCH_SUITE("ComparisonSlow"); 24void ComparisonSlow(picobench::state& state) { -25 for (auto _ : state) { +25 for (auto _ : state) { 26 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 27 } 28} @@ -523,7 +523,7 @@

Sourcecode32void ComparisonFluctuating(picobench::state& state) { 33 std::random_device dev; 34 std::mt19937_64 rng(dev()); -35 for (auto _ : state) { +35 for (auto _ : state) { 36 // each run, perform a random number of rng calls 37 auto iterations = rng() & UINT64_C(0xff); 38 for (uint64_t i = 0; i < iterations; ++i) { @@ -815,7 +815,7 @@

folly Benchmark -

© Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

+

© Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

Built with Sphinx using a diff --git a/docs/genindex.html b/docs/genindex.html index 1c0b380..cdb550a 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -29,7 +29,7 @@
- v4.3.6 + v4.3.7
@@ -310,7 +310,7 @@

T


-

© Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

+

© Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

Built with Sphinx using a diff --git a/docs/index.html b/docs/index.html index 22422f3..d64ca21 100644 --- a/docs/index.html +++ b/docs/index.html @@ -31,7 +31,7 @@
- v4.3.6 + v4.3.7
@@ -291,7 +291,7 @@

Design Goals -

© Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

+

© Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

Built with Sphinx using a diff --git a/docs/license.html b/docs/license.html index c8beb7d..27c9da3 100644 --- a/docs/license.html +++ b/docs/license.html @@ -32,7 +32,7 @@
- v4.3.6 + v4.3.7
@@ -187,7 +187,7 @@

MIT License

MIT License

-

Copyright (c) 2019-2021 Martin Ankerl

+

Copyright (c) 2019-2022 Martin Ankerl

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 @@ -216,7 +216,7 @@

MIT License -

© Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

+

© Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

Built with Sphinx using a diff --git a/docs/reference.html b/docs/reference.html index 161ae9f..20079f4 100644 --- a/docs/reference.html +++ b/docs/reference.html @@ -33,7 +33,7 @@
- v4.3.6 + v4.3.7
@@ -330,7 +330,7 @@

Bench &epochs(size_t numEpochs) noexcept

Controls number of epochs, the number of measurements to perform.

The reported result will be the median of evaluation of each epoch. The higher you choose this, the more deterministic the result be and outliers will be more easily removed. Also the err% will be more accurate the higher this number is. Note that the err% will not necessarily decrease when number of epochs is increased. But it will be a more accurate representation of the benchmarked code’s runtime stability.

-

Choose the value wisely. In practice, 11 has been shown to be a reasonable choice between runtime performance and accuracy. This setting goes hand in hand with minEpocIterations() (or minEpochTime()). If you are more interested in median runtime, you might want to increase epochs(). If you are more interested in mean runtime, you might want to increase minEpochIterations() instead.

+

Choose the value wisely. In practice, 11 has been shown to be a reasonable choice between runtime performance and accuracy. This setting goes hand in hand with minEpochIterations() (or minEpochTime()). If you are more interested in median runtime, you might want to increase epochs(). If you are more interested in mean runtime, you might want to increase minEpochIterations() instead.

Parameters

numEpochs – Number of epochs.

@@ -343,10 +343,10 @@

Bench &maxEpochTime(std::chrono::nanoseconds t) noexcept

Upper limit for the runtime of each epoch.

As a safety precausion if the clock is not very accurate, we can set an upper limit for the maximum evaluation time per epoch. Default is 100ms. At least a single evaluation of the benchmark is performed.

-

-
See

minEpochTime(), minEpochIterations()

-
-
+

Parameters
@@ -360,10 +360,10 @@

Bench &minEpochTime(std::chrono::nanoseconds t) noexcept

Minimum time each epoch should take.

Default is zero, so we are fully relying on clockResolutionMultiple(). In most cases this is exactly what you want. If you see that the evaluation is unreliable with a high err%, you can increase either minEpochTime() or minEpochIterations().

-

-
See

maxEpochTime(), minEpochIterations()

-
-
+

Parameters
@@ -377,10 +377,10 @@

Bench &minEpochIterations(uint64_t numIters) noexcept

Sets the minimum number of iterations each epoch should take.

Default is 1, and we rely on clockResolutionMultiple(). If the err% is high and you want a more smooth result, you might want to increase the minimum number or iterations, or increase the minEpochTime().

-

-
See

minEpochTime(), maxEpochTime(), minEpochIterations()

-
-
+

Parameters
@@ -450,7 +450,7 @@

std::vector<Result> const &results() const noexcept

Retrieves all benchmark results collected by the bench object so far.

-

Each call to run() generates a Result that is stored within the Bench instance. This is mostly for advanced users who want to see all the nitty gritty detials.

+

Each call to run() generates a Result that is stored within the Bench instance. This is mostly for advanced users who want to see all the nitty gritty details.

Returns

All results collected so far.

@@ -521,7 +521,7 @@

The resulting mean squared error can be printed with std::cout << logLogN. E.g. it prints something like this:

-

2.46985e-05 * O(log log n), rms=1.48121
+

2.46985e-05 * O(log log n), rms=1.48121
 

@@ -728,7 +728,7 @@

{{clockResolution}} Accuracy of the clock, i.e. what’s the smallest time possible to measure with the clock. For modern systems, this can be around 20 ns. This value is automatically determined by nanobench at the first benchmark that is run, and used as a static variable throughout the application’s runtime.

  • {{clockResolutionMultiple}} Configuration multiplier for clockResolution. See Bench::clockResolutionMultiple(). This is the target runtime for each measurement (epoch). That means the more accurate your clock is, the faster will be the benchmark. Basing the measurement’s runtime on the clock resolution is the main reason why nanobench is so fast.

  • {{maxEpochTime}} Configuration for a maximum time each measurement (epoch) is allowed to take. Note that at least a single iteration will be performed, even when that takes longer than maxEpochTime. See Bench::maxEpochTime().

  • -
  • {{minEpochTime}} Minimum epoch time, usually not set. See Bench::minEpochTime().

  • +
  • {{minEpochTime}} Minimum epoch time, defaults to 1ms. See Bench::minEpochTime().

  • {{minEpochIterations}} See Bench::minEpochIterations().

  • {{epochIterations}} See Bench::epochIterations().

  • {{warmup}} Number of iterations used before measuring starts. See Bench::warmup().

  • @@ -817,10 +817,10 @@

    HTML Box Plots for an example.

    -

    -
    See

    ankerl::nanobench::render()

    -
    -
    +

    +

    See also

    +

    ankerl::nanobench::render()

    +

    @@ -841,7 +841,7 @@

    char const *ankerl::nanobench::templates::pyperf() noexcept
    -

    Output in pyperf compatible JSON format, which can be used for more analyzations.

    +

    Output in pyperf compatible JSON format, which can be used for more analyzation.

    See the tutorial at pyperf - Python pyperf module Output for an example how to further analyze the output.

    @@ -895,7 +895,7 @@

    NANOBENCH_SUPPR
    -

    © Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

    +

    © Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

    Built with Sphinx using a diff --git a/docs/search.html b/docs/search.html index 44ee621..c57c225 100644 --- a/docs/search.html +++ b/docs/search.html @@ -32,7 +32,7 @@
    - v4.3.6 + v4.3.7
    @@ -203,7 +203,7 @@
    -

    © Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

    +

    © Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

    Built with Sphinx using a diff --git a/docs/searchindex.js b/docs/searchindex.js index 1b803db..64042c5 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["CODE_OF_CONDUCT","comparison","genindex","index","license","reference","tutorial"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["CODE_OF_CONDUCT.md","comparison.rst","genindex.rst","index.rst","license.rst","reference.rst","tutorial.rst"],objects:{"":{"ankerl::nanobench::Bench":[5,0,1,"_CPPv4N6ankerl9nanobench5BenchE"],"ankerl::nanobench::Bench::Bench":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench5BenchEv"],"ankerl::nanobench::Bench::batch":[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench5batchER5Bench1T"],"ankerl::nanobench::Bench::batch::T":[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench5batchER5Bench1T"],"ankerl::nanobench::Bench::batch::b":[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench5batchER5Bench1T"],"ankerl::nanobench::Bench::clockResolutionMultiple":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench23clockResolutionMultipleE6size_t"],"ankerl::nanobench::Bench::clockResolutionMultiple::multiple":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench23clockResolutionMultipleE6size_t"],"ankerl::nanobench::Bench::complexityBigO":[5,1,1,"_CPPv4NK6ankerl9nanobench5Bench14complexityBigOEv"],"ankerl::nanobench::Bench::complexityBigO::Op":[5,2,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op"],"ankerl::nanobench::Bench::complexityBigO::name":[5,3,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op"],"ankerl::nanobench::Bench::complexityBigO::op":[5,3,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op"],"ankerl::nanobench::Bench::complexityN":[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench11complexityNER5Bench1T"],"ankerl::nanobench::Bench::complexityN::T":[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench11complexityNER5Bench1T"],"ankerl::nanobench::Bench::complexityN::b":[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench11complexityNER5Bench1T"],"ankerl::nanobench::Bench::doNotOptimizeAway":[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench17doNotOptimizeAwayER5BenchRR3Arg"],"ankerl::nanobench::Bench::doNotOptimizeAway::Arg":[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench17doNotOptimizeAwayER5BenchRR3Arg"],"ankerl::nanobench::Bench::doNotOptimizeAway::arg":[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench17doNotOptimizeAwayER5BenchRR3Arg"],"ankerl::nanobench::Bench::epochIterations":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench15epochIterationsE8uint64_t"],"ankerl::nanobench::Bench::epochIterations::numIters":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench15epochIterationsE8uint64_t"],"ankerl::nanobench::Bench::epochs":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6epochsE6size_t"],"ankerl::nanobench::Bench::epochs::numEpochs":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6epochsE6size_t"],"ankerl::nanobench::Bench::maxEpochTime":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench12maxEpochTimeENSt6chrono11nanosecondsE"],"ankerl::nanobench::Bench::maxEpochTime::t":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench12maxEpochTimeENSt6chrono11nanosecondsE"],"ankerl::nanobench::Bench::minEpochIterations":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench18minEpochIterationsE8uint64_t"],"ankerl::nanobench::Bench::minEpochIterations::numIters":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench18minEpochIterationsE8uint64_t"],"ankerl::nanobench::Bench::minEpochTime":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench12minEpochTimeENSt6chrono11nanosecondsE"],"ankerl::nanobench::Bench::minEpochTime::t":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench12minEpochTimeENSt6chrono11nanosecondsE"],"ankerl::nanobench::Bench::name":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench4nameEPKc"],"ankerl::nanobench::Bench::name::benchmarkName":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench4nameEPKc"],"ankerl::nanobench::Bench::output":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6outputEPNSt7ostreamE"],"ankerl::nanobench::Bench::output::outstream":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6outputEPNSt7ostreamE"],"ankerl::nanobench::Bench::performanceCounters":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench19performanceCountersEb"],"ankerl::nanobench::Bench::performanceCounters::showPerformanceCounters":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench19performanceCountersEb"],"ankerl::nanobench::Bench::relative":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench8relativeEb"],"ankerl::nanobench::Bench::relative::isRelativeEnabled":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench8relativeEb"],"ankerl::nanobench::Bench::render":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6renderEPKcRNSt7ostreamE"],"ankerl::nanobench::Bench::render::os":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6renderEPKcRNSt7ostreamE"],"ankerl::nanobench::Bench::render::templateContent":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6renderEPKcRNSt7ostreamE"],"ankerl::nanobench::Bench::results":[5,1,1,"_CPPv4NK6ankerl9nanobench5Bench7resultsEv"],"ankerl::nanobench::Bench::run":[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchRR2Op"],"ankerl::nanobench::Bench::run::Op":[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchRR2Op"],"ankerl::nanobench::Bench::run::benchmarkName":[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchPKcRR2Op"],"ankerl::nanobench::Bench::run::op":[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchRR2Op"],"ankerl::nanobench::Bench::timeUnit":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench8timeUnitERKNSt6chrono8durationIdEERKNSt6stringE"],"ankerl::nanobench::Bench::timeUnit::tu":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench8timeUnitERKNSt6chrono8durationIdEERKNSt6stringE"],"ankerl::nanobench::Bench::timeUnit::tuName":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench8timeUnitERKNSt6chrono8durationIdEERKNSt6stringE"],"ankerl::nanobench::Bench::title":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench5titleEPKc"],"ankerl::nanobench::Bench::title::benchmarkTitle":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench5titleEPKc"],"ankerl::nanobench::Bench::unit":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench4unitEPKc"],"ankerl::nanobench::Bench::unit::unit":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench4unitEPKc"],"ankerl::nanobench::Bench::warmup":[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6warmupE8uint64_t"],"ankerl::nanobench::Bench::warmup::numWarmupIters":[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6warmupE8uint64_t"],"ankerl::nanobench::Result":[5,0,1,"_CPPv4N6ankerl9nanobench6ResultE"],"ankerl::nanobench::Rng":[5,0,1,"_CPPv4N6ankerl9nanobench3RngE"],"ankerl::nanobench::Rng::Rng":[5,1,1,"_CPPv4N6ankerl9nanobench3Rng3RngEv"],"ankerl::nanobench::Rng::Rng::seed":[5,3,1,"_CPPv4N6ankerl9nanobench3Rng3RngE8uint64_t"],"ankerl::nanobench::Rng::bounded":[5,1,1,"_CPPv4N6ankerl9nanobench3Rng7boundedE8uint32_t"],"ankerl::nanobench::Rng::bounded::range":[5,3,1,"_CPPv4N6ankerl9nanobench3Rng7boundedE8uint32_t"],"ankerl::nanobench::Rng::copy":[5,1,1,"_CPPv4NK6ankerl9nanobench3Rng4copyEv"],"ankerl::nanobench::Rng::operator()":[5,1,1,"_CPPv4N6ankerl9nanobench3RngclEv"],"ankerl::nanobench::Rng::operator=":[5,1,1,"_CPPv4N6ankerl9nanobench3RngaSERK3Rng"],"ankerl::nanobench::Rng::result_type":[5,4,1,"_CPPv4N6ankerl9nanobench3Rng11result_typeE"],"ankerl::nanobench::Rng::shuffle":[5,1,1,"_CPPv4I0EN6ankerl9nanobench3Rng7shuffleEvR9Container"],"ankerl::nanobench::Rng::shuffle::Container":[5,2,1,"_CPPv4I0EN6ankerl9nanobench3Rng7shuffleEvR9Container"],"ankerl::nanobench::Rng::shuffle::container":[5,3,1,"_CPPv4I0EN6ankerl9nanobench3Rng7shuffleEvR9Container"],"ankerl::nanobench::Rng::state":[5,1,1,"_CPPv4NK6ankerl9nanobench3Rng5stateEv"],"ankerl::nanobench::Rng::uniform01":[5,1,1,"_CPPv4N6ankerl9nanobench3Rng9uniform01Ev"],"ankerl::nanobench::doNotOptimizeAway":[5,1,1,"_CPPv4I0EN6ankerl9nanobench17doNotOptimizeAwayEvRR3Arg"],"ankerl::nanobench::doNotOptimizeAway::Arg":[5,2,1,"_CPPv4I0EN6ankerl9nanobench17doNotOptimizeAwayEvRR3Arg"],"ankerl::nanobench::doNotOptimizeAway::arg":[5,3,1,"_CPPv4I0EN6ankerl9nanobench17doNotOptimizeAwayEvRR3Arg"],"ankerl::nanobench::render":[5,1,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE"],"ankerl::nanobench::render::bench":[5,3,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE"],"ankerl::nanobench::render::mustacheTemplate":[5,3,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE"],"ankerl::nanobench::render::out":[5,3,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE"],"ankerl::nanobench::templates::csv":[5,1,1,"_CPPv4N6ankerl9nanobench9templates3csvEv"],"ankerl::nanobench::templates::htmlBoxplot":[5,1,1,"_CPPv4N6ankerl9nanobench9templates11htmlBoxplotEv"],"ankerl::nanobench::templates::json":[5,1,1,"_CPPv4N6ankerl9nanobench9templates4jsonEv"],"ankerl::nanobench::templates::pyperf":[5,1,1,"_CPPv4N6ankerl9nanobench9templates6pyperfEv"]}},objnames:{"0":["cpp","class","C++ class"],"1":["cpp","function","C++ function"],"2":["cpp","templateParam","C++ template parameter"],"3":["cpp","functionParam","C++ function parameter"],"4":["cpp","type","C++ type"]},objtypes:{"0":"cpp:class","1":"cpp:function","2":"cpp:templateParam","3":"cpp:functionParam","4":"cpp:type"},terms:{"0":[0,1,3,5,6],"00":[1,3,6],"000":1,"000167224":1,"000171959":6,"000217248":6,"000218811":6,"000661384":1,"00091350764819687":6,"001":1,"00116867939228672":6,"00169204737732657":6,"00297176820208024":6,"003":1,"0030441400304414":6,"00307692307692308":6,"00308166409861325":6,"0031104199066874":6,"0032520325203252":6,"0033003300330033":6,"00345423143350604":6,"0034662045061":6,"00347222222222222":6,"004":1,"00528169014084507":6,"007":6,"01":6,"010":1,"011887072808":6,"012":1,"012176560122":6,"012307692308":6,"012326656394":6,"012441679627":6,"0129533678757":6,"013008130081":6,"01319":1,"013201320132":6,"013536379019":6,"013816925734":6,"013888888889":6,"014084507042":6,"019":1,"02":6,"0236579384033733":6,"0296662546354":6,"03":[1,6],"035125448044942":6,"0426":1,"05":[1,5,6],"056":1,"059027777778":6,"06":[5,6],"061":1,"063":6,"068":[1,6],"07":[1,3,6],"071":6,"074":1,"079":1,"08":[5,6],"080":6,"081":6,"086":1,"08935e":5,"09":[5,6],"096":6,"099":6,"0th":6,"0xff":[1,6],"1":[1,3,5,6],"10":[1,5,6],"100":[1,5,6],"1000":[1,5,6],"10000000":1,"1000000000":1,"10000u":6,"1000u":6,"10055943":1,"10055959":1,"10088773":1,"100m":[5,6],"100th":6,"100u":6,"101":[1,6],"10113643":1,"10114054":1,"1013":1,"10137913":1,"1016":1,"102":6,"1041":1,"1057":1,"106":6,"10608e":5,"10742e":6,"108808290155":6,"109":1,"1090":1,"1098":1,"10k":6,"10m":1,"10u":6,"11":[1,3,5,6],"1103":1,"112":1,"113":6,"114":6,"115":6,"116":6,"117":6,"118":6,"1189":1,"11992392254248e":6,"12":[1,6],"121":6,"12288k":1,"123":6,"12414":1,"125":6,"12506e":1,"1258":1,"125m":6,"127":6,"128":[1,5,6],"12n":6,"13":[1,6],"130":6,"1302":1,"131":6,"1313":1,"132":[3,5],"133":3,"134":6,"1357":1,"136":[1,6],"1396":1,"14":[3,6],"141":6,"149":[1,6],"15":[5,6],"1551":1,"15683e":6,"156862745":1,"157":6,"159":1,"16":6,"161":1,"162":5,"167":6,"1679586563308":6,"168":6,"17":[3,6],"170":6,"177":6,"1777":1,"178":[1,6],"18":[1,6],"182":6,"183":1,"185":1,"18520325203252e":6,"18547854785479e":6,"18618307426598e":6,"187":6,"18769230769231e":6,"18973561430793e":6,"19":[1,6],"19013867488444e":6,"19049034175334e":6,"1912013536379e":6,"192":[1,6],"193":6,"19305555555556e":6,"19558599695586e":6,"1m":5,"1n":5,"2":[1,5,6],"20":[1,3,5],"200":[5,6],"2000u":6,"200u":6,"20126262626263e":6,"2019":[1,4],"202":1,"2021":4,"203":1,"204":1,"20480002":1,"205":6,"20n":5,"20u":6,"21":[1,6],"2137323943662e":6,"219":6,"22":1,"229832572298":6,"23":[1,6],"232":6,"233":1,"23305882352941e":6,"239":3,"24":[3,6],"24097693351425e":6,"2414":1,"24x":6,"25":[1,6],"25215e":1,"253":6,"25310880829016e":6,"254":6,"255":1,"2560000000":1,"256k":1,"259":1,"25th":6,"26":[1,6],"262":6,"2635658914729":6,"26465858909014e":6,"266033254157":6,"27":6,"2724":1,"274":1,"276":[3,6],"277":6,"279":6,"28":[1,6],"287":6,"29":[1,6],"291":6,"29307e":5,"2ghz":1,"2m":[5,6],"3":[1,5,6],"30":6,"31":[1,6],"3110098709":1,"312":6,"313":1,"3141104294":1,"318":6,"32":6,"32792e":6,"32bit":5,"32k":1,"33":6,"3324":1,"332892998679":6,"334":6,"334214002642":6,"338":6,"34":1,"343":1,"3479809976247":6,"35":[1,6],"3505882352941":6,"36":6,"3623737373737":6,"364":6,"365":1,"367":1,"37":6,"374491180461":6,"375":1,"38":6,"39":6,"391095":1,"391109":1,"391135":1,"3920":1,"392941176470588":6,"394":1,"396464646464646":6,"399":6,"3m":6,"4":[1,5,6],"40":6,"402":6,"40387e":6,"405440414507772":6,"4096":1,"41":6,"412":6,"417910447761194":6,"42":6,"420454545455":6,"424":6,"43":6,"431":6,"44":6,"444":6,"446":6,"45":1,"451":1,"46":[5,6],"4600":1,"462351387054":6,"469":1,"46985e":5,"47":5,"472":6,"47588e":6,"48":6,"48121":5,"486":6,"48677e":5,"49":6,"490":6,"492":6,"4952":1,"497":6,"5":[1,3,5,6],"50":[1,5,6],"500":6,"5000":6,"5000u":6,"500u":6,"502":6,"50619e":1,"509":1,"50th":6,"50u":6,"51":[1,5,6],"512":1,"512000000":1,"514":6,"51982200647249e":6,"52":3,"524":1,"529":6,"5290482076638":6,"53":[1,6],"531":6,"53405963302752e":6,"539":1,"54":6,"54441805225653e":6,"54708571428571e":6,"55":[1,6],"55985915493":6,"56":6,"563073394495413":6,"56376":1,"564133016627078":6,"565":1,"567":6,"568":6,"57":6,"570":1,"574857142857143":6,"575":1,"575539568345324":6,"576":6,"576227390181":6,"579":6,"57n":6,"58":[1,6],"580":6,"5814":1,"582":6,"582200247218789":6,"5823529411765":6,"58467243510507e":6,"59":6,"590439276485788":6,"591":6,"59256594724221e":6,"595":6,"5th":6,"6":[1,3,5,6],"60":[1,6],"606":6,"60607235142119e":6,"60m":[3,6],"61":6,"610":1,"611sec":1,"615":6,"618229854689564":6,"62":6,"621":6,"629":6,"629411764706":6,"63":6,"635491606715":6,"638":6,"63870541611625e":6,"63n":6,"64":[1,5],"643":6,"6431478968792":6,"644485":1,"649":6,"64bit":[5,6],"64u":6,"65":3,"650":6,"655":6,"657":6,"66":[1,6],"661":6,"66562e":6,"67":6,"673":6,"69":[5,6],"693":6,"699":6,"7":[1,3,6],"70":6,"706946":1,"709":[1,6],"71":6,"713sec":1,"714":6,"715":1,"72":6,"73":1,"733":6,"737":[1,6],"740":1,"741":1,"744":1,"75":6,"753":6,"757":6,"7580275229358":6,"7588383838384":6,"759":6,"75th":6,"761":6,"764":6,"7645714285714":6,"7661870503597":6,"767":6,"768":6,"77":6,"771322620519":6,"772":6,"774":6,"78":6,"782":1,"786":6,"79":[1,3,6],"792":6,"797":6,"8":[1,3,5,6],"80":6,"803":1,"809":6,"81":6,"810":1,"812":6,"815":[1,6],"8192":1,"819sec":1,"82":6,"820":6,"824":6,"825":1,"827":1,"828sec":1,"83":6,"833":6,"834":6,"8341968911917":6,"83498349835":6,"84":6,"842":6,"844":1,"85":6,"850":6,"850539291217":6,"853":6,"858536585366":6,"86":[1,6],"862":6,"87":6,"8700":1,"872":6,"875":6,"88":1,"881":6,"88133e":5,"883sec":1,"885":6,"885714285714":6,"8859857482185":6,"889":6,"89":6,"898461538462":6,"8e":6,"9":[1,3,5,6],"90":6,"906222":1,"909957":1,"90m":6,"91":6,"911":6,"916619":1,"924":6,"93":6,"9352517985612":6,"94":6,"944162436548":6,"945584":1,"9470827679783":6,"948":3,"95":1,"957":6,"95th":6,"963":1,"965":6,"966":1,"967":1,"97":6,"973254086181":6,"973561430793":6,"98":[1,6],"982":6,"984":6,"98793e":5,"989637305699":6,"9896788990826":6,"989678899083":6,"99":[1,6],"990":6,"991":1,"992":[1,6],"993":1,"998":6,"999":1,"\u03bcs":1,"byte":5,"case":[1,3,5,6],"catch":1,"char":[1,5,6],"class":[0,5],"const":[1,5,6],"default":[5,6],"do":[4,5,6],"final":5,"function":[1,5,6],"import":6,"int":[1,3,6],"long":[1,5],"new":[1,5,6],"public":[0,5],"return":[1,5,6],"static":[1,5,6],"switch":5,"true":[5,6],"try":6,"var":6,"void":[1,5,6],"while":[1,6],A:[0,1,3,4,5],AND:4,AS:4,As:5,At:5,BE:4,BUT:4,Be:3,Being:0,But:5,FOR:4,For:[0,1,5,6],IN:4,IS:4,If:[5,6],In:[5,6],It:[1,5,6],NO:4,NOT:4,No:[0,1,6],Not:[1,5],OF:4,OR:4,On:[3,5,6],One:6,THE:4,TO:4,That:[5,6],The:[0,1,3,4,5,6],There:6,To:[5,6],WITH:4,With:[1,6],_:[0,1],a_i:5,abl:5,about:[0,1,5,6],abov:[4,5,6],absolut:5,abus:0,accept:0,access:5,account:0,accumul:6,accur:[3,5,6],accuraci:5,achiev:1,acl:6,act:0,action:[0,3,4],activ:1,actual:[5,6],adapt:0,add:5,add_execut:6,addition:5,address:0,advanc:[0,5],advantag:6,affect:0,after:[1,5,6],ag:[0,1],again:6,against:[3,5],aggress:0,algorithm:[5,6],alias:5,align:0,all:[0,1,4,5,6],allow:[0,5,6],alreadi:6,also:[0,5,6],altern:5,although:5,alwai:6,am:1,among:1,amount:6,an:[0,1,4,5,6],analysi:6,analyz:[5,6],ani:[0,4,5,6],ankerl:[0,1,3,4,6],ankerl_nanobench_impl:[1,3,6],anoth:3,answer:0,anyth:5,anywher:3,ap:5,apart:5,api:[1,3,5],apolog:0,app:5,appear:0,appli:[0,5],applic:[1,5],appoint:0,appropri:0,approx:5,approxim:[5,6],ar:[0,1,3,5,6],arg:[1,5],argument:5,aris:4,around:[0,5,6],artif:6,assert:1,assign:[5,6],associ:4,asymptot:5,atom:6,attach:5,attack:0,attent:0,author:4,auto:[1,5,6],automat:[1,5,6],autorang:6,autotun:1,avail:[0,5,6],averag:[1,3,5,6],avoid:0,awai:[1,5,6],awar:5,b:[5,6],b_i:5,bad:5,base:[5,6],baselin:[1,5,6],basic:[1,5],batch:[5,6],battl:1,becaus:[1,5,6],becom:5,been:[1,5],befor:5,begin:[5,6],behavior:[0,5],being:5,bench:[1,3,6],benchmark:3,benchmark_main:1,benchmarknam:5,benchmarktitl:5,best:[0,5,6],better:[5,6],between:[5,6],beyond:5,bia:5,bias:5,big:[5,6],bigo:[5,6],bit:[1,5],black:6,blog:5,bodi:[0,6],bool:5,boom:6,both:6,bound:5,box:5,boxplot:[5,6],boxpoint:6,bra:[1,3,6],branch:[3,5,6],branchinstruct:[5,6],branchmiss:[5,6],build:1,bulk:6,c:[1,3,4,6],cach:[1,5],calcul:[5,6],calibr:6,call:[1,5,6],can:[3,5,6],capabl:6,capac:5,captur:5,cast:5,catch_config_enable_benchmark:1,catch_config_main:1,catchorg:1,caus:5,cdn:6,cdot:5,chang:[5,6],channel:0,characterist:0,charg:4,chart:5,check:5,choic:5,choos:5,chosen:5,chrono:[1,5,6],chronomet:1,ci:[1,5],claim:[1,4],clarifi:0,clariti:0,clear:5,clearli:1,clock:[1,5,6],clockresolut:[5,6],clockresolutionmultipl:[5,6],close:5,cmake:1,cmake_cxx_standard:6,cmake_minimum_requir:6,cmakelist:6,cmakenanobenchexampl:6,coars:5,code:[3,5,6],coeffici:[5,6],collect:[1,5],com:[0,1,6],come:[1,5,6],comma:5,command:5,comment:0,commit:0,common:0,commun:0,compact:6,compar:5,compare_exchange_strong:6,compare_to:6,comparison:[1,6],comparison_fast:1,comparison_fluctuating_v2:1,comparison_slow:1,comparisonfast:1,comparisonfluctu:1,comparisonslow:1,compat:[5,6],compil:[1,3,5,6],complaint:0,complex:5,complexi:6,complexitybigo:[5,6],complexityn:[5,6],complic:1,compromis:5,condit:4,configur:[1,5,6],confus:1,connect:4,consequ:0,consid:0,consol:6,constexpr:6,construct:[0,5],constructor:5,contain:5,contend:5,context:5,contextswitch:[5,6],continu:0,contract:4,contribut:0,control:5,conveni:5,copi:[4,5],copyright:4,correct:5,correspond:5,could:[0,5,6],couldn:1,count:5,counter:5,cours:1,cout:[1,5,6],cpp:[1,6],cpu:[1,3,5,6],cpucycl:[5,6],crash:5,creat:[1,5,6],cryptograph:5,cstdint:1,curl:1,current:5,curv:6,custom:5,cxx:6,cyc:[1,3,6],cycl:[3,5,6],d:[1,3],damag:4,daniel:5,data:[1,5,6],databas:5,dataset:5,deal:[1,4],decai:1,decis:[0,3],decltyp:1,decreas:5,deem:0,default_random_engin:[5,6],defaultrng:6,defin:[1,3,5,6],definit:5,delet:5,demonstr:[0,6],depend:5,derogatori:0,describ:[1,5],descript:6,desir:5,destroi:5,detail:[5,6],determin:[0,5],determinist:[3,5],detial:5,dev:[1,6],develop:5,deviat:5,didn:1,differ:[0,1,5,6],dim:1,directli:[5,6],disabl:[0,5,6],disparag:0,displai:5,distort:5,distribut:[4,5],div:6,divers:0,doctest:6,document:4,doe:[1,6],doesn:[1,6],don:5,done:[5,6],donotoptim:1,donotoptimizeawai:[1,3,6],dot:[5,6],doubl:[3,5],down:1,download:[3,6],dramat:5,drop:5,dropdown:3,due:5,durat:[5,6],dure:0,e:[0,1,5,6],e_i:5,each:[1,5,6],eas:3,easi:[1,3,6],easili:[5,6],econom:0,edit:0,educ:0,effect:5,either:[5,6],elaps:[5,6],element:[5,6],els:3,email:0,empathi:0,enabl:[1,5],encount:5,end:[5,6],endl:[1,6],endless:5,enhanc:5,enorm:1,enough:5,entri:6,environ:0,environmen:5,epoch:[5,6],epochiter:[5,6],err:[1,3,5,6],error:[1,5,6],especi:6,estim:[1,5],etc:5,ethnic:0,evalu:[1,5,6],even:[5,6],event:[0,4,5,6],everyon:0,everyth:6,exact:5,exactli:[1,5],exampl:[0,1,5],example_pyperf:6,example_random_number_gener:6,excel:[5,6],except:5,excerpt:6,exclud:5,exclus:5,execut:[1,3,5,6],exist:6,expect:6,experi:0,explan:0,explicit:[0,5],express:[0,4],extern:[0,5],extra:1,extract:5,extrem:6,facebook:1,facil:[1,5],facilii:1,factor:6,fair:0,fairli:0,fals:[5,6],faq:0,far:5,fast:[1,3],faster:[1,5,6],fastest:[1,5,6],fault:1,featur:[1,5],feedback:0,fetchcont:6,fetchcontent_declar:6,fetchcontent_makeavail:6,few:[3,5,6],figur:1,file:[4,6],fill:6,filter:5,find:[1,5,6],fine:1,finish:5,first:[5,6],fit:[4,5,6],fix:6,fluctuat:[1,3,5,6],fn:1,focus:0,follow:[0,4,5,6],forc:5,form:5,format:[1,5,6],forward:1,found:1,fout1:6,fout2:6,frac:5,framework:[1,5,6],free:[0,4],frequenc:5,friendli:5,from:[0,1,4,5,6],fstream:6,full:[5,6],full_exampl:6,fulli:5,furnish:4,further:[5,6],futur:5,g:[1,5,6],gbench:1,gen:6,gender:0,gener:[5,6],get:[1,3,5,6],git:[1,6],git_repositori:6,git_shallow:6,git_tag:6,github:[1,3,6],githubusercont:1,give:[0,1,5,6],given:[1,5],global:1,gmail:0,goe:5,good:[1,5],googlebench:1,got:[1,6],gracefulli:0,grant:4,gritti:5,guarante:5,h:[1,3,6],ha:[1,5,6],had:1,half:5,hand:5,harass:0,hard:[1,5,6],hardcod:1,harm:0,hash:5,have:[0,1,5,6],hazzl:1,head:6,header:5,healthi:0,heavili:5,help:5,helper:5,here:[1,3,5,6],herebi:4,hierarchi:5,high:[1,5,6],higher:5,hist:6,hold:[5,6],holder:4,home:1,homepag:1,honestli:1,host:1,hotspot:5,how:[1,5,6],hpp:1,html:[0,5],htmlboxplot:6,http:[0,1,5,6],i7:1,i:[1,5,6],ibob:1,id:6,ident:0,ignor:5,imageri:0,immedi:[5,6],impact:0,implement:[5,6],impli:4,improv:5,inappropri:0,incid:0,includ:[0,1,3,4,5,6],inclus:0,increas:[1,5,6],incur:1,independ:3,indic:6,individu:[0,1,5],inflat:1,inform:[0,6],initi:[1,5],initializer_list:1,inlin:[5,6],inner_loop:6,input:[5,6],ins:[1,3,6],insert:6,inspect:5,inspir:[0,5],instal:1,instanc:[0,5,6],instanti:5,instead:[5,6],instruct:[1,3,5,6],insult:0,integ:5,integr:[1,3],intend:5,intent:1,interact:[0,5,6],interest:[1,5,6],interestingli:[1,6],intern:5,interpret:5,interv:5,invers:5,investig:0,invis:0,involv:[0,5,6],iostream:[1,6],ipc:[1,3,6],irrelev:5,isrelativeen:5,issu:0,iter:[1,5,6],itself:6,ivafana:1,javascript:5,job:5,js:6,just:[0,1,3,5,6],k:6,kind:[0,4,6],knuth_b:6,l1:1,l2:1,l3:1,l:1,ladder:0,lambda:5,languag:[0,6],larg:[5,6],last:[5,6],latest:[3,6],layer:5,layout:6,lazi:1,lb:1,lbenchmark:1,lead:0,leader:0,learn:0,least:[5,6],left:6,lemir:5,length:5,less:[5,6],let:6,letter:5,level:[0,6],lgit:1,liabil:4,liabl:4,lib:1,librari:[1,3],like:[0,1,3],limit:[4,5],line:[5,6],link:[1,3,6],linux:[5,6],littl:1,ll:6,load:1,lock:1,log2:5,log:[5,6],logarithm:6,logic:5,loglogn:5,longer:5,look:6,looong:1,loop:6,lot:1,low:[1,5,6],lpthread:1,lsltbench:1,ly:6,m:[1,5,6],machin:6,mad:6,mai:[0,1],mail:0,main:[1,3,6],maintain:1,major:1,make:[0,1,3,5,6],manual:[5,6],map:[5,6],margin:1,mark:5,markdown:[5,6],marker:5,martin:[0,4],martinu:[1,6],master:1,mathcal:[5,6],mathemat:5,mathrm:5,matter:6,maxepochtim:[5,6],maximum:[5,6],mayb:6,mb:1,mdape:5,me:1,mean:[1,5,6],meaning:5,meaningful:6,measuer:5,measur:[1,3,5,6],mechan:6,med:5,media:0,median:[5,6],medianabsolutepercenterror:[5,6],member:0,merchant:4,mere:5,merg:4,metadata:6,meter:1,method:5,metric:5,mhz:1,microbenchmark:[1,3],middl:5,might:[5,6],million:[3,6],millisecond:[1,3,6],min:6,minepochiter:[1,5,6],minepochtim:[5,6],minepociter:5,minimum:[5,6],miss:[1,3,5,6],misspredict:6,mistak:0,mix:5,mode:5,moder:0,modern:5,modifi:4,modul:5,modulo:5,more:[5,6],most:[5,6],mostli:[1,5],mozilla:0,ms:[1,5,6],mt19937:6,mt19937_64:[1,5,6],much:[1,5,6],multipl:[5,6],multipli:5,must:5,mustachetempl:[5,6],my:[1,5,6],my_exampl:6,mydiv:6,myexampl:6,n:[5,6],name:[1,3,5,6],namespac:6,nanobech:5,nanobench:6,nanonbech:1,nanosecond:[3,5],nasamrng:6,nation:0,natur:0,necessari:5,necessarili:[5,6],need:[1,5,6],nest:5,never:6,newplot:6,next:[5,6],nice:[5,6],nitti:5,noexcept:[5,6],noinlin:5,nois:5,noisi:1,non:5,none:[1,5],noninfring:4,nonius_benchmark:1,nonius_param:1,nonius_runn:1,nonius_singl:1,normal:5,notat:5,note:[5,6],notic:4,ns:[1,3,5,6],nullptr:[5,6],number:[1,5,6],numepoch:5,numit:5,numwarmupit:5,o2:1,o3:[1,6],o:[1,5,6],object:5,oblig:0,obtain:4,offens:0,offici:0,offlin:0,ofstream:6,often:[5,6],ok:1,old:6,onc:[5,6],one:[5,6],onli:[1,5,6],onlin:[0,1],op:[1,3,5,6],open:[0,5],oper:[1,5,6],opinion:0,optim:[1,5,6],option:[1,6],orbit:6,org:[0,5],orient:0,origin:5,os:5,ostream:5,other:[0,4,5],otherwis:[0,1,4,5],out:[1,4,5,6],outlier:[1,3,5,6],output:5,outstream:5,over:5,overal:0,overflow:6,overhead:[1,5],overton:5,overview:5,pagefault:[5,6],paper:[5,6],parallel:6,param:1,paramet:[1,5],part:5,particip:0,particular:4,pass:1,pattern:0,pb:1,peopl:0,per:[3,5,6],percent:5,percentag:[5,6],percentil:6,perf:[5,6],perf_event_paranoid:6,perfectli:6,perform:[1,5,6],performancecount:[5,6],period:0,permiss:[0,4,6],permit:4,person:[0,4],physic:0,picobench_implement_with_main:1,picobench_suit:1,platform:3,pleas:[5,6],plot:5,plotli:[5,6],plu:1,point:6,pointer:5,pointpo:6,polit:0,portion:4,posit:0,possibl:[3,5,6],post:[0,5],potenti:5,power:[3,5,6],practic:[5,6],precaus:5,precis:5,preconfigur:[5,6],predict:3,prefer:5,pressur:5,prevent:5,previous:5,print:[1,3,5,6],privaci:0,privat:[0,6],process:[5,6],processor:5,produc:[1,5,6],product:5,profession:0,profil:5,project:6,promptli:0,prone:1,properli:5,proven:1,provid:[0,1,4,5,6],pthread:1,publish:[0,4],pure:6,purpos:[4,5],pyperf:1,pyperf_shuffle_nanobench:6,pyperf_shuffle_std:6,python3:6,python:5,q1:6,q3:6,question:0,quit:[5,6],r:6,race:0,random:[1,5,6],random_devic:[1,5,6],randomli:[1,6],rang:5,rangemod:6,ranlux24:6,ranlux24_bas:6,ranlux48:6,ranlux48_bas:6,rather:[1,6],raw:[1,6],reach:5,read:[1,5],real:1,realli:[1,5,6],reason:[0,5,6],recent:1,record:6,red:6,reduc:5,reduct:5,regardless:0,regist:5,reject:[0,5],rel:[5,6],releas:[3,5,6],reli:5,reliabl:3,religion:0,remain:6,remov:[0,5],render:3,renderout:6,repeat:3,repeatedli:5,replac:5,report:[0,5],repres:0,represent:5,request:0,requir:[1,6],resid:6,resolut:[1,5],respect:0,respons:6,restrict:4,result:3,result_typ:5,retir:5,retriev:5,review:0,rich:1,right:[0,4],rm:5,rng1:6,rng2:6,rng:[1,6],robust:[3,5],romu:[5,6],romuduo:6,romuduojr:[5,6],romutrio:6,rotl:6,round:[1,5],row:5,run:[1,3,6],runner:6,runtim:[3,5,6],s:[0,1,3,5,6],safeti:5,same:5,sampl:[1,5],scale:[1,5,6],screen:1,script:6,sec:[1,5,6],second:[1,3,5,6],section:5,secur:[0,5],see:[0,5,6],seed:5,seem:[1,5],segment:1,sell:4,semicolon:6,sens:1,separ:[3,5],sequenc:5,seri:0,serial:5,seriou:0,set:[0,5,6],set_result:1,setsiz:6,sever:[1,6],sex:0,sexual:0,sfc4:6,shall:4,ship:5,shortcut:5,should:[5,6],shouldn:5,show:[1,5],showcas:6,showlegend:6,shown:5,showperformancecount:5,shuffl:[5,6],shuffle_pyperf:6,side:5,similar:1,simpl:[1,3,6],sinc:[5,6],singl:[0,1,3,5,6],singular:5,size:[0,5,6],size_t:5,skip:6,sleep:[1,6],sleep_for:[1,6],slight:5,slightli:5,slow:[1,5],slower:5,sltbench_funct:1,sltbench_main:1,small:5,smallest:5,smooth:5,so:[3,4,5,6],social:0,socio:0,softwar:4,some:[3,5,6],someth:[1,3,5],sometim:5,sort:[0,5,6],sound:3,sourc:5,space:0,special:5,specifi:[0,5],speed:5,splitmix64:5,squar:5,src:[1,6],stabl:[5,6],stai:5,standard:[5,6],start:[1,5],startup:1,stat:6,state:[1,5,6],statea:6,stateb:6,statist:[1,5],statu:[0,1],std:[1,5,6],still:[1,5,6],stop:5,store:5,straight:1,stream:5,streamabl:5,string:[5,6],struct:1,subject:4,sublicens:4,submodul:6,substanti:4,success:5,suggest:6,sum:[5,6],sum_:5,summari:5,sumproduct:[5,6],suppli:5,support:[1,6],suppress:5,sure:[1,5],sustain:0,system:[1,5,6],systemtim:1,t:[1,5,6],tabl:[5,6],tag:[5,6],take:[0,1,3,5,6],target:5,target_link_librari:6,templat:1,templatecont:5,templateout:6,term:0,test:6,test_cas:[1,6],text:6,than:[1,5],thank:6,thei:[0,5,6],them:6,theoret:6,therefor:6,thi:[0,1,4,5,6],thirdparti:6,this_thread:[1,6],those:0,though:[5,6],thread:[1,6],threaten:0,three:1,through:[0,6],throughout:5,thu:[5,6],time:[0,1,3,5,6],timer:5,timeunit:5,titl:[5,6],toggl:3,too:[1,5,6],took:[1,5,6],tool:[1,6],tort:4,total:[1,3,5,6],totaltim:6,toward:0,tozero:6,translat:0,tree:6,trick:5,troll:0,tu:5,tunam:5,tune:[1,5,6],tutori:5,tutorial_complexity_set:6,tutorial_complexity_set_find:6,tutorial_fast_v1:6,tutorial_fast_v2:6,tutorial_fluctuating_v1:6,tutorial_fluctuating_v2:6,tutorial_mustach:6,tutorial_render_simpl:6,tutorial_slow_v1:6,tutorial_slow_v2:6,twice:5,two:[5,6],txt:6,type:[1,5,6],typenam:[1,5,6],ub:1,uint32_t:5,uint64_c:[1,6],uint64_t:[1,5,6],unaccept:0,unaffect:1,unfortun:1,unifi:1,uniform01:5,uniform:5,uniform_int_distribut:6,uniformli:5,unit:[1,5,6],unless:5,unprofession:0,unreli:5,unsign:6,unsolicit:0,unstabl:1,unwelcom:0,up:[5,6],upgrad:6,upper:5,us:[0,1,3,4,5,6],usag:5,user:[5,6],usual:5,v2:1,v4:6,valu:5,variabl:[1,6],varianc:1,variat:5,ve:1,vector:[5,6],veri:[1,5,6],version:[0,6],via:0,view:3,viewpoint:0,violat:0,visibl:0,visual:6,volatil:1,volatilize_fn:1,wa:[0,1,6],wai:[0,1,5],wall:[5,6],want:[5,6],warm:5,warmup:[5,6],warn:[1,3,6],warranti:4,wavy_dash:[1,5,6],we:[0,5,6],welcom:0,well:0,were:[0,5,6],what:[0,5,6],whatev:5,when:[0,5,6],whenev:[5,6],where:[1,5,6],whether:4,which:[0,1,3,5,6],who:5,whole:[3,5,6],whom:4,why:[0,5],wiki:0,wise:5,within:[0,5],without:[0,4,5,6],work:1,would:[1,5],write:[1,5,6],written:0,wrote:1,www:[0,5],wyrng:6,x1:1,x6:1,x:[1,5,6],y:6,yaxi:6,you:[3,5,6],your:[5,6],yourapp:5,zero:5},titles:["Contributor Covenant Code of Conduct","Test Set","Index","nanobench","MIT License","ankerl::nanobench Reference","Installation"],titleterms:{"1":0,"2":0,"3":0,"4":0,No:5,ankerl:5,asymptot:6,attribut:0,ban:0,bench:5,benchmark:[1,5,6],box:6,catch2:1,celero:1,cmake:6,code:0,comma:6,compar:6,complex:6,conduct:0,contributor:0,correct:0,coven:0,csv:[5,6],design:3,direct:6,donotoptimizeawai:5,endlessli:5,enforc:0,entri:5,environ:5,exampl:6,extrem:5,fast:[5,6],folli:1,goal:3,googl:1,guidelin:0,histogram:6,html:6,htmlboxplot:5,implement:1,inclus:6,index:2,instal:6,integr:6,javascript:6,json:[5,6],licens:4,like:[5,6],main:5,microbench:1,mit:4,modul:6,moodycamel:1,mustach:[5,6],nanobench:[1,3,5],nanobench_endless:5,nanobench_suppress_warn:5,noniu:1,notat:6,object:6,our:0,output:[1,6],perman:0,picobench:1,pledg:0,plot:6,point:5,prng:5,pyperf:[5,6],python:6,refer:5,render:[5,6],respons:0,result:[1,5,6],rng:5,run:5,runtim:1,scope:0,separ:6,set:1,show:6,slow:6,sltbench:1,someth:6,sourcecod:1,specif:5,stabil:5,standard:0,statist:6,templat:[5,6],temporari:0,test:[1,5],unstabl:6,usag:6,valu:6,variabl:5,warn:[0,5]}}) \ No newline at end of file +Search.setIndex({docnames:["CODE_OF_CONDUCT","comparison","genindex","index","license","reference","tutorial"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":5,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["CODE_OF_CONDUCT.md","comparison.rst","genindex.rst","index.rst","license.rst","reference.rst","tutorial.rst"],objects:{"":[[5,0,1,"_CPPv4N6ankerl9nanobench5BenchE","ankerl::nanobench::Bench"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench5BenchEv","ankerl::nanobench::Bench::Bench"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench5batchER5Bench1T","ankerl::nanobench::Bench::batch"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench5batchER5Bench1T","ankerl::nanobench::Bench::batch::T"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench5batchER5Bench1T","ankerl::nanobench::Bench::batch::b"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench23clockResolutionMultipleE6size_t","ankerl::nanobench::Bench::clockResolutionMultiple"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench23clockResolutionMultipleE6size_t","ankerl::nanobench::Bench::clockResolutionMultiple::multiple"],[5,1,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op","ankerl::nanobench::Bench::complexityBigO"],[5,1,1,"_CPPv4NK6ankerl9nanobench5Bench14complexityBigOEv","ankerl::nanobench::Bench::complexityBigO"],[5,2,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op","ankerl::nanobench::Bench::complexityBigO::Op"],[5,3,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op","ankerl::nanobench::Bench::complexityBigO::name"],[5,3,1,"_CPPv4I0ENK6ankerl9nanobench5Bench14complexityBigOE4BigOPKc2Op","ankerl::nanobench::Bench::complexityBigO::op"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench11complexityNER5Bench1T","ankerl::nanobench::Bench::complexityN"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench11complexityNER5Bench1T","ankerl::nanobench::Bench::complexityN::T"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench11complexityNER5Bench1T","ankerl::nanobench::Bench::complexityN::b"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench17doNotOptimizeAwayER5BenchRR3Arg","ankerl::nanobench::Bench::doNotOptimizeAway"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench17doNotOptimizeAwayER5BenchRR3Arg","ankerl::nanobench::Bench::doNotOptimizeAway::Arg"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench17doNotOptimizeAwayER5BenchRR3Arg","ankerl::nanobench::Bench::doNotOptimizeAway::arg"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench15epochIterationsE8uint64_t","ankerl::nanobench::Bench::epochIterations"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench15epochIterationsE8uint64_t","ankerl::nanobench::Bench::epochIterations::numIters"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6epochsE6size_t","ankerl::nanobench::Bench::epochs"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6epochsE6size_t","ankerl::nanobench::Bench::epochs::numEpochs"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench12maxEpochTimeENSt6chrono11nanosecondsE","ankerl::nanobench::Bench::maxEpochTime"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench12maxEpochTimeENSt6chrono11nanosecondsE","ankerl::nanobench::Bench::maxEpochTime::t"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench18minEpochIterationsE8uint64_t","ankerl::nanobench::Bench::minEpochIterations"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench18minEpochIterationsE8uint64_t","ankerl::nanobench::Bench::minEpochIterations::numIters"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench12minEpochTimeENSt6chrono11nanosecondsE","ankerl::nanobench::Bench::minEpochTime"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench12minEpochTimeENSt6chrono11nanosecondsE","ankerl::nanobench::Bench::minEpochTime::t"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench4nameEPKc","ankerl::nanobench::Bench::name"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench4nameEPKc","ankerl::nanobench::Bench::name::benchmarkName"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6outputEPNSt7ostreamE","ankerl::nanobench::Bench::output"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6outputEPNSt7ostreamE","ankerl::nanobench::Bench::output::outstream"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench19performanceCountersEb","ankerl::nanobench::Bench::performanceCounters"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench19performanceCountersEb","ankerl::nanobench::Bench::performanceCounters::showPerformanceCounters"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench8relativeEb","ankerl::nanobench::Bench::relative"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench8relativeEb","ankerl::nanobench::Bench::relative::isRelativeEnabled"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6renderEPKcRNSt7ostreamE","ankerl::nanobench::Bench::render"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6renderEPKcRNSt7ostreamE","ankerl::nanobench::Bench::render::os"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6renderEPKcRNSt7ostreamE","ankerl::nanobench::Bench::render::templateContent"],[5,1,1,"_CPPv4NK6ankerl9nanobench5Bench7resultsEv","ankerl::nanobench::Bench::results"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchPKcRR2Op","ankerl::nanobench::Bench::run"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchRR2Op","ankerl::nanobench::Bench::run"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchPKcRR2Op","ankerl::nanobench::Bench::run::Op"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchRR2Op","ankerl::nanobench::Bench::run::Op"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchPKcRR2Op","ankerl::nanobench::Bench::run::benchmarkName"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchPKcRR2Op","ankerl::nanobench::Bench::run::op"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench5Bench3runER5BenchRR2Op","ankerl::nanobench::Bench::run::op"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench8timeUnitERKNSt6chrono8durationIdEERKNSt6stringE","ankerl::nanobench::Bench::timeUnit"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench8timeUnitERKNSt6chrono8durationIdEERKNSt6stringE","ankerl::nanobench::Bench::timeUnit::tu"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench8timeUnitERKNSt6chrono8durationIdEERKNSt6stringE","ankerl::nanobench::Bench::timeUnit::tuName"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench5titleEPKc","ankerl::nanobench::Bench::title"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench5titleEPKc","ankerl::nanobench::Bench::title::benchmarkTitle"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench4unitEPKc","ankerl::nanobench::Bench::unit"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench4unitEPKc","ankerl::nanobench::Bench::unit::unit"],[5,1,1,"_CPPv4N6ankerl9nanobench5Bench6warmupE8uint64_t","ankerl::nanobench::Bench::warmup"],[5,3,1,"_CPPv4N6ankerl9nanobench5Bench6warmupE8uint64_t","ankerl::nanobench::Bench::warmup::numWarmupIters"],[5,0,1,"_CPPv4N6ankerl9nanobench6ResultE","ankerl::nanobench::Result"],[5,0,1,"_CPPv4N6ankerl9nanobench3RngE","ankerl::nanobench::Rng"],[5,1,1,"_CPPv4N6ankerl9nanobench3Rng3RngE8uint64_t","ankerl::nanobench::Rng::Rng"],[5,1,1,"_CPPv4N6ankerl9nanobench3Rng3RngERK3Rng","ankerl::nanobench::Rng::Rng"],[5,1,1,"_CPPv4N6ankerl9nanobench3Rng3RngEv","ankerl::nanobench::Rng::Rng"],[5,3,1,"_CPPv4N6ankerl9nanobench3Rng3RngE8uint64_t","ankerl::nanobench::Rng::Rng::seed"],[5,1,1,"_CPPv4N6ankerl9nanobench3Rng7boundedE8uint32_t","ankerl::nanobench::Rng::bounded"],[5,3,1,"_CPPv4N6ankerl9nanobench3Rng7boundedE8uint32_t","ankerl::nanobench::Rng::bounded::range"],[5,1,1,"_CPPv4NK6ankerl9nanobench3Rng4copyEv","ankerl::nanobench::Rng::copy"],[5,1,1,"_CPPv4N6ankerl9nanobench3RngclEv","ankerl::nanobench::Rng::operator()"],[5,1,1,"_CPPv4N6ankerl9nanobench3RngaSERK3Rng","ankerl::nanobench::Rng::operator="],[5,4,1,"_CPPv4N6ankerl9nanobench3Rng11result_typeE","ankerl::nanobench::Rng::result_type"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench3Rng7shuffleEvR9Container","ankerl::nanobench::Rng::shuffle"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench3Rng7shuffleEvR9Container","ankerl::nanobench::Rng::shuffle::Container"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench3Rng7shuffleEvR9Container","ankerl::nanobench::Rng::shuffle::container"],[5,1,1,"_CPPv4NK6ankerl9nanobench3Rng5stateEv","ankerl::nanobench::Rng::state"],[5,1,1,"_CPPv4N6ankerl9nanobench3Rng9uniform01Ev","ankerl::nanobench::Rng::uniform01"],[5,1,1,"_CPPv4I0EN6ankerl9nanobench17doNotOptimizeAwayEvRR3Arg","ankerl::nanobench::doNotOptimizeAway"],[5,2,1,"_CPPv4I0EN6ankerl9nanobench17doNotOptimizeAwayEvRR3Arg","ankerl::nanobench::doNotOptimizeAway::Arg"],[5,3,1,"_CPPv4I0EN6ankerl9nanobench17doNotOptimizeAwayEvRR3Arg","ankerl::nanobench::doNotOptimizeAway::arg"],[5,1,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE","ankerl::nanobench::render"],[5,3,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE","ankerl::nanobench::render::bench"],[5,3,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE","ankerl::nanobench::render::mustacheTemplate"],[5,3,1,"_CPPv4N6ankerl9nanobench6renderEPKcRK5BenchRNSt7ostreamE","ankerl::nanobench::render::out"],[5,1,1,"_CPPv4N6ankerl9nanobench9templates3csvEv","ankerl::nanobench::templates::csv"],[5,1,1,"_CPPv4N6ankerl9nanobench9templates11htmlBoxplotEv","ankerl::nanobench::templates::htmlBoxplot"],[5,1,1,"_CPPv4N6ankerl9nanobench9templates4jsonEv","ankerl::nanobench::templates::json"],[5,1,1,"_CPPv4N6ankerl9nanobench9templates6pyperfEv","ankerl::nanobench::templates::pyperf"]]},objnames:{"0":["cpp","class","C++ class"],"1":["cpp","function","C++ function"],"2":["cpp","templateParam","C++ template parameter"],"3":["cpp","functionParam","C++ function parameter"],"4":["cpp","type","C++ type"]},objtypes:{"0":"cpp:class","1":"cpp:function","2":"cpp:templateParam","3":"cpp:functionParam","4":"cpp:type"},terms:{"0":[0,1,3,5,6],"00":[1,3,6],"000":1,"000167224":1,"000171959":6,"000217248":6,"000218811":6,"000661384":1,"00091350764819687":6,"001":1,"00116867939228672":6,"00169204737732657":6,"00297176820208024":6,"003":1,"0030441400304414":6,"00307692307692308":6,"00308166409861325":6,"0031104199066874":6,"0032520325203252":6,"0033003300330033":6,"00345423143350604":6,"0034662045061":6,"00347222222222222":6,"004":1,"00528169014084507":6,"007":6,"01":6,"010":1,"011887072808":6,"012":1,"012176560122":6,"012307692308":6,"012326656394":6,"012441679627":6,"0129533678757":6,"013008130081":6,"01319":1,"013201320132":6,"013536379019":6,"013816925734":6,"013888888889":6,"014084507042":6,"019":1,"02":6,"0236579384033733":6,"0296662546354":6,"03":[1,6],"035125448044942":6,"0426":1,"05":[1,5,6],"056":1,"059027777778":6,"06":[5,6],"061":1,"063":6,"068":[1,6],"07":[1,3,6],"071":6,"074":1,"079":1,"08":[5,6],"080":6,"081":6,"086":1,"08935e":5,"09":[5,6],"096":6,"099":6,"0th":6,"0xff":[1,6],"1":[1,3,5,6],"10":[1,5,6],"100":[1,5,6],"1000":[1,5,6],"10000000":1,"1000000000":1,"10000u":6,"1000u":6,"10055943":1,"10055959":1,"10088773":1,"100m":[5,6],"100th":6,"100u":6,"101":[1,6],"10113643":1,"10114054":1,"1013":1,"10137913":1,"1016":1,"102":6,"1041":1,"1057":1,"106":6,"10608e":5,"10742e":6,"108808290155":6,"109":1,"1090":1,"1098":1,"10k":6,"10m":1,"10u":6,"11":[1,3,5,6],"1103":1,"112":1,"113":6,"114":6,"115":6,"116":6,"117":6,"118":6,"1189":1,"11992392254248e":6,"12":[1,6],"121":6,"12288k":1,"123":6,"12414":1,"125":6,"12506e":1,"1258":1,"125m":6,"127":6,"128":[1,5,6],"12n":6,"13":[1,6],"130":6,"1302":1,"131":6,"1313":1,"132":[3,5],"133":3,"134":6,"1357":1,"136":[1,6],"1396":1,"14":[3,6],"141":6,"149":[1,6],"15":[5,6],"1551":1,"15683e":6,"156862745":1,"157":6,"159":1,"16":6,"161":1,"162":5,"167":6,"1679586563308":6,"168":6,"17":[3,6],"170":6,"177":6,"1777":1,"178":[1,6],"18":[1,6],"182":6,"183":1,"185":1,"18520325203252e":6,"18547854785479e":6,"18618307426598e":6,"187":6,"18769230769231e":6,"18973561430793e":6,"19":[1,6],"19013867488444e":6,"19049034175334e":6,"1912013536379e":6,"192":[1,6],"193":6,"19305555555556e":6,"19558599695586e":6,"1m":5,"1n":5,"2":[1,5,6],"20":[1,3,5],"200":[5,6],"2000u":6,"200u":6,"20126262626263e":6,"2019":[1,4],"202":1,"2022":4,"203":1,"204":1,"20480002":1,"205":6,"20n":5,"20u":6,"21":[1,6],"2137323943662e":6,"219":6,"22":1,"229832572298":6,"23":[1,6],"232":6,"233":1,"23305882352941e":6,"239":3,"24":[3,6],"24097693351425e":6,"2414":1,"24x":6,"25":[1,6],"25215e":1,"253":6,"25310880829016e":6,"254":6,"255":1,"2560000000":1,"256k":1,"259":1,"25th":6,"26":[1,6],"262":6,"2635658914729":6,"26465858909014e":6,"266033254157":6,"27":6,"2724":1,"274":1,"276":[3,6],"277":6,"279":6,"28":[1,6],"287":6,"29":[1,6],"291":6,"29307e":5,"2ghz":1,"2m":[5,6],"3":[1,5,6],"30":6,"31":[1,6],"3110098709":1,"312":6,"313":1,"3141104294":1,"318":6,"32":6,"32792e":6,"32bit":5,"32k":1,"33":6,"3324":1,"332892998679":6,"334":6,"334214002642":6,"338":6,"34":1,"343":1,"3479809976247":6,"35":[1,6],"3505882352941":6,"36":6,"3623737373737":6,"364":6,"365":1,"367":1,"37":6,"374491180461":6,"375":1,"38":6,"39":6,"391095":1,"391109":1,"391135":1,"3920":1,"392941176470588":6,"394":1,"396464646464646":6,"399":6,"3m":6,"4":[1,5,6],"40":6,"402":6,"40387e":6,"405440414507772":6,"4096":1,"41":6,"412":6,"417910447761194":6,"42":6,"420454545455":6,"424":6,"43":6,"431":6,"44":6,"444":6,"446":6,"45":1,"451":1,"46":[5,6],"4600":1,"462351387054":6,"469":1,"46985e":5,"47":5,"472":6,"47588e":6,"48":6,"48121":5,"486":6,"48677e":5,"49":6,"490":6,"492":6,"4952":1,"497":6,"5":[1,3,5,6],"50":[1,5,6],"500":6,"5000":6,"5000u":6,"500u":6,"502":6,"50619e":1,"509":1,"50th":6,"50u":6,"51":[1,5,6],"512":1,"512000000":1,"514":6,"51982200647249e":6,"52":3,"524":1,"529":6,"5290482076638":6,"53":[1,6],"531":6,"53405963302752e":6,"539":1,"54":6,"54441805225653e":6,"54708571428571e":6,"55":[1,6],"55985915493":6,"56":6,"563073394495413":6,"56376":1,"564133016627078":6,"565":1,"567":6,"568":6,"57":6,"570":1,"574857142857143":6,"575":1,"575539568345324":6,"576":6,"576227390181":6,"579":6,"57n":6,"58":[1,6],"580":6,"5814":1,"582":6,"582200247218789":6,"5823529411765":6,"58467243510507e":6,"59":6,"590439276485788":6,"591":6,"59256594724221e":6,"595":6,"5th":6,"6":[1,3,5,6],"60":[1,6],"606":6,"60607235142119e":6,"60m":[3,6],"61":6,"610":1,"611sec":1,"615":6,"618229854689564":6,"62":6,"621":6,"629":6,"629411764706":6,"63":6,"635491606715":6,"638":6,"63870541611625e":6,"63n":6,"64":[1,5],"643":6,"6431478968792":6,"644485":1,"649":6,"64bit":[5,6],"64u":6,"65":3,"650":6,"655":6,"657":6,"66":[1,6],"661":6,"66562e":6,"67":6,"673":6,"69":[5,6],"693":6,"699":6,"7":[1,3,6],"70":6,"706946":1,"709":[1,6],"71":6,"713sec":1,"714":6,"715":1,"72":6,"73":1,"733":6,"737":[1,6],"740":1,"741":1,"744":1,"75":6,"753":6,"757":6,"7580275229358":6,"7588383838384":6,"759":6,"75th":6,"761":6,"764":6,"7645714285714":6,"7661870503597":6,"767":6,"768":6,"77":6,"771322620519":6,"772":6,"774":6,"78":6,"782":1,"786":6,"79":[1,3,6],"792":6,"797":6,"8":[1,3,5,6],"80":6,"803":1,"809":6,"81":6,"810":1,"812":6,"815":[1,6],"8192":1,"819sec":1,"82":6,"820":6,"824":6,"825":1,"827":1,"828sec":1,"83":6,"833":6,"834":6,"8341968911917":6,"83498349835":6,"84":6,"842":6,"844":1,"85":6,"850":6,"850539291217":6,"853":6,"858536585366":6,"86":[1,6],"862":6,"87":6,"8700":1,"872":6,"875":6,"88":1,"881":6,"88133e":5,"883sec":1,"885":6,"885714285714":6,"8859857482185":6,"889":6,"89":6,"898461538462":6,"8e":6,"9":[1,3,5,6],"90":6,"906222":1,"909957":1,"90m":6,"91":6,"911":6,"916619":1,"924":6,"93":6,"9352517985612":6,"94":6,"944162436548":6,"945584":1,"9470827679783":6,"948":3,"95":1,"957":6,"95th":6,"963":1,"965":6,"966":1,"967":1,"97":6,"973254086181":6,"973561430793":6,"98":[1,6],"982":6,"984":6,"98793e":5,"989637305699":6,"9896788990826":6,"989678899083":6,"99":[1,6],"990":6,"991":1,"992":[1,6],"993":1,"998":6,"999":1,"\u03bcs":1,"byte":5,"case":[1,3,5,6],"catch":1,"char":[1,5,6],"class":[0,5],"const":[1,5,6],"default":[5,6],"do":[4,5,6],"final":5,"function":[1,5,6],"import":6,"int":[1,3,6],"long":[1,5],"new":[1,5,6],"public":[0,5],"return":[1,5,6],"static":[1,5,6],"switch":5,"true":[5,6],"try":6,"var":6,"void":[1,5,6],"while":[1,6],A:[0,1,3,4,5],AND:4,AS:4,As:[5,6],At:5,BE:4,BUT:4,Be:3,Being:0,But:5,FOR:4,For:[0,1,5,6],IN:4,IS:4,If:[5,6],In:[5,6],It:[1,5,6],NO:4,NOT:4,No:[0,1,6],Not:[1,5],OF:4,OR:4,On:[3,5,6],One:6,THE:4,TO:4,That:[5,6],The:[0,1,3,4,5,6],There:6,To:[5,6],WITH:4,With:[1,6],_:[0,1],a_i:5,abl:5,about:[0,1,5,6],abov:[4,5,6],absolut:5,abus:0,accept:0,access:5,account:0,accumul:6,accur:[3,5,6],accuraci:5,achiev:1,acl:6,act:0,action:[0,3,4],activ:1,actual:[5,6],adapt:0,add:5,add_execut:6,addition:5,address:0,advanc:[0,5],advantag:6,affect:0,after:[1,5,6],ag:[0,1],again:6,against:[3,5],aggress:0,algorithm:[5,6],alias:5,align:0,all:[0,1,4,5,6],allow:[0,5,6],alreadi:6,also:[0,5,6],altern:5,although:5,alwai:6,am:1,among:1,amount:6,an:[0,1,4,5,6],analysi:6,analyz:[5,6],ani:[0,4,5,6],ankerl:[0,1,3,4,6],ankerl_nanobench_impl:[1,3,6],anoth:3,answer:0,anyth:5,anywher:3,ap:5,apart:5,api:[1,3,5],apolog:0,app:5,appear:0,appli:[0,5],applic:[1,5],appoint:0,appropri:0,approx:5,approxim:[5,6],ar:[0,1,3,5,6],arg:[1,5],argument:5,aris:4,around:[0,5,6],artif:6,assert:1,assign:[5,6],associ:4,asymptot:5,atom:6,attach:5,attack:0,attent:0,author:4,auto:[1,5,6],automat:[1,5,6],autorang:6,autotun:1,avail:[0,5,6],averag:[1,3,5,6],avoid:0,awai:[1,5,6],awar:5,b:[5,6],b_i:5,bad:5,base:[5,6],baselin:[1,5,6],basic:[1,5],batch:[5,6],battl:1,becaus:[1,5,6],becom:5,been:[1,5],befor:5,begin:[5,6],behavior:[0,5],being:5,bench:[1,3,6],benchmark:3,benchmark_main:1,benchmarknam:5,benchmarktitl:5,best:[0,5,6],better:[5,6],between:[5,6],beyond:5,bia:5,bias:5,big:[5,6],bigo:[5,6],bit:[1,5],black:6,blog:5,bodi:[0,6],bool:5,boom:6,both:6,bound:5,box:5,boxplot:[5,6],boxpoint:6,bra:[1,3,6],branch:[3,5,6],branchinstruct:[5,6],branchmiss:[5,6],build:1,bulk:6,c:[1,3,4,6],cach:[1,5],calcul:[5,6],calibr:6,call:[1,5,6],can:[3,5,6],capabl:6,capac:5,captur:5,cast:5,catch_config_enable_benchmark:1,catch_config_main:1,catchorg:1,caus:5,cdn:6,cdot:5,chang:[5,6],channel:0,characterist:0,charg:4,chart:5,check:5,choic:5,choos:5,chosen:5,chrono:[1,5,6],chronomet:1,ci:[1,5],claim:[1,4],clarifi:0,clariti:0,clear:5,clearli:1,clock:[1,5,6],clockresolut:[5,6],clockresolutionmultipl:[5,6],close:5,cmake:1,cmake_cxx_standard:6,cmake_minimum_requir:6,cmakelist:6,cmakenanobenchexampl:6,coars:5,code:[3,5,6],coeffici:[5,6],collect:[1,5],com:[0,1,6],come:[1,5,6],comma:5,command:5,comment:0,commit:0,common:0,commun:0,compact:6,compar:5,compare_exchange_strong:6,compare_to:6,comparison:[1,6],comparison_fast:1,comparison_fluctuating_v2:1,comparison_slow:1,comparisonfast:1,comparisonfluctu:1,comparisonslow:1,compat:[5,6],compil:[1,3,5,6],complaint:0,complex:5,complexi:6,complexitybigo:[5,6],complexityn:[5,6],complic:1,compromis:5,condit:4,configur:[1,5,6],confus:1,connect:4,consequ:0,consid:0,consol:6,constexpr:6,construct:[0,5],constructor:5,contain:5,contend:5,context:5,contextswitch:[5,6],continu:0,contract:4,contribut:0,control:5,conveni:5,copi:[4,5],copyright:4,correct:5,correspond:5,could:[0,5,6],couldn:1,count:5,counter:5,cours:1,cout:[1,5,6],cpp:[1,6],cpu:[1,3,5,6],cpucycl:[5,6],crash:5,creat:[1,5,6],cryptograph:5,cstdint:1,curl:1,current:5,curv:6,custom:5,cxx:6,cyc:[1,3,6],cycl:[3,5,6],d:[1,3],damag:4,daniel:5,data:[1,5,6],databas:5,dataset:5,deal:[1,4],decai:1,decis:[0,3],decltyp:1,decreas:5,deem:0,default_random_engin:[5,6],defaultrng:6,defin:[1,3,5,6],definit:5,delet:5,demonstr:[0,6],depend:5,derogatori:0,describ:[1,5],descript:6,desir:5,destroi:5,detail:[5,6],determin:[0,5],determinist:[3,5],dev:[1,6],develop:5,deviat:5,didn:1,differ:[0,1,5,6],dim:1,directli:[5,6],disabl:[0,5,6],disparag:0,displai:5,distort:5,distribut:[4,5],div:6,divers:0,doctest:6,document:4,doe:[1,6],doesn:[1,6],don:5,done:[5,6],donotoptim:1,donotoptimizeawai:[1,3,6],dot:[5,6],doubl:[3,5],down:1,download:[3,6],dramat:5,drop:5,dropdown:3,due:5,durat:[5,6],dure:0,e:[0,1,5,6],e_i:5,each:[1,5,6],eas:3,easi:[1,3,6],easili:[5,6],econom:0,edit:0,educ:0,effect:5,either:[5,6],elaps:[5,6],element:[5,6],els:3,email:0,empathi:0,enabl:[1,5,6],encount:5,end:[5,6],endl:[1,6],endless:5,enhanc:5,enorm:1,enough:5,entri:6,environ:0,environmen:5,epoch:[5,6],epochiter:[5,6],err:[1,3,5,6],error:[1,5,6],especi:6,estim:[1,5],etc:5,ethnic:0,evalu:[1,5,6],even:[5,6],event:[0,4,5,6],everyon:0,everyth:6,exact:5,exactli:[1,5],exampl:[0,1,5],example_pyperf:6,example_random_number_gener:6,excel:[5,6],except:5,excerpt:6,exclud:5,exclus:5,execut:[1,3,5,6],exist:6,expect:6,experi:0,explan:0,explicit:[0,5],express:[0,4],extern:[0,5],extra:1,extract:5,extrem:6,facebook:1,facil:[1,5],facilii:1,factor:6,fair:0,fairli:0,fals:[5,6],faq:0,far:5,fast:[1,3],faster:[1,5,6],fastest:[1,5,6],fault:1,featur:[1,5],feedback:0,fetchcont:6,fetchcontent_declar:6,fetchcontent_makeavail:6,few:[3,5,6],figur:1,file:[4,6],fill:6,filter:5,find:[1,5,6],fine:1,finish:5,first:[5,6],fit:[4,5,6],fix:6,fluctuat:[1,3,5,6],fn:1,focus:0,follow:[0,4,5,6],forc:5,form:5,format:[1,5,6],forward:1,found:1,fout1:6,fout2:6,frac:5,framework:[1,5,6],free:[0,4],frequenc:5,friendli:5,from:[0,1,4,5,6],fstream:6,full:[5,6],full_exampl:6,fulli:5,furnish:4,further:[5,6],futur:5,g:[1,5,6],gbench:1,gen:6,gender:0,gener:[5,6],get:[1,3,5,6],git:[1,6],git_repositori:6,git_shallow:6,git_tag:6,github:[1,3,6],githubusercont:1,give:[0,1,5,6],given:[1,5],global:1,gmail:0,goe:5,good:[1,5],googlebench:1,got:[1,6],gracefulli:0,grant:4,gritti:5,guarante:5,h:[1,3,6],ha:[1,5,6],had:1,half:5,hand:5,harass:0,hard:[1,5,6],hardcod:1,harm:0,hash:5,have:[0,1,5,6],hazzl:1,head:6,header:5,healthi:0,heavili:5,help:5,helper:5,here:[1,3,5,6],herebi:4,hierarchi:5,high:[1,5,6],higher:5,hist:6,hold:[5,6],holder:4,home:1,homepag:1,honestli:1,host:1,hotspot:5,how:[1,5,6],hpp:1,html:[0,5],htmlboxplot:6,http:[0,1,5,6],i7:1,i:[1,5,6],ibob:1,id:6,ident:0,ignor:5,imageri:0,immedi:[5,6],impact:0,implement:[5,6],impli:4,improv:5,inappropri:0,incid:0,includ:[0,1,3,4,5,6],inclus:0,increas:[1,5,6],incur:1,independ:3,indic:6,individu:[0,1,5],inflat:1,inform:[0,6],initi:[1,5],initializer_list:1,inlin:[5,6],inner_loop:6,input:[5,6],ins:[1,3,6],insert:6,inspect:5,inspir:[0,5],instal:1,instanc:[0,5,6],instanti:5,instead:[5,6],instruct:[1,3,5,6],insult:0,integ:5,integr:[1,3],intend:5,intent:1,interact:[0,5,6],interest:[1,5,6],interestingli:[1,6],intern:5,interpret:5,interv:5,invers:5,investig:0,invis:0,involv:[0,5,6],iostream:[1,6],ipc:[1,3,6],irrelev:5,isrelativeen:5,issu:0,iter:[1,5,6],itself:6,ivafana:1,javascript:5,job:5,js:6,just:[0,1,3,5,6],k:6,keep:6,kind:[0,4,6],knuth_b:6,l1:1,l2:1,l3:1,l:1,ladder:0,lambda:5,languag:[0,6],larg:[5,6],last:[5,6],latest:[3,6],layer:5,layout:6,lazi:1,lb:1,lbenchmark:1,lead:0,leader:0,learn:0,least:[5,6],left:6,lemir:5,length:5,less:[5,6],let:6,letter:5,level:[0,6],lgit:1,liabil:4,liabl:4,lib:1,librari:[1,3],like:[0,1,3],limit:[4,5],line:[5,6],link:[1,3,6],linux:[5,6],littl:1,ll:6,load:1,lock:1,log2:5,log:[5,6],logarithm:6,logic:5,loglogn:5,longer:5,look:6,looong:1,loop:6,lot:1,low:[1,5,6],lpthread:1,lsltbench:1,ly:6,m:[1,5,6],machin:6,mad:6,mai:[0,1],mail:0,main:[1,3,6],maintain:1,major:1,make:[0,1,3,5,6],manual:[5,6],map:[5,6],margin:1,mark:5,markdown:[5,6],marker:5,martin:[0,4],martinu:[1,6],master:1,mathcal:[5,6],mathemat:5,mathrm:5,matter:6,maxepochtim:[5,6],maximum:[5,6],mayb:6,mb:1,mdape:5,me:1,mean:[1,5,6],meaning:5,meaningful:6,measuer:5,measur:[1,3,5,6],mechan:6,med:5,media:0,median:[5,6],medianabsolutepercenterror:[5,6],member:0,merchant:4,mere:5,merg:4,metadata:6,meter:1,method:5,metric:5,mhz:1,microbenchmark:[1,3],middl:5,might:[5,6],million:[3,6],millisecond:[1,3,6],min:6,minepochiter:[1,5,6],minepochtim:[5,6],minimum:[5,6],miss:[1,3,5,6],misspredict:6,mistak:0,mix:5,mode:5,moder:0,modern:5,modifi:4,modul:5,modulo:5,more:[5,6],most:[5,6],mostli:[1,5],mozilla:0,ms:[1,5,6],mt19937:6,mt19937_64:[1,5,6],much:[1,5,6],multipl:[5,6],multipli:5,must:5,mustachetempl:[5,6],my:[1,5,6],my_exampl:6,mydiv:6,myexampl:6,n:[5,6],name:[1,3,5,6],namespac:6,nanobech:5,nanobench:6,nanonbech:1,nanosecond:[3,5],nasamrng:6,nation:0,natur:0,necessari:5,necessarili:[5,6],need:[1,5,6],nest:5,never:6,newplot:6,next:[5,6],nice:[5,6],nitti:5,noexcept:[5,6],noinlin:5,nois:5,noisi:1,non:5,none:[1,5],noninfring:4,nonius_benchmark:1,nonius_param:1,nonius_runn:1,nonius_singl:1,normal:5,notat:5,note:[5,6],notic:4,ns:[1,3,5,6],nullptr:[5,6],number:[1,5,6],numepoch:5,numit:5,numwarmupit:5,o2:1,o3:[1,6],o:[1,5,6],object:5,oblig:0,obtain:4,offens:0,offici:0,offlin:0,ofstream:6,often:[5,6],ok:1,old:6,onc:[5,6],one:[5,6],onli:[1,5,6],onlin:[0,1],op:[1,3,5,6],open:[0,5],oper:[1,5,6],opinion:0,optim:[1,5,6],option:[1,6],orbit:6,org:[0,5],orient:0,origin:5,os:5,ostream:5,other:[0,4,5],otherwis:[0,1,4,5],out:[1,4,5,6],outlier:[1,3,5,6],output:5,outstream:5,over:5,overal:0,overflow:6,overhead:[1,5],overton:5,overview:5,pagefault:[5,6],paper:[5,6],parallel:6,param:1,paramet:[1,5],part:5,particip:0,particular:4,pass:1,pattern:0,pb:1,peopl:0,per:[3,5,6],percent:5,percentag:[5,6],percentil:6,perf:[5,6],perf_event_paranoid:6,perfectli:6,perform:[1,5,6],performancecount:[5,6],period:0,permiss:[0,4,6],permit:4,person:[0,4],physic:0,picobench_implement_with_main:1,picobench_suit:1,platform:3,pleas:[5,6],plot:5,plotli:[5,6],plu:1,point:6,pointer:5,pointpo:6,polit:0,portion:4,posit:0,possibl:[3,5,6],post:[0,5],potenti:5,power:[3,5,6],practic:[5,6],precaus:5,precis:5,preconfigur:[5,6],predict:3,prefer:5,pressur:5,prevent:5,previous:5,print:[1,3,5,6],privaci:0,privat:[0,6],process:[5,6],processor:5,produc:[1,5,6],product:5,profession:0,profil:5,project:6,promptli:0,prone:1,properli:5,proven:1,provid:[0,1,4,5,6],pthread:1,publish:[0,4],pure:6,purpos:[4,5],pyperf:1,pyperf_shuffle_nanobench:6,pyperf_shuffle_std:6,python3:6,python:5,q1:6,q3:6,question:0,quit:[5,6],r:6,race:0,random:[1,5,6],random_devic:[1,5,6],randomli:[1,6],rang:5,rangemod:6,ranlux24:6,ranlux24_bas:6,ranlux48:6,ranlux48_bas:6,rather:[1,6],raw:[1,6],reach:5,read:[1,5],real:1,realli:[1,5,6],reason:[0,5,6],recent:1,record:6,red:6,reduc:5,reduct:5,regardless:0,regist:5,reject:[0,5],rel:[5,6],releas:[3,5,6],reli:5,reliabl:3,religion:0,remain:6,remov:[0,5],render:3,renderout:6,repeat:3,repeatedli:5,replac:5,report:[0,5],repres:0,represent:5,request:0,requir:[1,6],resid:6,resolut:[1,5],respect:0,respons:6,restrict:4,result:3,result_typ:5,retir:5,retriev:5,review:0,rich:1,right:[0,4],rm:5,rng1:6,rng2:6,rng:[1,6],robust:[3,5],romu:[5,6],romuduo:6,romuduojr:[5,6],romutrio:6,rotl:6,round:[1,5],row:5,run:[1,3,6],runner:6,runtim:[3,5,6],s:[0,1,3,5,6],safeti:5,same:5,sampl:[1,5],scale:[1,5,6],screen:1,script:6,sec:[1,5,6],second:[1,3,5,6],section:5,secur:[0,5],see:[0,5,6],seed:5,seem:[1,5],segment:1,sell:4,semicolon:6,sens:1,separ:[3,5],sequenc:5,seri:0,serial:5,seriou:0,set:[0,5,6],set_result:1,setsiz:6,sever:[1,6],sex:0,sexual:0,sfc4:6,shall:4,ship:5,shortcut:5,should:[5,6],shouldn:5,show:[1,5],showcas:6,showlegend:6,shown:5,showperformancecount:5,shuffl:[5,6],shuffle_pyperf:6,side:5,similar:1,simpl:[1,3,6],sinc:[5,6],singl:[0,1,3,5,6],singular:5,size:[0,5,6],size_t:5,skip:6,sleep:[1,6],sleep_for:[1,6],slight:5,slightli:5,slow:[1,5],slower:5,sltbench_funct:1,sltbench_main:1,small:5,smallest:5,smooth:5,so:[3,4,5,6],social:0,socio:0,softwar:4,some:[3,5,6],someth:[1,3,5],sometim:5,sort:[0,5,6],sound:3,sourc:5,space:0,special:5,specifi:[0,5],speed:5,splitmix64:5,squar:5,src:[1,6],stabl:[5,6],stai:5,standard:[5,6],start:[1,5],startup:1,stat:6,state:[1,5,6],statea:6,stateb:6,statist:[1,5],statu:[0,1],std:[1,5,6],still:[1,5,6],stop:5,store:5,straight:1,stream:5,streamabl:5,string:[5,6],struct:1,subject:4,sublicens:4,submodul:6,substanti:4,success:5,suggest:6,sum:[5,6],sum_:5,summari:5,sumproduct:[5,6],suppli:5,support:[1,6],suppress:5,sure:[1,5],sustain:0,system:[1,5,6],systemtim:1,t:[1,5,6],tabl:[5,6],tag:[5,6],take:[0,1,3,5,6],target:5,target_link_librari:6,templat:1,templatecont:5,templateout:6,term:0,test:6,test_cas:[1,6],text:6,than:[1,5],thank:6,thei:[0,5,6],them:6,theoret:6,therefor:6,thi:[0,1,4,5,6],thirdparti:6,this_thread:[1,6],those:0,though:[5,6],thread:[1,6],threaten:0,three:1,through:[0,6],throughout:5,thu:[5,6],time:[0,1,3,5,6],timer:5,timeunit:5,titl:[5,6],toggl:3,too:[1,5,6],took:[1,5,6],tool:[1,6],tort:4,total:[1,3,5,6],totaltim:6,toward:0,tozero:6,translat:0,tree:6,trick:5,troll:0,tu:5,tunam:5,tune:[1,5,6],tutori:5,tutorial_complexity_set:6,tutorial_complexity_set_find:6,tutorial_fast_v1:6,tutorial_fast_v2:6,tutorial_fluctuating_v1:6,tutorial_fluctuating_v2:6,tutorial_mustach:6,tutorial_render_simpl:6,tutorial_slow_v1:6,tutorial_slow_v2:6,twice:5,two:[5,6],txt:6,type:[1,5,6],typenam:[1,5,6],ub:1,uint32_t:5,uint64_c:[1,6],uint64_t:[1,5,6],unaccept:0,unaffect:1,unfortun:1,unifi:1,uniform01:5,uniform:5,uniform_int_distribut:6,uniformli:5,unit:[1,5,6],unless:5,unprofession:0,unreli:5,unsign:6,unsolicit:0,unstabl:1,unwelcom:0,up:[5,6],upgrad:6,upper:5,us:[0,1,3,4,5,6],usag:5,user:[5,6],usual:5,v2:1,v4:6,valu:5,variabl:[1,6],varianc:1,variat:5,ve:1,vector:[5,6],veri:[1,5,6],version:[0,6],via:0,view:3,viewpoint:0,violat:0,visibl:0,visual:6,volatil:1,volatilize_fn:1,wa:[0,1,6],wai:[0,1,5],wall:[5,6],want:[5,6],warm:5,warmup:[5,6],warn:[1,3,6],warranti:4,wavy_dash:[1,5,6],we:[0,5,6],welcom:0,well:0,were:[0,5,6],what:[0,5,6],whatev:5,when:[0,5,6],whenev:[5,6],where:[1,5,6],whether:4,which:[0,1,3,5,6],who:5,whole:[3,5,6],whom:4,why:[0,5],wiki:0,wise:5,within:[0,5],without:[0,4,5,6],work:1,would:[1,5],write:[1,5,6],written:0,wrote:1,www:[0,5],wyrng:6,x1:1,x6:1,x:[1,5,6],y:6,yaxi:6,you:[3,5,6],your:[5,6],yourapp:5,zero:5},titles:["Contributor Covenant Code of Conduct","Test Set","Index","nanobench","MIT License","ankerl::nanobench Reference","Installation"],titleterms:{"1":0,"2":0,"3":0,"4":0,No:5,ankerl:5,asymptot:6,attribut:0,ban:0,bench:5,benchmark:[1,5,6],box:6,catch2:1,celero:1,cmake:6,code:0,comma:6,compar:6,complex:6,conduct:0,contributor:0,correct:0,coven:0,csv:[5,6],design:3,direct:6,donotoptimizeawai:5,endlessli:5,enforc:0,entri:5,environ:5,exampl:6,extrem:5,fast:[5,6],folli:1,goal:3,googl:1,guidelin:0,histogram:6,html:6,htmlboxplot:5,implement:1,inclus:6,index:2,instal:6,integr:6,javascript:6,json:[5,6],licens:4,like:[5,6],main:5,microbench:1,mit:4,modul:6,moodycamel:1,mustach:[5,6],nanobench:[1,3,5],nanobench_endless:5,nanobench_suppress_warn:5,noniu:1,notat:6,object:6,our:0,output:[1,6],perman:0,picobench:1,pledg:0,plot:6,point:5,prng:5,pyperf:[5,6],python:6,refer:5,render:[5,6],respons:0,result:[1,5,6],rng:5,run:5,runtim:1,scope:0,separ:6,set:1,show:6,slow:6,sltbench:1,someth:6,sourcecod:1,specif:5,stabil:5,standard:0,statist:6,templat:[5,6],temporari:0,test:[1,5],unstabl:6,usag:6,valu:6,variabl:5,warn:[0,5]}}) \ No newline at end of file diff --git a/docs/tutorial.html b/docs/tutorial.html index 5d94739..2ee4a29 100644 --- a/docs/tutorial.html +++ b/docs/tutorial.html @@ -33,7 +33,7 @@
    - v4.3.6 + v4.3.7
    @@ -211,26 +211,26 @@

    CMake Integrationgit submodule. Here is a full example how to this can be done:

    CMakeLists.txt
    -
     1cmake_minimum_required(VERSION 3.14)
    - 2set(CMAKE_CXX_STANDARD 17)
    +
     1cmake_minimum_required(VERSION 3.14)
    + 2set(CMAKE_CXX_STANDARD 17)
      3
      4project(
    - 5    CMakeNanobenchExample
    - 6    VERSION 1.0
    - 7    LANGUAGES CXX)
    + 5    CMakeNanobenchExample
    + 6    VERSION 1.0
    + 7    LANGUAGES CXX)
      8
      9include(FetchContent)
     10
     11FetchContent_Declare(
    -12    nanobench
    -13    GIT_REPOSITORY https://github.com/martinus/nanobench.git
    -14    GIT_TAG v4.1.0
    -15    GIT_SHALLOW TRUE)
    +12    nanobench
    +13    GIT_REPOSITORY https://github.com/martinus/nanobench.git
    +14    GIT_TAG v4.1.0
    +15    GIT_SHALLOW TRUE)
     16
     17FetchContent_MakeAvailable(nanobench)
     18
    -19add_executable(MyExample my_example.cpp)
    -20target_link_libraries(MyExample PRIVATE nanobench)
    +19add_executable(MyExample my_example.cpp)
    +20target_link_libraries(MyExample PRIVATE nanobench)
     
    @@ -495,7 +495,8 @@

    Something Unstable

    Comparing Results

    -

    I have implemented a comparison of multiple random number generators. +

    To compare results, keep the ankerl::nanobench::Bench object around, enable .relative(true), and .run(…) your benchmarks. All benchmarks will be automatically compared to the first one.

    +

    As an example, I have implemented a comparison of multiple random number generators. Here several RNGs are compared to a baseline calculated from std::default_random_engine. I factored out the general benchmarking code so it’s easy to use for each of the random number generators:

    @@ -512,7 +513,7 @@

    Something Unstable10namespace { 11 12// Benchmarks how fast we can get 64bit random values from Rng. -13template <typename Rng> +13template <typename Rng> 14void bench(ankerl::nanobench::Bench* bench, char const* name) { 15 std::random_device dev; 16 Rng rng(dev()); @@ -613,7 +614,7 @@

    Something Unstable15 std::set<uint64_t> set; 16 17 // Running the benchmark multiple times, with different number of elements -18 for (auto setSize : +18 for (auto setSize : 19 {10U, 20U, 50U, 100U, 200U, 500U, 1000U, 2000U, 5000U, 10000U}) { 20 21 // fill up the set with random data @@ -913,284 +914,284 @@

    Something Unstableankerl::nanobench::Bench::epochs(), not just the accumulated data as in the CSV template.

    -
      1{
    -  2    "results": [
    -  3        {
    -  4            "title": "Benchmarking std::mt19937_64 and std::knuth_b",
    -  5            "name": "std::mt19937_64",
    -  6            "unit": "op",
    -  7            "batch": 1,
    -  8            "complexityN": -1,
    -  9            "epochs": 11,
    - 10            "clockResolution": 1.8e-08,
    - 11            "clockResolutionMultiple": 1000,
    - 12            "maxEpochTime": 0.1,
    - 13            "minEpochTime": 0,
    - 14            "minEpochIterations": 1,
    - 15            "warmup": 0,
    - 16            "relative": 0,
    - 17            "median(elapsed)": 2.54441805225653e-08,
    - 18            "medianAbsolutePercentError(elapsed)": 0.0236579384033733,
    - 19            "median(instructions)": 125.989678899083,
    - 20            "medianAbsolutePercentError(instructions)": 0.035125448044942,
    - 21            "median(cpucycles)": 81.3479809976247,
    - 22            "median(contextswitches)": 0,
    - 23            "median(pagefaults)": 0,
    - 24            "median(branchinstructions)": 16.7645714285714,
    - 25            "median(branchmisses)": 0.564133016627078,
    - 26            "totalTime": 0.000218811,
    - 27            "measurements": [
    - 28                {
    - 29                    "iterations": 875,
    - 30                    "elapsed": 2.54708571428571e-08,
    - 31                    "pagefaults": 0,
    - 32                    "cpucycles": 81.472,
    - 33                    "contextswitches": 0,
    - 34                    "instructions": 125.885714285714,
    - 35                    "branchinstructions": 16.7645714285714,
    - 36                    "branchmisses": 0.574857142857143
    - 37                },
    - 38                {
    - 39                    "iterations": 809,
    - 40                    "elapsed": 2.58467243510507e-08,
    - 41                    "pagefaults": 0,
    - 42                    "cpucycles": 82.5290482076638,
    - 43                    "contextswitches": 0,
    - 44                    "instructions": 128.771322620519,
    - 45                    "branchinstructions": 17.0296662546354,
    - 46                    "branchmisses": 0.582200247218789
    - 47                },
    - 48                {
    - 49                    "iterations": 737,
    - 50                    "elapsed": 2.24097693351425e-08,
    - 51                    "pagefaults": 0,
    - 52                    "cpucycles": 71.6431478968792,
    - 53                    "contextswitches": 0,
    - 54                    "instructions": 118.374491180461,
    - 55                    "branchinstructions": 15.9470827679783,
    - 56                    "branchmisses": 0.417910447761194
    - 57                },
    - 58                {
    - 59                    "iterations": 872,
    - 60                    "elapsed": 2.53405963302752e-08,
    - 61                    "pagefaults": 0,
    - 62                    "cpucycles": 80.9896788990826,
    - 63                    "contextswitches": 0,
    - 64                    "instructions": 125.989678899083,
    - 65                    "branchinstructions": 16.7580275229358,
    - 66                    "branchmisses": 0.563073394495413
    - 67                },
    - 68                {
    - 69                    "iterations": 834,
    - 70                    "elapsed": 2.59256594724221e-08,
    - 71                    "pagefaults": 0,
    - 72                    "cpucycles": 82.7661870503597,
    - 73                    "contextswitches": 0,
    - 74                    "instructions": 127.635491606715,
    - 75                    "branchinstructions": 16.9352517985612,
    - 76                    "branchmisses": 0.575539568345324
    - 77                },
    - 78                {
    - 79                    "iterations": 772,
    - 80                    "elapsed": 2.25310880829016e-08,
    - 81                    "pagefaults": 0,
    - 82                    "cpucycles": 72.0129533678757,
    - 83                    "contextswitches": 0,
    - 84                    "instructions": 117.108808290155,
    - 85                    "branchinstructions": 15.8341968911917,
    - 86                    "branchmisses": 0.405440414507772
    - 87                },
    - 88                {
    - 89                    "iterations": 842,
    - 90                    "elapsed": 2.54441805225653e-08,
    - 91                    "pagefaults": 0,
    - 92                    "cpucycles": 81.3479809976247,
    - 93                    "contextswitches": 0,
    - 94                    "instructions": 127.266033254157,
    - 95                    "branchinstructions": 16.8859857482185,
    - 96                    "branchmisses": 0.564133016627078
    - 97                },
    - 98                {
    - 99                    "iterations": 792,
    -100                    "elapsed": 2.20126262626263e-08,
    -101                    "pagefaults": 0,
    -102                    "cpucycles": 70.3623737373737,
    -103                    "contextswitches": 0,
    -104                    "instructions": 116.420454545455,
    -105                    "branchinstructions": 15.7588383838384,
    -106                    "branchmisses": 0.396464646464646
    -107                },
    -108                {
    -109                    "iterations": 757,
    -110                    "elapsed": 2.63870541611625e-08,
    -111                    "pagefaults": 0,
    -112                    "cpucycles": 84.332892998679,
    -113                    "contextswitches": 0,
    -114                    "instructions": 131.462351387054,
    -115                    "branchinstructions": 17.334214002642,
    -116                    "branchmisses": 0.618229854689564
    -117                },
    -118                {
    -119                    "iterations": 850,
    -120                    "elapsed": 2.23305882352941e-08,
    -121                    "pagefaults": 0,
    -122                    "cpucycles": 71.3505882352941,
    -123                    "contextswitches": 0,
    -124                    "instructions": 114.629411764706,
    -125                    "branchinstructions": 15.5823529411765,
    -126                    "branchmisses": 0.392941176470588
    -127                },
    -128                {
    -129                    "iterations": 774,
    -130                    "elapsed": 2.60607235142119e-08,
    -131                    "pagefaults": 0,
    -132                    "cpucycles": 83.1679586563308,
    -133                    "contextswitches": 0,
    -134                    "instructions": 130.576227390181,
    -135                    "branchinstructions": 17.2635658914729,
    -136                    "branchmisses": 0.590439276485788
    -137                }
    -138            ]
    -139        },
    -140        {
    -141            "title": "Benchmarking std::mt19937_64 and std::knuth_b",
    -142            "name": "std::knuth_b",
    -143            "unit": "op",
    -144            "batch": 1,
    -145            "complexityN": -1,
    -146            "epochs": 11,
    -147            "clockResolution": 1.8e-08,
    -148            "clockResolutionMultiple": 1000,
    -149            "maxEpochTime": 0.1,
    -150            "minEpochTime": 0,
    -151            "minEpochIterations": 1,
    -152            "warmup": 0,
    -153            "relative": 0,
    -154            "median(elapsed)": 3.19013867488444e-08,
    -155            "medianAbsolutePercentError(elapsed)": 0.00091350764819687,
    -156            "median(instructions)": 170.013008130081,
    -157            "medianAbsolutePercentError(instructions)": 4.11992392254248e-06,
    -158            "median(cpucycles)": 101.973254086181,
    -159            "median(contextswitches)": 0,
    -160            "median(pagefaults)": 0,
    -161            "median(branchinstructions)": 28,
    -162            "median(branchmisses)": 0.0031104199066874,
    -163            "totalTime": 0.000217248,
    -164            "measurements": [
    -165                {
    -166                    "iterations": 568,
    -167                    "elapsed": 3.2137323943662e-08,
    -168                    "pagefaults": 0,
    -169                    "cpucycles": 102.55985915493,
    -170                    "contextswitches": 0,
    -171                    "instructions": 170.014084507042,
    -172                    "branchinstructions": 28,
    -173                    "branchmisses": 0.00528169014084507
    -174                },
    -175                {
    -176                    "iterations": 576,
    -177                    "elapsed": 3.19305555555556e-08,
    -178                    "pagefaults": 0,
    -179                    "cpucycles": 102.059027777778,
    -180                    "contextswitches": 0,
    -181                    "instructions": 170.013888888889,
    -182                    "branchinstructions": 28,
    -183                    "branchmisses": 0.00347222222222222
    -184                },
    -185                {
    -186                    "iterations": 643,
    -187                    "elapsed": 3.18973561430793e-08,
    -188                    "pagefaults": 0,
    -189                    "cpucycles": 101.973561430793,
    -190                    "contextswitches": 0,
    -191                    "instructions": 170.012441679627,
    -192                    "branchinstructions": 28,
    -193                    "branchmisses": 0.0031104199066874
    -194                },
    -195                {
    -196                    "iterations": 591,
    -197                    "elapsed": 3.1912013536379e-08,
    -198                    "pagefaults": 0,
    -199                    "cpucycles": 101.944162436548,
    -200                    "contextswitches": 0,
    -201                    "instructions": 170.013536379019,
    -202                    "branchinstructions": 28,
    -203                    "branchmisses": 0.00169204737732657
    -204                },
    -205                {
    -206                    "iterations": 673,
    -207                    "elapsed": 3.19049034175334e-08,
    -208                    "pagefaults": 0,
    -209                    "cpucycles": 101.973254086181,
    -210                    "contextswitches": 0,
    -211                    "instructions": 170.011887072808,
    -212                    "branchinstructions": 28,
    -213                    "branchmisses": 0.00297176820208024
    -214                },
    -215                {
    -216                    "iterations": 649,
    -217                    "elapsed": 3.19013867488444e-08,
    -218                    "pagefaults": 0,
    -219                    "cpucycles": 101.850539291217,
    -220                    "contextswitches": 0,
    -221                    "instructions": 170.012326656394,
    -222                    "branchinstructions": 28,
    -223                    "branchmisses": 0.00308166409861325
    -224                },
    -225                {
    -226                    "iterations": 606,
    -227                    "elapsed": 3.18547854785479e-08,
    -228                    "pagefaults": 0,
    -229                    "cpucycles": 101.83498349835,
    -230                    "contextswitches": 0,
    -231                    "instructions": 170.013201320132,
    -232                    "branchinstructions": 28,
    -233                    "branchmisses": 0.0033003300330033
    -234                },
    -235                {
    -236                    "iterations": 650,
    -237                    "elapsed": 3.18769230769231e-08,
    -238                    "pagefaults": 0,
    -239                    "cpucycles": 101.898461538462,
    -240                    "contextswitches": 0,
    -241                    "instructions": 170.012307692308,
    -242                    "branchinstructions": 28,
    -243                    "branchmisses": 0.00307692307692308
    -244                },
    -245                {
    -246                    "iterations": 615,
    -247                    "elapsed": 3.18520325203252e-08,
    -248                    "pagefaults": 0,
    -249                    "cpucycles": 101.858536585366,
    -250                    "contextswitches": 0,
    -251                    "instructions": 170.013008130081,
    -252                    "branchinstructions": 28,
    -253                    "branchmisses": 0.0032520325203252
    -254                },
    -255                {
    -256                    "iterations": 579,
    -257                    "elapsed": 3.18618307426598e-08,
    -258                    "pagefaults": 0,
    -259                    "cpucycles": 101.989637305699,
    -260                    "contextswitches": 0,
    -261                    "instructions": 170.013816925734,
    -262                    "branchinstructions": 28,
    -263                    "branchmisses": 0.00345423143350604
    -264                },
    -265                {
    -266                    "iterations": 657,
    -267                    "elapsed": 3.19558599695586e-08,
    -268                    "pagefaults": 0,
    -269                    "cpucycles": 102.229832572298,
    -270                    "contextswitches": 0,
    -271                    "instructions": 170.012176560122,
    -272                    "branchinstructions": 28,
    -273                    "branchmisses": 0.0030441400304414
    -274                }
    -275            ]
    -276        }
    -277    ]
    -278}
    +
      1{
    +  2    "results": [
    +  3        {
    +  4            "title": "Benchmarking std::mt19937_64 and std::knuth_b",
    +  5            "name": "std::mt19937_64",
    +  6            "unit": "op",
    +  7            "batch": 1,
    +  8            "complexityN": -1,
    +  9            "epochs": 11,
    + 10            "clockResolution": 1.8e-08,
    + 11            "clockResolutionMultiple": 1000,
    + 12            "maxEpochTime": 0.1,
    + 13            "minEpochTime": 0,
    + 14            "minEpochIterations": 1,
    + 15            "warmup": 0,
    + 16            "relative": 0,
    + 17            "median(elapsed)": 2.54441805225653e-08,
    + 18            "medianAbsolutePercentError(elapsed)": 0.0236579384033733,
    + 19            "median(instructions)": 125.989678899083,
    + 20            "medianAbsolutePercentError(instructions)": 0.035125448044942,
    + 21            "median(cpucycles)": 81.3479809976247,
    + 22            "median(contextswitches)": 0,
    + 23            "median(pagefaults)": 0,
    + 24            "median(branchinstructions)": 16.7645714285714,
    + 25            "median(branchmisses)": 0.564133016627078,
    + 26            "totalTime": 0.000218811,
    + 27            "measurements": [
    + 28                {
    + 29                    "iterations": 875,
    + 30                    "elapsed": 2.54708571428571e-08,
    + 31                    "pagefaults": 0,
    + 32                    "cpucycles": 81.472,
    + 33                    "contextswitches": 0,
    + 34                    "instructions": 125.885714285714,
    + 35                    "branchinstructions": 16.7645714285714,
    + 36                    "branchmisses": 0.574857142857143
    + 37                },
    + 38                {
    + 39                    "iterations": 809,
    + 40                    "elapsed": 2.58467243510507e-08,
    + 41                    "pagefaults": 0,
    + 42                    "cpucycles": 82.5290482076638,
    + 43                    "contextswitches": 0,
    + 44                    "instructions": 128.771322620519,
    + 45                    "branchinstructions": 17.0296662546354,
    + 46                    "branchmisses": 0.582200247218789
    + 47                },
    + 48                {
    + 49                    "iterations": 737,
    + 50                    "elapsed": 2.24097693351425e-08,
    + 51                    "pagefaults": 0,
    + 52                    "cpucycles": 71.6431478968792,
    + 53                    "contextswitches": 0,
    + 54                    "instructions": 118.374491180461,
    + 55                    "branchinstructions": 15.9470827679783,
    + 56                    "branchmisses": 0.417910447761194
    + 57                },
    + 58                {
    + 59                    "iterations": 872,
    + 60                    "elapsed": 2.53405963302752e-08,
    + 61                    "pagefaults": 0,
    + 62                    "cpucycles": 80.9896788990826,
    + 63                    "contextswitches": 0,
    + 64                    "instructions": 125.989678899083,
    + 65                    "branchinstructions": 16.7580275229358,
    + 66                    "branchmisses": 0.563073394495413
    + 67                },
    + 68                {
    + 69                    "iterations": 834,
    + 70                    "elapsed": 2.59256594724221e-08,
    + 71                    "pagefaults": 0,
    + 72                    "cpucycles": 82.7661870503597,
    + 73                    "contextswitches": 0,
    + 74                    "instructions": 127.635491606715,
    + 75                    "branchinstructions": 16.9352517985612,
    + 76                    "branchmisses": 0.575539568345324
    + 77                },
    + 78                {
    + 79                    "iterations": 772,
    + 80                    "elapsed": 2.25310880829016e-08,
    + 81                    "pagefaults": 0,
    + 82                    "cpucycles": 72.0129533678757,
    + 83                    "contextswitches": 0,
    + 84                    "instructions": 117.108808290155,
    + 85                    "branchinstructions": 15.8341968911917,
    + 86                    "branchmisses": 0.405440414507772
    + 87                },
    + 88                {
    + 89                    "iterations": 842,
    + 90                    "elapsed": 2.54441805225653e-08,
    + 91                    "pagefaults": 0,
    + 92                    "cpucycles": 81.3479809976247,
    + 93                    "contextswitches": 0,
    + 94                    "instructions": 127.266033254157,
    + 95                    "branchinstructions": 16.8859857482185,
    + 96                    "branchmisses": 0.564133016627078
    + 97                },
    + 98                {
    + 99                    "iterations": 792,
    +100                    "elapsed": 2.20126262626263e-08,
    +101                    "pagefaults": 0,
    +102                    "cpucycles": 70.3623737373737,
    +103                    "contextswitches": 0,
    +104                    "instructions": 116.420454545455,
    +105                    "branchinstructions": 15.7588383838384,
    +106                    "branchmisses": 0.396464646464646
    +107                },
    +108                {
    +109                    "iterations": 757,
    +110                    "elapsed": 2.63870541611625e-08,
    +111                    "pagefaults": 0,
    +112                    "cpucycles": 84.332892998679,
    +113                    "contextswitches": 0,
    +114                    "instructions": 131.462351387054,
    +115                    "branchinstructions": 17.334214002642,
    +116                    "branchmisses": 0.618229854689564
    +117                },
    +118                {
    +119                    "iterations": 850,
    +120                    "elapsed": 2.23305882352941e-08,
    +121                    "pagefaults": 0,
    +122                    "cpucycles": 71.3505882352941,
    +123                    "contextswitches": 0,
    +124                    "instructions": 114.629411764706,
    +125                    "branchinstructions": 15.5823529411765,
    +126                    "branchmisses": 0.392941176470588
    +127                },
    +128                {
    +129                    "iterations": 774,
    +130                    "elapsed": 2.60607235142119e-08,
    +131                    "pagefaults": 0,
    +132                    "cpucycles": 83.1679586563308,
    +133                    "contextswitches": 0,
    +134                    "instructions": 130.576227390181,
    +135                    "branchinstructions": 17.2635658914729,
    +136                    "branchmisses": 0.590439276485788
    +137                }
    +138            ]
    +139        },
    +140        {
    +141            "title": "Benchmarking std::mt19937_64 and std::knuth_b",
    +142            "name": "std::knuth_b",
    +143            "unit": "op",
    +144            "batch": 1,
    +145            "complexityN": -1,
    +146            "epochs": 11,
    +147            "clockResolution": 1.8e-08,
    +148            "clockResolutionMultiple": 1000,
    +149            "maxEpochTime": 0.1,
    +150            "minEpochTime": 0,
    +151            "minEpochIterations": 1,
    +152            "warmup": 0,
    +153            "relative": 0,
    +154            "median(elapsed)": 3.19013867488444e-08,
    +155            "medianAbsolutePercentError(elapsed)": 0.00091350764819687,
    +156            "median(instructions)": 170.013008130081,
    +157            "medianAbsolutePercentError(instructions)": 4.11992392254248e-06,
    +158            "median(cpucycles)": 101.973254086181,
    +159            "median(contextswitches)": 0,
    +160            "median(pagefaults)": 0,
    +161            "median(branchinstructions)": 28,
    +162            "median(branchmisses)": 0.0031104199066874,
    +163            "totalTime": 0.000217248,
    +164            "measurements": [
    +165                {
    +166                    "iterations": 568,
    +167                    "elapsed": 3.2137323943662e-08,
    +168                    "pagefaults": 0,
    +169                    "cpucycles": 102.55985915493,
    +170                    "contextswitches": 0,
    +171                    "instructions": 170.014084507042,
    +172                    "branchinstructions": 28,
    +173                    "branchmisses": 0.00528169014084507
    +174                },
    +175                {
    +176                    "iterations": 576,
    +177                    "elapsed": 3.19305555555556e-08,
    +178                    "pagefaults": 0,
    +179                    "cpucycles": 102.059027777778,
    +180                    "contextswitches": 0,
    +181                    "instructions": 170.013888888889,
    +182                    "branchinstructions": 28,
    +183                    "branchmisses": 0.00347222222222222
    +184                },
    +185                {
    +186                    "iterations": 643,
    +187                    "elapsed": 3.18973561430793e-08,
    +188                    "pagefaults": 0,
    +189                    "cpucycles": 101.973561430793,
    +190                    "contextswitches": 0,
    +191                    "instructions": 170.012441679627,
    +192                    "branchinstructions": 28,
    +193                    "branchmisses": 0.0031104199066874
    +194                },
    +195                {
    +196                    "iterations": 591,
    +197                    "elapsed": 3.1912013536379e-08,
    +198                    "pagefaults": 0,
    +199                    "cpucycles": 101.944162436548,
    +200                    "contextswitches": 0,
    +201                    "instructions": 170.013536379019,
    +202                    "branchinstructions": 28,
    +203                    "branchmisses": 0.00169204737732657
    +204                },
    +205                {
    +206                    "iterations": 673,
    +207                    "elapsed": 3.19049034175334e-08,
    +208                    "pagefaults": 0,
    +209                    "cpucycles": 101.973254086181,
    +210                    "contextswitches": 0,
    +211                    "instructions": 170.011887072808,
    +212                    "branchinstructions": 28,
    +213                    "branchmisses": 0.00297176820208024
    +214                },
    +215                {
    +216                    "iterations": 649,
    +217                    "elapsed": 3.19013867488444e-08,
    +218                    "pagefaults": 0,
    +219                    "cpucycles": 101.850539291217,
    +220                    "contextswitches": 0,
    +221                    "instructions": 170.012326656394,
    +222                    "branchinstructions": 28,
    +223                    "branchmisses": 0.00308166409861325
    +224                },
    +225                {
    +226                    "iterations": 606,
    +227                    "elapsed": 3.18547854785479e-08,
    +228                    "pagefaults": 0,
    +229                    "cpucycles": 101.83498349835,
    +230                    "contextswitches": 0,
    +231                    "instructions": 170.013201320132,
    +232                    "branchinstructions": 28,
    +233                    "branchmisses": 0.0033003300330033
    +234                },
    +235                {
    +236                    "iterations": 650,
    +237                    "elapsed": 3.18769230769231e-08,
    +238                    "pagefaults": 0,
    +239                    "cpucycles": 101.898461538462,
    +240                    "contextswitches": 0,
    +241                    "instructions": 170.012307692308,
    +242                    "branchinstructions": 28,
    +243                    "branchmisses": 0.00307692307692308
    +244                },
    +245                {
    +246                    "iterations": 615,
    +247                    "elapsed": 3.18520325203252e-08,
    +248                    "pagefaults": 0,
    +249                    "cpucycles": 101.858536585366,
    +250                    "contextswitches": 0,
    +251                    "instructions": 170.013008130081,
    +252                    "branchinstructions": 28,
    +253                    "branchmisses": 0.0032520325203252
    +254                },
    +255                {
    +256                    "iterations": 579,
    +257                    "elapsed": 3.18618307426598e-08,
    +258                    "pagefaults": 0,
    +259                    "cpucycles": 101.989637305699,
    +260                    "contextswitches": 0,
    +261                    "instructions": 170.013816925734,
    +262                    "branchinstructions": 28,
    +263                    "branchmisses": 0.00345423143350604
    +264                },
    +265                {
    +266                    "iterations": 657,
    +267                    "elapsed": 3.19558599695586e-08,
    +268                    "pagefaults": 0,
    +269                    "cpucycles": 102.229832572298,
    +270                    "contextswitches": 0,
    +271                    "instructions": 170.012176560122,
    +272                    "branchinstructions": 28,
    +273                    "branchmisses": 0.0030441400304414
    +274                }
    +275            ]
    +276        }
    +277    ]
    +278}
     
    @@ -1353,7 +1354,7 @@

    Compare Results -

    © Copyright 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>.

    +

    © Copyright 2019-2022 Martin Ankerl <martin.ankerl@gmail.com>.

    Built with Sphinx using a diff --git a/src/docs/conf.py b/src/docs/conf.py index 159c206..b2cefe1 100644 --- a/src/docs/conf.py +++ b/src/docs/conf.py @@ -20,9 +20,9 @@ # -- Project information ----------------------------------------------------- project = 'nanobench' -copyright = '2019-2021 Martin Ankerl ' +copyright = '2019-2022 Martin Ankerl ' author = 'Martin Ankerl' -version = 'v4.3.6' +version = 'v4.3.7' # -- General configuration --------------------------------------------------- diff --git a/src/docs/generate.sh b/src/docs/generate.sh index ee31171..91e4690 100755 --- a/src/docs/generate.sh +++ b/src/docs/generate.sh @@ -5,10 +5,7 @@ set -e # # Install breathe (assuming there's a venv in ~/git/venv) # source ~/git/venv/bin/activate -# pip install -U sphinx -# pip install -U breathe -# pip install -U sphinx_rtd_theme -# pip install -U recommonmark +# pip install -U sphinx breathe sphinx_rtd_theme recommonmark # rm should work, this should copy all files, but for safety reasons I'm not doing it... #rm -Rvf ../../docs diff --git a/src/include/nanobench.h b/src/include/nanobench.h index 8b5acb7..56faee2 100644 --- a/src/include/nanobench.h +++ b/src/include/nanobench.h @@ -7,7 +7,7 @@ // // Licensed under the MIT License . // SPDX-License-Identifier: MIT -// Copyright (c) 2019-2021 Martin Ankerl +// Copyright (c) 2019-2022 Martin Ankerl // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ // see https://semver.org/ #define ANKERL_NANOBENCH_VERSION_MAJOR 4 // incompatible API changes #define ANKERL_NANOBENCH_VERSION_MINOR 3 // backwards-compatible changes -#define ANKERL_NANOBENCH_VERSION_PATCH 6 // backwards-compatible bug fixes +#define ANKERL_NANOBENCH_VERSION_PATCH 7 // backwards-compatible bug fixes /////////////////////////////////////////////////////////////////////////////////////////////////// // public facing api - as minimal as possible @@ -167,7 +167,7 @@ class BigO; * * `{{maxEpochTime}}` Configuration for a maximum time each measurement (epoch) is allowed to take. Note that at least * a single iteration will be performed, even when that takes longer than maxEpochTime. See Bench::maxEpochTime(). * - * * `{{minEpochTime}}` Minimum epoch time, usually not set. See Bench::minEpochTime(). + * * `{{minEpochTime}}` Minimum epoch time, defaults to 1ms. See Bench::minEpochTime(). * * * `{{minEpochIterations}}` See Bench::minEpochIterations(). * @@ -386,7 +386,7 @@ struct Config { size_t mNumEpochs = 11; size_t mClockResolutionMultiple = static_cast(1000); std::chrono::nanoseconds mMaxEpochTime = std::chrono::milliseconds(100); - std::chrono::nanoseconds mMinEpochTime{}; + std::chrono::nanoseconds mMinEpochTime = std::chrono::milliseconds(1); uint64_t mMinEpochIterations{1}; uint64_t mEpochIterations{0}; // If not 0, run *exactly* these number of iterations per epoch. uint64_t mWarmup = 0; diff --git a/src/test/thirdparty/doctest/doctest.h b/src/test/thirdparty/doctest/doctest.h index 9444698..d25f526 100644 --- a/src/test/thirdparty/doctest/doctest.h +++ b/src/test/thirdparty/doctest/doctest.h @@ -4,14 +4,14 @@ // // doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD // -// Copyright (c) 2016-2019 Viktor Kirilov +// Copyright (c) 2016-2021 Viktor Kirilov // // Distributed under the MIT Software License // See accompanying file LICENSE.txt or copy at // https://opensource.org/licenses/MIT // // The documentation can be found at the library's page: -// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md +// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md // // ================================================================================================= // ================================================================================================= @@ -48,8 +48,16 @@ #define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 0 -#define DOCTEST_VERSION_STR "2.4.0" +#define DOCTEST_VERSION_PATCH 8 + +// util we need here +#define DOCTEST_TOSTR_IMPL(x) #x +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) + +#define DOCTEST_VERSION_STR \ + DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -137,85 +145,93 @@ // == COMPILER WARNINGS ============================================================================ // ================================================================================================= +// both the header and the implementation suppress all of these, +// so it only makes sense to aggregrate them like so +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ + \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ + \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + /* these 4 also disabled globally via cmake: */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ + /* */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + /* static analysis */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ + +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") -DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") -DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") -DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") -DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor") -DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs") -DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") -DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo") DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning -DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning -DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration -DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression -DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated -DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant -DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding -DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe -// static analysis -DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept' -DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable -DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ... -DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtr... -DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' - -// 4548 - expression before comma has no effect; expected expression with side - effect -// 4265 - class has virtual functions, but destructor is not virtual -// 4986 - exception specification does not match previous declaration -// 4350 - behavior change: 'member1' called instead of 'member2' -// 4668 - 'x' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' -// 4365 - conversion from 'int' to 'unsigned long', signed/unsigned mismatch -// 4774 - format string expected in argument 'x' is not a string literal -// 4820 - padding in structs - -// only 4 should be disabled globally: -// - 4514 # unreferenced inline function has been removed -// - 4571 # SEH related -// - 4710 # function not inlined -// - 4711 # function 'x' selected for automatic inline expansion #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - DOCTEST_MSVC_SUPPRESS_WARNING(4548) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4265) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4986) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4350) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4668) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4365) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4774) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) \ - DOCTEST_MSVC_SUPPRESS_WARNING(4623) \ - DOCTEST_MSVC_SUPPRESS_WARNING(5039) \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) \ - DOCTEST_MSVC_SUPPRESS_WARNING(5105) + DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -228,6 +244,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' // GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html // MSVC version table: // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering +// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022) // MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) // MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) @@ -237,6 +254,10 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' // MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) // MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) +// Universal Windows Platform support +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_WINDOWS_SEH +#endif // WINAPI_FAMILY #if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH) #define DOCTEST_CONFIG_WINDOWS_SEH #endif // MSVC @@ -301,20 +322,40 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' #define DOCTEST_NOINLINE __declspec(noinline) #define DOCTEST_UNUSED #define DOCTEST_ALIGNMENT(x) -#else // MSVC +#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) +#define DOCTEST_NOINLINE +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#else #define DOCTEST_NOINLINE __attribute__((noinline)) #define DOCTEST_UNUSED __attribute__((unused)) #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) -#endif // MSVC +#endif #ifndef DOCTEST_NORETURN +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NORETURN +#else // DOCTEST_MSVC #define DOCTEST_NORETURN [[noreturn]] +#endif // DOCTEST_MSVC #endif // DOCTEST_NORETURN #ifndef DOCTEST_NOEXCEPT +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NOEXCEPT +#else // DOCTEST_MSVC #define DOCTEST_NOEXCEPT noexcept +#endif // DOCTEST_MSVC #endif // DOCTEST_NOEXCEPT +#ifndef DOCTEST_CONSTEXPR +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_CONSTEXPR const +#else // DOCTEST_MSVC +#define DOCTEST_CONSTEXPR constexpr +#endif // DOCTEST_MSVC +#endif // DOCTEST_CONSTEXPR + // ================================================================================================= // == FEATURE DETECTION END ======================================================================== // ================================================================================================= @@ -328,8 +369,6 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) #endif // __COUNTER__ -#define DOCTEST_TOSTR(x) #x - #ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE #define DOCTEST_REF_WRAP(x) x& #else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE @@ -347,16 +386,31 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' #define DOCTEST_PLATFORM_LINUX #endif // DOCTEST_PLATFORM -#define DOCTEST_GLOBAL_NO_WARNINGS(var) \ +namespace doctest { namespace detail { + static DOCTEST_CONSTEXPR int consume(const int*, int) { return 0; } +}} + +#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \ - static int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp) -#define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP + static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #ifndef DOCTEST_BREAK_INTO_DEBUGGER // should probably take a look at https://github.com/scottt/debugbreak -#ifdef DOCTEST_PLATFORM_MAC -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) +#ifdef DOCTEST_PLATFORM_LINUX +#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) +// Break at the location of the failing check if possible +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler) +#else +#include +#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) +#endif +#elif defined(DOCTEST_PLATFORM_MAC) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler) +#else +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT (hicpp-no-assembler) +#endif #elif DOCTEST_MSVC #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() #elif defined(__MINGW32__) @@ -365,7 +419,7 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak(); DOCTEST_GCC_SUPPRESS_WARNING_POP #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() #else // linux -#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0) +#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) #endif // linux #endif // DOCTEST_BREAK_INTO_DEBUGGER @@ -374,29 +428,31 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #define DOCTEST_CONFIG_USE_STD_HEADERS #endif // DOCTEST_CONFIG_USE_IOSFWD -#ifdef DOCTEST_CONFIG_USE_STD_HEADERS -#include -#include -#include -#else // DOCTEST_CONFIG_USE_STD_HEADERS - +// for clang - always include ciso646 (which drags some std stuff) because +// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in +// which case we don't want to forward declare stuff from std - for reference: +// https://github.com/doctest/doctest/issues/126 +// https://github.com/doctest/doctest/issues/356 #if DOCTEST_CLANG -// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier) #include -#endif // clang - #ifdef _LIBCPP_VERSION -#define DOCTEST_STD_NAMESPACE_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD -#define DOCTEST_STD_NAMESPACE_END _LIBCPP_END_NAMESPACE_STD -#else // _LIBCPP_VERSION -#define DOCTEST_STD_NAMESPACE_BEGIN namespace std { -#define DOCTEST_STD_NAMESPACE_END } +#define DOCTEST_CONFIG_USE_STD_HEADERS #endif // _LIBCPP_VERSION +#endif // clang + +#ifdef DOCTEST_CONFIG_USE_STD_HEADERS +#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#include +#include +#include +#else // DOCTEST_CONFIG_USE_STD_HEADERS // Forward declaring 'X' in namespace std is not permitted by the C++ Standard. DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) -DOCTEST_STD_NAMESPACE_BEGIN // NOLINT (cert-dcl58-cpp) +namespace std { // NOLINT (cert-dcl58-cpp) typedef decltype(nullptr) nullptr_t; template struct char_traits; @@ -405,17 +461,20 @@ struct char_traits; template class basic_ostream; typedef basic_ostream> ostream; +template +class basic_istream; +typedef basic_istream> istream; template class tuple; #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 -template +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +template class allocator; -template +template class basic_string; using string = basic_string, allocator>; #endif // VS 2019 -DOCTEST_STD_NAMESPACE_END +} // namespace std DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -467,6 +526,8 @@ class DOCTEST_INTERFACE String view data; }; + char* allocate(unsigned sz); + bool isOnStack() const { return (buf[last] & 128) == 0; } void setOnHeap(); void setLast(unsigned in = last); @@ -481,11 +542,12 @@ class DOCTEST_INTERFACE String String(const char* in); String(const char* in, unsigned in_size); + String(std::istream& in, unsigned in_size); + String(const String& other); String& operator=(const String& other); String& operator+=(const String& other); - String operator+(const String& other) const; String(String&& other); String& operator=(String&& other); @@ -508,6 +570,8 @@ class DOCTEST_INTERFACE String int compare(const String& other, bool no_case = false) const; }; +DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); @@ -637,12 +701,14 @@ DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); struct DOCTEST_INTERFACE TestCaseData { - String m_file; // the file in which the test was registered + String m_file; // the file in which the test was registered (using String - see #350) unsigned m_line; // the line where the test was registered const char* m_name; // name of the test case const char* m_test_suite; // the test suite in which the test was added const char* m_description; bool m_skip; + bool m_no_breaks; + bool m_no_output; bool m_may_fail; bool m_should_fail; int m_expected_failures; @@ -696,11 +762,16 @@ struct DOCTEST_INTERFACE IContextScope virtual void stringify(std::ostream*) const = 0; }; +namespace detail { + struct DOCTEST_INTERFACE TestCase; +} // namespace detail + struct ContextOptions //!OCLINT too many fields { - std::ostream* cout; // stdout stream - std::cout by default - std::ostream* cerr; // stderr stream - std::cerr by default - String binary_name; // the test binary name + std::ostream* cout = nullptr; // stdout stream + String binary_name; // the test binary name + + const detail::TestCase* currentTest = nullptr; // == parameters from the command line String out; // output filename @@ -717,9 +788,12 @@ struct ContextOptions //!OCLINT too many fields bool case_sensitive; // if filtering should be case sensitive bool exit; // if the program should be exited after the tests are ran/whatever bool duration; // print the time duration of each test case + bool minimal; // minimal console output (only test failures) + bool quiet; // no console output bool no_throw; // to skip exceptions-related assertion macros bool no_exitcode; // if the framework should return 0 as the exitcode bool no_run; // to not run the tests at all (can be done with an "*" exclude) + bool no_intro; // to not print the intro of the framework bool no_version; // to not print the version of the framework bool no_colors; // if output to the console should be colorized bool force_colors; // forces the use of colors even when a tty cannot be detected @@ -728,6 +802,7 @@ struct ContextOptions //!OCLINT too many fields bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): bool no_path_in_filenames; // if the path to files should be removed from the output bool no_line_numbers; // if source code line numbers should be omitted from the output + bool no_debug_output; // no output in the debug console when a debugger is attached bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! @@ -740,7 +815,6 @@ struct ContextOptions //!OCLINT too many fields }; namespace detail { -#if defined(DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING) || defined(DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS) template struct enable_if {}; @@ -748,15 +822,48 @@ namespace detail { template struct enable_if { typedef TYPE type; }; -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING) || DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS // clang-format off template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; + template U declval(int); + + template T declval(long); + + template auto declval() DOCTEST_NOEXCEPT -> decltype(declval(0)) ; + + template struct is_lvalue_reference { const static bool value=false; }; + template struct is_lvalue_reference { const static bool value=true; }; + + template struct is_rvalue_reference { const static bool value=false; }; + template struct is_rvalue_reference { const static bool value=true; }; + + template + inline T&& forward(typename remove_reference::type& t) DOCTEST_NOEXCEPT + { + return static_cast(t); + } + + template + inline T&& forward(typename remove_reference::type&& t) DOCTEST_NOEXCEPT + { + static_assert(!is_lvalue_reference::value, + "Can not forward an rvalue as an lvalue."); + return static_cast(t); + } + template struct remove_const { typedef T type; }; template struct remove_const { typedef T type; }; +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template struct is_enum : public std::is_enum {}; + template struct underlying_type : public std::underlying_type {}; +#else + // Use compiler intrinsics + template struct is_enum { DOCTEST_CONSTEXPR static bool value = __is_enum(T); }; + template struct underlying_type { typedef __underlying_type(T) type; }; +#endif // clang-format on template @@ -771,22 +878,21 @@ namespace detail { template struct check { - static constexpr auto value = false; + static DOCTEST_CONSTEXPR bool value = false; }; template struct check(), void())> { - static constexpr auto value = true; + static DOCTEST_CONSTEXPR bool value = true; }; } // namespace has_insertion_operator_impl template - using has_insertion_operator = has_insertion_operator_impl::check; + using has_insertion_operator = has_insertion_operator_impl::check; - DOCTEST_INTERFACE void my_memcpy(void* dest, const void* src, unsigned num); + DOCTEST_INTERFACE std::ostream* tlssPush(); + DOCTEST_INTERFACE String tlssPop(); - DOCTEST_INTERFACE std::ostream* getTlsOss(); // returns a thread-local ostringstream - DOCTEST_INTERFACE String getTlsOssResult(); template struct StringMakerBase @@ -797,13 +903,61 @@ namespace detail { } }; + // Vector and various type other than pointer or array. + template + struct filldata + { + static void fill(std::ostream* stream, const T &in) { + *stream << in; + } + }; + + template + struct filldata + { + static void fill(std::ostream* stream, const T (&in)[N]) { + for (unsigned long i = 0; i < N; i++) { + *stream << in[i]; + } + } + }; + + // Specialized since we don't want the terminating null byte! + template + struct filldata + { + static void fill(std::ostream* stream, const char(&in)[N]) { + *stream << in; + } + }; + + template + void filloss(std::ostream* stream, const T& in) { + filldata::fill(stream, in); + } + + template + void filloss(std::ostream* stream, const T (&in)[N]) { + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filldata::type>::fill(stream, in); + } + template <> struct StringMakerBase { template static String convert(const DOCTEST_REF_WRAP(T) in) { - *getTlsOss() << in; - return getTlsOssResult(); + /* When parameter "in" is a null terminated const char* it works. + * When parameter "in" is a T arr[N] without '\0' we can fill the + * stringstream with N objects (T=char).If in is char pointer * + * without '\0' , it would cause segfault + * stepping over unaccessible memory. + */ + + std::ostream* stream = tlssPush(); + filloss(stream, in); + return tlssPop(); } }; @@ -845,7 +999,7 @@ struct StringMaker } }; -template +template ::value, bool>::type = true> String toString(const DOCTEST_REF_WRAP(T) value) { return StringMaker::convert(value); } @@ -872,8 +1026,14 @@ DOCTEST_INTERFACE String toString(int long long in); DOCTEST_INTERFACE String toString(int long long unsigned in); DOCTEST_INTERFACE String toString(std::nullptr_t in); +template ::value, bool>::type = true> +String toString(const DOCTEST_REF_WRAP(T) value) { + typedef typename detail::underlying_type::type UT; + return toString(static_cast(value)); +} + #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 DOCTEST_INTERFACE String toString(const std::string& in); #endif // VS 2019 @@ -1004,13 +1164,33 @@ namespace detail { template String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, const DOCTEST_REF_WRAP(R) rhs) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) return toString(lhs) + op + toString(rhs); } +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + +// This will check if there is any way it could find a operator like member or friend and uses it. +// If not it doesn't find the operator or if the operator at global scope is defined after +// this template, the template won't be instantiated due to SFINAE. Once the template is not +// instantiated it can look for global operator using normal conversions. +#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) + #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ template \ - DOCTEST_NOINLINE Result operator op(const DOCTEST_REF_WRAP(R) rhs) { \ - bool res = op_macro(lhs, rhs); \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(const R&& rhs) { \ + bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ + if(m_at & assertType::is_false) \ + res = !res; \ + if(!res || doctest::getContextOptions()->success) \ + return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ + return Result(res); \ + } \ + template ::value, void >::type* = nullptr> \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(const R& rhs) { \ + bool res = op_macro(doctest::detail::forward(lhs), rhs); \ if(m_at & assertType::is_false) \ res = !res; \ if(!res || doctest::getContextOptions()->success) \ @@ -1034,6 +1214,7 @@ namespace detail { bool m_passed; String m_decomp; + Result() = default; Result(bool passed, const String& decomposition = String()); // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence @@ -1091,6 +1272,7 @@ namespace detail { #define DOCTEST_COMPARISON_RETURN_TYPE bool #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if::value || can_use_op::value, bool>::type + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } @@ -1137,12 +1319,15 @@ namespace detail { L lhs; assertType::Enum m_at; - explicit Expression_lhs(L in, assertType::Enum at) - : lhs(in) + explicit Expression_lhs(L&& in, assertType::Enum at) + : lhs(doctest::detail::forward(in)) , m_at(at) {} DOCTEST_NOINLINE operator Result() { - bool res = !!lhs; +// this is needed only for MSVC 2015 +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); +DOCTEST_MSVC_SUPPRESS_WARNING_POP if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional res = !res; @@ -1151,6 +1336,9 @@ namespace detail { return Result(res); } + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } + // clang-format off DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional @@ -1191,6 +1379,10 @@ namespace detail { #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_POP +#endif + struct DOCTEST_INTERFACE ExpressionDecomposer { assertType::Enum m_at; @@ -1202,20 +1394,27 @@ namespace detail { // https://github.com/catchorg/Catch2/issues/870 // https://github.com/catchorg/Catch2/issues/565 template - Expression_lhs operator<<(const DOCTEST_REF_WRAP(L) operand) { - return Expression_lhs(operand, m_at); + Expression_lhs operator<<(const L &&operand) { + return Expression_lhs(doctest::detail::forward(operand), m_at); + } + + template ::value,void >::type* = nullptr> + Expression_lhs operator<<(const L &operand) { + return Expression_lhs(operand, m_at); } }; struct DOCTEST_INTERFACE TestSuite { - const char* m_test_suite; - const char* m_description; - bool m_skip; - bool m_may_fail; - bool m_should_fail; - int m_expected_failures; - double m_timeout; + const char* m_test_suite = nullptr; + const char* m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; TestSuite& operator*(const char* in); @@ -1283,12 +1482,12 @@ namespace detail { template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; // clang-format on - DOCTEST_BINARY_RELATIONAL_OP(0, eq) - DOCTEST_BINARY_RELATIONAL_OP(1, ne) - DOCTEST_BINARY_RELATIONAL_OP(2, gt) - DOCTEST_BINARY_RELATIONAL_OP(3, lt) - DOCTEST_BINARY_RELATIONAL_OP(4, ge) - DOCTEST_BINARY_RELATIONAL_OP(5, le) + DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) + DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) + DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) + DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) + DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) + DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) struct DOCTEST_INTERFACE ResultBuilder : public AssertData { @@ -1298,15 +1497,16 @@ namespace detail { void setResult(const Result& res); template - DOCTEST_NOINLINE void binary_assert(const DOCTEST_REF_WRAP(L) lhs, + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { m_failed = !RelationalComparator()(lhs, rhs); if(m_failed || getContextOptions()->success) m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); + return !m_failed; } template - DOCTEST_NOINLINE void unary_assert(const DOCTEST_REF_WRAP(L) val) { + DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { m_failed = !val; if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional @@ -1314,6 +1514,8 @@ namespace detail { if(m_failed || getContextOptions()->success) m_decomp = toString(val); + + return !m_failed; } void translateException(); @@ -1333,7 +1535,7 @@ namespace detail { DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); - DOCTEST_INTERFACE void decomp_assert(assertType::Enum at, const char* file, int line, + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, Result result); #define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ @@ -1349,7 +1551,7 @@ namespace detail { if(checkIfShouldThrow(at)) \ throwException(); \ } \ - return; \ + return !failed; \ } \ } while(false) @@ -1364,7 +1566,7 @@ namespace detail { throwException() template - DOCTEST_NOINLINE void binary_assert(assertType::Enum at, const char* file, int line, + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, const char* expr, const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { bool failed = !RelationalComparator()(lhs, rhs); @@ -1375,10 +1577,11 @@ namespace detail { // ################################################################################### DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; } template - DOCTEST_NOINLINE void unary_assert(assertType::Enum at, const char* file, int line, + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, const char* expr, const DOCTEST_REF_WRAP(L) val) { bool failed = !val; @@ -1391,6 +1594,7 @@ namespace detail { // ################################################################################### DOCTEST_ASSERT_OUT_OF_TESTS(toString(val)); DOCTEST_ASSERT_IN_TESTS(toString(val)); + return !failed; } struct DOCTEST_INTERFACE IExceptionTranslator @@ -1415,9 +1619,9 @@ namespace detail { } catch(T ex) { // NOLINT res = m_translateFunction(ex); //!OCLINT parameter reassignment return true; - } catch(...) {} //!OCLINT - empty catch statement -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - ((void)res); // to silence -Wunused-parameter + } catch(...) {} //!OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter return false; } @@ -1484,38 +1688,57 @@ namespace detail { class DOCTEST_INTERFACE ContextScopeBase : public IContextScope { protected: ContextScopeBase(); + ContextScopeBase(ContextScopeBase&& other); void destroy(); + bool need_to_destroy{true}; }; template class ContextScope : public ContextScopeBase { - const L &lambda_; + const L lambda_; public: explicit ContextScope(const L &lambda) : lambda_(lambda) {} - ContextScope(ContextScope &&other) : lambda_(other.lambda_) {} + ContextScope(ContextScope &&other) : ContextScopeBase(static_cast(other)), lambda_(other.lambda_) {} void stringify(std::ostream* s) const override { lambda_(s); } - ~ContextScope() override { destroy(); } + ~ContextScope() override { + if (need_to_destroy) { + destroy(); + } + } }; struct DOCTEST_INTERFACE MessageBuilder : public MessageData { std::ostream* m_stream; + bool logged = false; MessageBuilder(const char* file, int line, assertType::Enum severity); MessageBuilder() = delete; ~MessageBuilder(); + // the preferred way of chaining parameters for stringification template - MessageBuilder& operator<<(const T& in) { + MessageBuilder& operator,(const T& in) { toStream(m_stream, in); return *this; } + // kept here just for backwards-compatibility - the comma operator should be preferred now + template + MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template + MessageBuilder& operator*(const T& in) { return this->operator,(in); } + bool log(); void react(); }; @@ -1539,6 +1762,8 @@ namespace detail { DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); DOCTEST_DEFINE_DECORATOR(description, const char*, ""); DOCTEST_DEFINE_DECORATOR(skip, bool, true); +DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); +DOCTEST_DEFINE_DECORATOR(no_output, bool, true); DOCTEST_DEFINE_DECORATOR(timeout, double, 0); DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); @@ -1589,6 +1814,7 @@ class DOCTEST_INTERFACE Context void addFilter(const char* filter, const char* value); void clearFilters(); + void setOption(const char* option, bool value); void setOption(const char* option, int value); void setOption(const char* option, const char* value); @@ -1598,6 +1824,8 @@ class DOCTEST_INTERFACE Context void setAssertHandler(detail::assert_handler ah); + void setCout(std::ostream* out); + int run(); }; @@ -1624,6 +1852,7 @@ struct DOCTEST_INTERFACE CurrentTestCaseStats int numAssertsFailedCurrentTest; double seconds; int failure_flags; // use TestCaseFailureReason::Enum + bool testCaseSuccess; }; struct DOCTEST_INTERFACE TestCaseException @@ -1721,10 +1950,11 @@ int registerReporter(const char* name, int priority, bool isReporter) { #if !defined(DOCTEST_CONFIG_DISABLE) // common code in asserts - for convenience -#define DOCTEST_ASSERT_LOG_AND_REACT(b) \ +#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ if(b.log()) \ DOCTEST_BREAK_INTO_DEBUGGER(); \ - b.react() + b.react(); \ + return !b.m_failed #ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #define DOCTEST_WRAP_IN_TRY(x) x; @@ -1732,7 +1962,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_WRAP_IN_TRY(x) \ try { \ x; \ - } catch(...) { _DOCTEST_RB.translateException(); } + } catch(...) { DOCTEST_RB.translateException(); } #endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS @@ -1746,13 +1976,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { // registers the test by initializing a dummy var with a function #define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ - global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \ + global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), \ doctest::detail::regTest( \ doctest::detail::TestCase( \ f, __FILE__, __LINE__, \ doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ - decorators); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() + decorators)) #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ namespace { \ @@ -1775,18 +2004,18 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ static doctest::detail::funcType proxy() { return f; } \ - DOCTEST_REGISTER_FUNCTION(inline const, proxy(), decorators) \ + DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ static void f() // for registering tests #define DOCTEST_TEST_CASE(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) // for registering tests in classes - requires C++17 for inline variables! #if __cplusplus >= 201703L || (DOCTEST_MSVC >= DOCTEST_COMPILER(19, 12, 0) && _MSVC_LANG >= 201703L) #define DOCTEST_TEST_CASE_CLASS(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), \ - DOCTEST_ANONYMOUS(_DOCTEST_ANON_PROXY_), \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ decorators) #else // DOCTEST_TEST_CASE_CLASS #define DOCTEST_TEST_CASE_CLASS(...) \ @@ -1795,8 +2024,8 @@ int registerReporter(const char* name, int priority, bool isReporter) { // for registering tests with a fixture #define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \ - DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators) + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) // for converting types to strings without the header and demangling #define DOCTEST_TYPE_TO_STRING_IMPL(...) \ @@ -1809,7 +2038,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { DOCTEST_TYPE_TO_STRING_IMPL(__VA_ARGS__) \ } \ } \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ template \ @@ -1840,20 +2069,20 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ - DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)) + DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \ - doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\ - DOCTEST_GLOBAL_NO_WARNINGS_END() + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), \ + doctest::detail::instantiationHelper( \ + DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ @@ -1862,11 +2091,11 @@ int registerReporter(const char* name, int priority, bool isReporter) { static void anon() #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) + DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) // for subcases #define DOCTEST_SUBCASE(name) \ - if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ + if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ doctest::detail::Subcase(name, __FILE__, __LINE__)) // for grouping tests in test suites by using code blocks @@ -1875,10 +2104,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - static doctest::detail::TestSuite data; \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ static bool inited = false; \ DOCTEST_MSVC_SUPPRESS_WARNING_POP \ DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ if(!inited) { \ data* decorators; \ inited = true; \ @@ -1890,79 +2121,79 @@ int registerReporter(const char* name, int priority, bool isReporter) { namespace ns_name #define DOCTEST_TEST_SUITE(decorators) \ - DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUITE_)) + DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) // for starting a testsuite block #define DOCTEST_TEST_SUITE_BEGIN(decorators) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ + static_assert(true, "") // for ending a testsuite block #define DOCTEST_TEST_SUITE_END \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * ""); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ + typedef int DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) // for registering exception translators #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ inline doctest::String translatorName(signature); \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)) = \ - doctest::registerExceptionTranslator(translatorName); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ + doctest::registerExceptionTranslator(translatorName)) \ doctest::String translatorName(signature) #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \ + DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ signature) // for registering reporters #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \ - doctest::registerReporter(name, priority, true); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), \ + doctest::registerReporter(name, priority, true)) \ + static_assert(true, "") // for registering listeners #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \ - doctest::registerReporter(name, priority, false); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) - -// for logging -#define DOCTEST_INFO(expression) \ - DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \ - DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), expression) - -#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, expression) \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \ - auto lambda_name = [&](std::ostream* s_name) { \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), \ + doctest::registerReporter(name, priority, false)) \ + static_assert(true, "") + +// clang-format off +// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 +#define DOCTEST_INFO(...) \ + DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \ + DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \ + __VA_ARGS__) +// clang-format on + +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ + [&](std::ostream* s_name) { \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ mb_name.m_stream = s_name; \ - mb_name << expression; \ - }; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name) + mb_name * __VA_ARGS__; \ + }) -#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := " << x) +#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) -#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, x) \ - do { \ +#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ + [&] { \ doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ - mb << x; \ - DOCTEST_ASSERT_LOG_AND_REACT(mb); \ - } while(false) + mb * __VA_ARGS__; \ + if(mb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + mb.react(); \ + }() // clang-format off -#define DOCTEST_ADD_MESSAGE_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) -#define DOCTEST_ADD_FAIL_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) // clang-format on -#define DOCTEST_MESSAGE(x) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, x) -#define DOCTEST_FAIL_CHECK(x) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, x) -#define DOCTEST_FAIL(x) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, x) +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. @@ -1970,18 +2201,18 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.setResult( \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ << __VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - do { \ + [&] { \ DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ - } while(false) + }() #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2005,51 +2236,55 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) // clang-format off -#define DOCTEST_WARN_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while(false) -#define DOCTEST_CHECK_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while(false) -#define DOCTEST_REQUIRE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while(false) -#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while(false) -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while(false) -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while(false) +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); }() +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); }() // clang-format on #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ - do { \ + [&] { \ if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ __LINE__, #expr, #__VA_ARGS__, message); \ try { \ DOCTEST_CAST_TO_VOID(expr) \ - } catch(const doctest::detail::remove_const< \ - doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \ - _DOCTEST_RB.translateException(); \ - _DOCTEST_RB.m_threw_as = true; \ - } catch(...) { _DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } catch(const typename doctest::detail::remove_const< \ + typename doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \ + DOCTEST_RB.translateException(); \ + DOCTEST_RB.m_threw_as = true; \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { \ + return false; \ } \ - } while(false) + }() #define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ - do { \ + [&] { \ if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ __LINE__, expr_str, "", __VA_ARGS__); \ try { \ DOCTEST_CAST_TO_VOID(expr) \ - } catch(...) { _DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { \ + return false; \ } \ - } while(false) + }() #define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ - do { \ - doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + [&] { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ __LINE__, #__VA_ARGS__); \ try { \ DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ - } catch(...) { _DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ - } while(false) + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + }() // clang-format off #define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") @@ -2072,42 +2307,42 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) #define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS(expr); } while(false) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS(expr); } while(false) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS(expr); } while(false) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while(false) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while(false) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while(false) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, with); } while(false) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, with); } while(false) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while(false) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while(false) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while(false) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while(false) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while(false) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while(false) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while(false) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); }() +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); }() +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); }() +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); }() +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); }() +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); }() +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); }() +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); }() +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); }() +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); }() +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); }() +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); }() +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); }() +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); }() +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); }() // clang-format on #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS #define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ - do { \ - doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + [&] { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ __LINE__, #__VA_ARGS__); \ DOCTEST_WRAP_IN_TRY( \ - _DOCTEST_RB.binary_assert( \ + DOCTEST_RB.binary_assert( \ __VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ - } while(false) + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + }() #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - do { \ - doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + [&] { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ - } while(false) + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + }() #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2183,37 +2418,37 @@ int registerReporter(const char* name, int priority, bool isReporter) { #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_WARN_THROWS(...) ((void)0) -#define DOCTEST_CHECK_THROWS(...) ((void)0) -#define DOCTEST_REQUIRE_THROWS(...) ((void)0) -#define DOCTEST_WARN_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_WARN_NOTHROW(...) ((void)0) -#define DOCTEST_CHECK_NOTHROW(...) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW(...) ((void)0) - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) +#define DOCTEST_WARN_THROWS(...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS(...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS(...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_AS(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ([] { return false; }) +#define DOCTEST_WARN_NOTHROW(...) ([] { return false; }) +#define DOCTEST_CHECK_NOTHROW(...) ([] { return false; }) +#define DOCTEST_REQUIRE_NOTHROW(...) ([] { return false; }) + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; }) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) ([] { return false; }) #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS @@ -2255,35 +2490,32 @@ int registerReporter(const char* name, int priority, bool isReporter) { // for registering tests #define DOCTEST_TEST_CASE(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for registering tests in classes #define DOCTEST_TEST_CASE_CLASS(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for registering tests with a fixture #define DOCTEST_TEST_CASE_FIXTURE(x, name) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \ - DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for converting types to strings without the header and demangling -#define DOCTEST_TYPE_TO_STRING(...) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") #define DOCTEST_TYPE_TO_STRING_IMPL(...) // for typed tests #define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ template \ - inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)() + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ template \ - inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)() - -#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") // for subcases #define DOCTEST_SUBCASE(name) @@ -2292,98 +2524,159 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_TEST_SUITE(name) namespace // for starting a testsuite block -#define DOCTEST_TEST_SUITE_BEGIN(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") // for ending a testsuite block -#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ template \ - static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature) + static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define DOCTEST_INFO(x) ((void)0) -#define DOCTEST_CAPTURE(x) ((void)0) -#define DOCTEST_ADD_MESSAGE_AT(file, line, x) ((void)0) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) ((void)0) -#define DOCTEST_ADD_FAIL_AT(file, line, x) ((void)0) -#define DOCTEST_MESSAGE(x) ((void)0) -#define DOCTEST_FAIL_CHECK(x) ((void)0) -#define DOCTEST_FAIL(x) ((void)0) - -#define DOCTEST_WARN(...) ((void)0) -#define DOCTEST_CHECK(...) ((void)0) -#define DOCTEST_REQUIRE(...) ((void)0) -#define DOCTEST_WARN_FALSE(...) ((void)0) -#define DOCTEST_CHECK_FALSE(...) ((void)0) -#define DOCTEST_REQUIRE_FALSE(...) ((void)0) - -#define DOCTEST_WARN_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_CHECK_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_REQUIRE_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) ((void)0) - -#define DOCTEST_WARN_THROWS(...) ((void)0) -#define DOCTEST_CHECK_THROWS(...) ((void)0) -#define DOCTEST_REQUIRE_THROWS(...) ((void)0) -#define DOCTEST_WARN_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_WARN_NOTHROW(...) ((void)0) -#define DOCTEST_CHECK_NOTHROW(...) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW(...) ((void)0) - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) - -#define DOCTEST_WARN_EQ(...) ((void)0) -#define DOCTEST_CHECK_EQ(...) ((void)0) -#define DOCTEST_REQUIRE_EQ(...) ((void)0) -#define DOCTEST_WARN_NE(...) ((void)0) -#define DOCTEST_CHECK_NE(...) ((void)0) -#define DOCTEST_REQUIRE_NE(...) ((void)0) -#define DOCTEST_WARN_GT(...) ((void)0) -#define DOCTEST_CHECK_GT(...) ((void)0) -#define DOCTEST_REQUIRE_GT(...) ((void)0) -#define DOCTEST_WARN_LT(...) ((void)0) -#define DOCTEST_CHECK_LT(...) ((void)0) -#define DOCTEST_REQUIRE_LT(...) ((void)0) -#define DOCTEST_WARN_GE(...) ((void)0) -#define DOCTEST_CHECK_GE(...) ((void)0) -#define DOCTEST_REQUIRE_GE(...) ((void)0) -#define DOCTEST_WARN_LE(...) ((void)0) -#define DOCTEST_CHECK_LE(...) ((void)0) -#define DOCTEST_REQUIRE_LE(...) ((void)0) - -#define DOCTEST_WARN_UNARY(...) ((void)0) -#define DOCTEST_CHECK_UNARY(...) ((void)0) -#define DOCTEST_REQUIRE_UNARY(...) ((void)0) -#define DOCTEST_WARN_UNARY_FALSE(...) ((void)0) -#define DOCTEST_CHECK_UNARY_FALSE(...) ((void)0) -#define DOCTEST_REQUIRE_UNARY_FALSE(...) ((void)0) +#define DOCTEST_INFO(...) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_MESSAGE(...) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) +#define DOCTEST_FAIL(...) (static_cast(0)) + +#ifdef DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() + +namespace doctest { +namespace detail { +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } + + DOCTEST_RELATIONAL_OP(eq, ==) + DOCTEST_RELATIONAL_OP(ne, !=) + DOCTEST_RELATIONAL_OP(lt, <) + DOCTEST_RELATIONAL_OP(gt, >) + DOCTEST_RELATIONAL_OP(le, <=) + DOCTEST_RELATIONAL_OP(ge, >=) +} // namespace detail +} // namespace doctest + +#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#define DOCTEST_WARN(...) ([] { return false; }) +#define DOCTEST_CHECK(...) ([] { return false; }) +#define DOCTEST_REQUIRE(...) ([] { return false; }) +#define DOCTEST_WARN_FALSE(...) ([] { return false; }) +#define DOCTEST_CHECK_FALSE(...) ([] { return false; }) +#define DOCTEST_REQUIRE_FALSE(...) ([] { return false; }) + +#define DOCTEST_WARN_MESSAGE(cond, ...) ([] { return false; }) +#define DOCTEST_CHECK_MESSAGE(cond, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) ([] { return false; }) +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) ([] { return false; }) +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) ([] { return false; }) + +#define DOCTEST_WARN_EQ(...) ([] { return false; }) +#define DOCTEST_CHECK_EQ(...) ([] { return false; }) +#define DOCTEST_REQUIRE_EQ(...) ([] { return false; }) +#define DOCTEST_WARN_NE(...) ([] { return false; }) +#define DOCTEST_CHECK_NE(...) ([] { return false; }) +#define DOCTEST_REQUIRE_NE(...) ([] { return false; }) +#define DOCTEST_WARN_GT(...) ([] { return false; }) +#define DOCTEST_CHECK_GT(...) ([] { return false; }) +#define DOCTEST_REQUIRE_GT(...) ([] { return false; }) +#define DOCTEST_WARN_LT(...) ([] { return false; }) +#define DOCTEST_CHECK_LT(...) ([] { return false; }) +#define DOCTEST_REQUIRE_LT(...) ([] { return false; }) +#define DOCTEST_WARN_GE(...) ([] { return false; }) +#define DOCTEST_CHECK_GE(...) ([] { return false; }) +#define DOCTEST_REQUIRE_GE(...) ([] { return false; }) +#define DOCTEST_WARN_LE(...) ([] { return false; }) +#define DOCTEST_CHECK_LE(...) ([] { return false; }) +#define DOCTEST_REQUIRE_LE(...) ([] { return false; }) + +#define DOCTEST_WARN_UNARY(...) ([] { return false; }) +#define DOCTEST_CHECK_UNARY(...) ([] { return false; }) +#define DOCTEST_REQUIRE_UNARY(...) ([] { return false; }) +#define DOCTEST_WARN_UNARY_FALSE(...) ([] { return false; }) +#define DOCTEST_CHECK_UNARY_FALSE(...) ([] { return false; }) +#define DOCTEST_REQUIRE_UNARY_FALSE(...) ([] { return false; }) + +#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +// TODO: think about if these also need to work properly even when doctest is disabled +#define DOCTEST_WARN_THROWS(...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS(...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS(...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_AS(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ([] { return false; }) +#define DOCTEST_WARN_NOTHROW(...) ([] { return false; }) +#define DOCTEST_CHECK_NOTHROW(...) ([] { return false; }) +#define DOCTEST_REQUIRE_NOTHROW(...) ([] { return false; }) + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; }) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; }) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; }) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) ([] { return false; }) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) ([] { return false; }) #endif // DOCTEST_CONFIG_DISABLE @@ -2415,7 +2708,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE #define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE -#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE DOCTEST_TEST_CASE_TEMPLATE_INVOKE +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__) // clang-format on // BDD style macros @@ -2435,138 +2728,138 @@ int registerReporter(const char* name, int priority, bool isReporter) { // == SHORT VERSIONS OF THE MACROS #if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES) -#define TEST_CASE DOCTEST_TEST_CASE -#define TEST_CASE_CLASS DOCTEST_TEST_CASE_CLASS -#define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE -#define TYPE_TO_STRING DOCTEST_TYPE_TO_STRING -#define TEST_CASE_TEMPLATE DOCTEST_TEST_CASE_TEMPLATE -#define TEST_CASE_TEMPLATE_DEFINE DOCTEST_TEST_CASE_TEMPLATE_DEFINE -#define TEST_CASE_TEMPLATE_INVOKE DOCTEST_TEST_CASE_TEMPLATE_INVOKE -#define TEST_CASE_TEMPLATE_APPLY DOCTEST_TEST_CASE_TEMPLATE_APPLY -#define SUBCASE DOCTEST_SUBCASE -#define TEST_SUITE DOCTEST_TEST_SUITE -#define TEST_SUITE_BEGIN DOCTEST_TEST_SUITE_BEGIN +#define TEST_CASE(name) DOCTEST_TEST_CASE(name) +#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) +#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) +#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) +#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) +#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) +#define SUBCASE(name) DOCTEST_SUBCASE(name) +#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) +#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) #define TEST_SUITE_END DOCTEST_TEST_SUITE_END -#define REGISTER_EXCEPTION_TRANSLATOR DOCTEST_REGISTER_EXCEPTION_TRANSLATOR -#define REGISTER_REPORTER DOCTEST_REGISTER_REPORTER -#define REGISTER_LISTENER DOCTEST_REGISTER_LISTENER -#define INFO DOCTEST_INFO -#define CAPTURE DOCTEST_CAPTURE -#define ADD_MESSAGE_AT DOCTEST_ADD_MESSAGE_AT -#define ADD_FAIL_CHECK_AT DOCTEST_ADD_FAIL_CHECK_AT -#define ADD_FAIL_AT DOCTEST_ADD_FAIL_AT -#define MESSAGE DOCTEST_MESSAGE -#define FAIL_CHECK DOCTEST_FAIL_CHECK -#define FAIL DOCTEST_FAIL -#define TO_LVALUE DOCTEST_TO_LVALUE - -#define WARN DOCTEST_WARN -#define WARN_FALSE DOCTEST_WARN_FALSE -#define WARN_THROWS DOCTEST_WARN_THROWS -#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS -#define WARN_THROWS_WITH DOCTEST_WARN_THROWS_WITH -#define WARN_THROWS_WITH_AS DOCTEST_WARN_THROWS_WITH_AS -#define WARN_NOTHROW DOCTEST_WARN_NOTHROW -#define CHECK DOCTEST_CHECK -#define CHECK_FALSE DOCTEST_CHECK_FALSE -#define CHECK_THROWS DOCTEST_CHECK_THROWS -#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS -#define CHECK_THROWS_WITH DOCTEST_CHECK_THROWS_WITH -#define CHECK_THROWS_WITH_AS DOCTEST_CHECK_THROWS_WITH_AS -#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW -#define REQUIRE DOCTEST_REQUIRE -#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE -#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS -#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS -#define REQUIRE_THROWS_WITH DOCTEST_REQUIRE_THROWS_WITH -#define REQUIRE_THROWS_WITH_AS DOCTEST_REQUIRE_THROWS_WITH_AS -#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW - -#define WARN_MESSAGE DOCTEST_WARN_MESSAGE -#define WARN_FALSE_MESSAGE DOCTEST_WARN_FALSE_MESSAGE -#define WARN_THROWS_MESSAGE DOCTEST_WARN_THROWS_MESSAGE -#define WARN_THROWS_AS_MESSAGE DOCTEST_WARN_THROWS_AS_MESSAGE -#define WARN_THROWS_WITH_MESSAGE DOCTEST_WARN_THROWS_WITH_MESSAGE -#define WARN_THROWS_WITH_AS_MESSAGE DOCTEST_WARN_THROWS_WITH_AS_MESSAGE -#define WARN_NOTHROW_MESSAGE DOCTEST_WARN_NOTHROW_MESSAGE -#define CHECK_MESSAGE DOCTEST_CHECK_MESSAGE -#define CHECK_FALSE_MESSAGE DOCTEST_CHECK_FALSE_MESSAGE -#define CHECK_THROWS_MESSAGE DOCTEST_CHECK_THROWS_MESSAGE -#define CHECK_THROWS_AS_MESSAGE DOCTEST_CHECK_THROWS_AS_MESSAGE -#define CHECK_THROWS_WITH_MESSAGE DOCTEST_CHECK_THROWS_WITH_MESSAGE -#define CHECK_THROWS_WITH_AS_MESSAGE DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE -#define CHECK_NOTHROW_MESSAGE DOCTEST_CHECK_NOTHROW_MESSAGE -#define REQUIRE_MESSAGE DOCTEST_REQUIRE_MESSAGE -#define REQUIRE_FALSE_MESSAGE DOCTEST_REQUIRE_FALSE_MESSAGE -#define REQUIRE_THROWS_MESSAGE DOCTEST_REQUIRE_THROWS_MESSAGE -#define REQUIRE_THROWS_AS_MESSAGE DOCTEST_REQUIRE_THROWS_AS_MESSAGE -#define REQUIRE_THROWS_WITH_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_MESSAGE -#define REQUIRE_THROWS_WITH_AS_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE -#define REQUIRE_NOTHROW_MESSAGE DOCTEST_REQUIRE_NOTHROW_MESSAGE - -#define SCENARIO DOCTEST_SCENARIO -#define SCENARIO_CLASS DOCTEST_SCENARIO_CLASS -#define SCENARIO_TEMPLATE DOCTEST_SCENARIO_TEMPLATE -#define SCENARIO_TEMPLATE_DEFINE DOCTEST_SCENARIO_TEMPLATE_DEFINE -#define GIVEN DOCTEST_GIVEN -#define WHEN DOCTEST_WHEN -#define AND_WHEN DOCTEST_AND_WHEN -#define THEN DOCTEST_THEN -#define AND_THEN DOCTEST_AND_THEN - -#define WARN_EQ DOCTEST_WARN_EQ -#define CHECK_EQ DOCTEST_CHECK_EQ -#define REQUIRE_EQ DOCTEST_REQUIRE_EQ -#define WARN_NE DOCTEST_WARN_NE -#define CHECK_NE DOCTEST_CHECK_NE -#define REQUIRE_NE DOCTEST_REQUIRE_NE -#define WARN_GT DOCTEST_WARN_GT -#define CHECK_GT DOCTEST_CHECK_GT -#define REQUIRE_GT DOCTEST_REQUIRE_GT -#define WARN_LT DOCTEST_WARN_LT -#define CHECK_LT DOCTEST_CHECK_LT -#define REQUIRE_LT DOCTEST_REQUIRE_LT -#define WARN_GE DOCTEST_WARN_GE -#define CHECK_GE DOCTEST_CHECK_GE -#define REQUIRE_GE DOCTEST_REQUIRE_GE -#define WARN_LE DOCTEST_WARN_LE -#define CHECK_LE DOCTEST_CHECK_LE -#define REQUIRE_LE DOCTEST_REQUIRE_LE -#define WARN_UNARY DOCTEST_WARN_UNARY -#define CHECK_UNARY DOCTEST_CHECK_UNARY -#define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY -#define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE -#define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE -#define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE +#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) +#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) +#define INFO(...) DOCTEST_INFO(__VA_ARGS__) +#define CAPTURE(x) DOCTEST_CAPTURE(x) +#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) +#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) +#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) +#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) +#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) + +#define WARN(...) DOCTEST_WARN(__VA_ARGS__) +#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) +#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) +#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) +#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) +#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) +#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) +#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) +#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) +#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) +#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) +#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) +#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) + +#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) +#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) +#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) +#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) +#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) +#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) + +#define SCENARIO(name) DOCTEST_SCENARIO(name) +#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) +#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) +#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) +#define GIVEN(name) DOCTEST_GIVEN(name) +#define WHEN(name) DOCTEST_WHEN(name) +#define AND_WHEN(name) DOCTEST_AND_WHEN(name) +#define THEN(name) DOCTEST_THEN(name) +#define AND_THEN(name) DOCTEST_AND_THEN(name) + +#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) +#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) +#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) +#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) +#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) +#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) +#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) +#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) +#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) +#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) +#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) +#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) +#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) +#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) +#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) +#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) +#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) +#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) +#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) +#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) +#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) +#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) +#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) // KEPT FOR BACKWARDS COMPATIBILITY -#define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ -#define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ -#define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ -#define FAST_WARN_NE DOCTEST_FAST_WARN_NE -#define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE -#define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE -#define FAST_WARN_GT DOCTEST_FAST_WARN_GT -#define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT -#define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT -#define FAST_WARN_LT DOCTEST_FAST_WARN_LT -#define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT -#define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT -#define FAST_WARN_GE DOCTEST_FAST_WARN_GE -#define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE -#define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE -#define FAST_WARN_LE DOCTEST_FAST_WARN_LE -#define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE -#define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE - -#define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY -#define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY -#define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY -#define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE -#define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE -#define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE - -#define TEST_CASE_TEMPLATE_INSTANTIATE DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE +#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) +#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) +#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) +#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) +#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) +#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) +#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) +#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) +#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) +#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) +#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) +#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) +#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) +#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) +#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) +#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) +#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) +#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) + +#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) +#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) +#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) +#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) +#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES @@ -2603,6 +2896,8 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + #endif // DOCTEST_LIBRARY_INCLUDED #ifndef DOCTEST_SINGLE_HEADER @@ -2622,13 +2917,11 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors") DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32") DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations") @@ -2636,64 +2929,35 @@ DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch") DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum") DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default") DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef") DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion") DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces") DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path") DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") -DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") -DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers") DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch") DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum") DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default") DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations") DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast") -DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs") -DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function") DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance") -DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute") DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning -DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning -DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data -DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression -DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated -DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch -DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding in structs -DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C -DOCTEST_MSVC_SUPPRESS_WARNING(5045) // Spectre mitigation stuff -DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted -DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning) -// static analysis -DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept' -DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable -DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ... -DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtor... -DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' +DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN @@ -2701,7 +2965,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include #include #include -// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37 +// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 #ifdef __BORLANDC__ #include #endif // __BORLANDC__ @@ -2723,9 +2987,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include #include #include -#ifdef DOCTEST_CONFIG_POSIX_SIGNALS #include -#endif // DOCTEST_CONFIG_POSIX_SIGNALS #include #include #include @@ -2750,11 +3012,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #ifdef __AFXDLL #include #else -#if defined(__MINGW32__) || defined(__MINGW64__) #include -#else // MINGW -#include -#endif // MINGW #endif #include @@ -2765,7 +3023,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #endif // DOCTEST_PLATFORM_WINDOWS -// this is a fix for https://github.com/onqtam/doctest/issues/348 +// this is a fix for https://github.com/doctest/doctest/issues/348 // https://mail.gnome.org/archives/xml/2012-January/msg00000.html #if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) #define STDOUT_FILENO fileno(stdout) @@ -2787,7 +3045,19 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #endif #ifndef DOCTEST_THREAD_LOCAL +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_THREAD_LOCAL +#else // DOCTEST_MSVC #define DOCTEST_THREAD_LOCAL thread_local +#endif // DOCTEST_MSVC +#endif // DOCTEST_THREAD_LOCAL + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES +#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32 +#endif + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE +#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64 #endif #ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS @@ -2796,12 +3066,38 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #define DOCTEST_OPTIONS_PREFIX_DISPLAY "" #endif +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS +#endif + +#ifndef DOCTEST_CDECL +#define DOCTEST_CDECL __cdecl +#endif + namespace doctest { bool is_running_in_test = false; namespace { using namespace detail; + + template + DOCTEST_NORETURN void throw_exception(Ex const& e) { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + throw e; +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + std::cerr << "doctest will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; + std::terminate(); +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } + +#ifndef DOCTEST_INTERNAL_ERROR +#define DOCTEST_INTERNAL_ERROR(msg) \ + throw_exception(std::logic_error( \ + __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) +#endif // DOCTEST_INTERNAL_ERROR + // case insensitive strcmp int stricmp(const char* a, const char* b) { for(;; a++, b++) { @@ -2845,8 +3141,6 @@ namespace { } // namespace namespace detail { - void my_memcpy(void* dest, const void* src, unsigned num) { memcpy(dest, src, num); } - String rawMemoryToString(const void* object, unsigned size) { // Reverse order for little endian architectures int i = 0, end = static_cast(size), inc = 1; @@ -2856,25 +3150,42 @@ namespace detail { } unsigned const char* bytes = static_cast(object); - std::ostringstream oss; - oss << "0x" << std::setfill('0') << std::hex; + std::ostream* oss = tlssPush(); + *oss << "0x" << std::setfill('0') << std::hex; for(; i != end; i += inc) - oss << std::setw(2) << static_cast(bytes[i]); - return oss.str().c_str(); + *oss << std::setw(2) << static_cast(bytes[i]); + return tlssPop(); } - DOCTEST_THREAD_LOCAL std::ostringstream g_oss; // NOLINT(cert-err58-cpp) + DOCTEST_THREAD_LOCAL class + { + std::vector stack; + std::stringstream ss; + + public: + std::ostream* push() { + stack.push_back(ss.tellp()); + return &ss; + } + + String pop() { + if (stack.empty()) + DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); - std::ostream* getTlsOss() { - g_oss.clear(); // there shouldn't be anything worth clearing in the flags - g_oss.str(""); // the slow way of resetting a string stream - //g_oss.seekp(0); // optimal reset - as seen here: https://stackoverflow.com/a/624291/3162383 - return &g_oss; + std::streampos pos = stack.back(); + stack.pop_back(); + unsigned sz = static_cast(ss.tellp() - pos); + ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); + return String(ss, sz); + } + } g_oss; + + std::ostream* tlssPush() { + return g_oss.push(); } - String getTlsOssResult() { - //g_oss << std::ends; // needed - as shown here: https://stackoverflow.com/a/624291/3162383 - return g_oss.str().c_str(); + String tlssPop() { + return g_oss.pop(); } #ifndef DOCTEST_CONFIG_DISABLE @@ -2885,8 +3196,7 @@ namespace timer_large_integer #if defined(DOCTEST_PLATFORM_WINDOWS) typedef ULONGLONG type; #else // DOCTEST_PLATFORM_WINDOWS - using namespace std; - typedef uint64_t type; + typedef std::uint64_t type; #endif // DOCTEST_PLATFORM_WINDOWS } @@ -2928,18 +3238,105 @@ typedef timer_large_integer::type ticks_t; ticks_t m_ticks = 0; }; +#ifdef DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + template + using AtomicOrMultiLaneAtomic = std::atomic; +#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + // Provides a multilane implementation of an atomic variable that supports add, sub, load, + // store. Instead of using a single atomic variable, this splits up into multiple ones, + // each sitting on a separate cache line. The goal is to provide a speedup when most + // operations are modifying. It achieves this with two properties: + // + // * Multiple atomics are used, so chance of congestion from the same atomic is reduced. + // * Each atomic sits on a separate cache line, so false sharing is reduced. + // + // The disadvantage is that there is a small overhead due to the use of TLS, and load/store + // is slower because all atomics have to be accessed. + template + class MultiLaneAtomic + { + struct CacheLineAlignedAtomic + { + std::atomic atomic{}; + char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(std::atomic)]; + }; + CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; + + static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, + "guarantee one atomic takes exactly one cache line"); + + public: + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } + + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } + + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_add(arg, order); + } + + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_sub(arg, order); + } + + operator T() const DOCTEST_NOEXCEPT { return load(); } + + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { + auto result = T(); + for(auto const& c : m_atomics) { + result += c.atomic.load(order); + } + return result; + } + + T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] + store(desired); + return desired; + } + + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + // first value becomes desired", all others become 0. + for(auto& c : m_atomics) { + c.atomic.store(desired, order); + desired = {}; + } + } + + private: + // Each thread has a different atomic that it operates on. If more than NumLanes threads + // use this, some will use the same atomic. So performance will degrade a bit, but still + // everything will work. + // + // The logic here is a bit tricky. The call should be as fast as possible, so that there + // is minimal to no overhead in determining the correct atomic for the current thread. + // + // 1. A global static counter laneCounter counts continuously up. + // 2. Each successive thread will use modulo operation of that counter so it gets an atomic + // assigned in a round-robin fashion. + // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with + // little overhead. + std::atomic& myAtomic() DOCTEST_NOEXCEPT { + static std::atomic laneCounter; + DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = + laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; + + return m_atomics[tlsLaneIdx].atomic; + } + }; + + template + using AtomicOrMultiLaneAtomic = MultiLaneAtomic; +#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + // this holds both parameters from the command line and runtime data for tests struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats { - std::atomic numAssertsCurrentTest_atomic; - std::atomic numAssertsFailedCurrentTest_atomic; + AtomicOrMultiLaneAtomic numAssertsCurrentTest_atomic; + AtomicOrMultiLaneAtomic numAssertsFailedCurrentTest_atomic; std::vector> filters = decltype(filters)(9); // 9 different filters std::vector reporters_currently_used; - const TestCase* currentTest = nullptr; - assert_handler ah = nullptr; Timer timer; @@ -3001,7 +3398,8 @@ typedef timer_large_integer::type ticks_t; (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); // if any subcase has failed - the whole test case has failed - if(failure_flags && !ok_to_fail) + testCaseSuccess = !(failure_flags && !ok_to_fail); + if(!testCaseSuccess) numTestCasesFailed++; } }; @@ -3016,19 +3414,29 @@ typedef timer_large_integer::type ticks_t; #endif // DOCTEST_CONFIG_DISABLE } // namespace detail +char* String::allocate(unsigned sz) { + if (sz <= last) { + buf[sz] = '\0'; + setLast(last - sz); + return buf; + } else { + setOnHeap(); + data.size = sz; + data.capacity = data.size + 1; + data.ptr = new char[data.capacity]; + data.ptr[sz] = '\0'; + return data.ptr; + } +} + void String::setOnHeap() { *reinterpret_cast(&buf[last]) = 128; } void String::setLast(unsigned in) { buf[last] = char(in); } void String::copy(const String& other) { - using namespace std; if(other.isOnStack()) { memcpy(buf, other.buf, len); } else { - setOnHeap(); - data.size = other.data.size; - data.capacity = data.size + 1; - data.ptr = new char[data.capacity]; - memcpy(data.ptr, other.data.ptr, data.size + 1); + memcpy(allocate(other.data.size), other.data.ptr, other.data.size); } } @@ -3040,23 +3448,18 @@ String::String() { String::~String() { if(!isOnStack()) delete[] data.ptr; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) } String::String(const char* in) : String(in, strlen(in)) {} String::String(const char* in, unsigned in_size) { - using namespace std; - if(in_size <= last) { - memcpy(buf, in, in_size + 1); - setLast(last - in_size); - } else { - setOnHeap(); - data.size = in_size; - data.capacity = data.size + 1; - data.ptr = new char[data.capacity]; - memcpy(data.ptr, in, in_size + 1); - } + memcpy(allocate(in_size), in, in_size); +} + +String::String(std::istream& in, unsigned in_size) { + in.read(allocate(in_size), in_size); } String::String(const String& other) { copy(other); } @@ -3076,11 +3479,11 @@ String& String::operator+=(const String& other) { const unsigned my_old_size = size(); const unsigned other_size = other.size(); const unsigned total_size = my_old_size + other_size; - using namespace std; if(isOnStack()) { if(total_size < len) { // append to the current stack space memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) setLast(last - total_size); } else { // alloc new chunk @@ -3122,17 +3525,13 @@ String& String::operator+=(const String& other) { return *this; } -String String::operator+(const String& other) const { return String(*this) += other; } - String::String(String&& other) { - using namespace std; memcpy(buf, other.buf, len); other.buf[0] = '\0'; other.setLast(); } String& String::operator=(String&& other) { - using namespace std; if(this != &other) { if(!isOnStack()) delete[] data.ptr; @@ -3177,6 +3576,9 @@ int String::compare(const String& other, bool no_case) const { return compare(other.c_str(), no_case); } +// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) +String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } + // clang-format off bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } @@ -3276,6 +3678,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") // depending on the current options this will remove the path of filenames const char* skipPathFromFilename(const char* file) { +#ifndef DOCTEST_CONFIG_DISABLE if(getContextOptions()->no_path_in_filenames) { auto back = std::strrchr(file, '\\'); auto forward = std::strrchr(file, '/'); @@ -3285,6 +3688,7 @@ const char* skipPathFromFilename(const char* file) { return forward + 1; } } +#endif // DOCTEST_CONFIG_DISABLE return file; } DOCTEST_CLANG_SUPPRESS_WARNING_POP @@ -3303,6 +3707,7 @@ IContextScope::~IContextScope() = default; #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING String toString(char* in) { return toString(static_cast(in)); } +// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING String toString(bool in) { return in ? "true" : "false"; } @@ -3332,7 +3737,7 @@ DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu") String toString(std::nullptr_t) { return "NULL"; } #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 String toString(const std::string& in) { return in.c_str(); } #endif // VS 2019 @@ -3375,7 +3780,8 @@ bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } String toString(const Approx& in) { - return String("Approx( ") + doctest::toString(in.m_value) + " )"; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + return "Approx( " + doctest::toString(in.m_value) + " )"; } const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } @@ -3388,11 +3794,13 @@ Context::~Context() = default; void Context::applyCommandLine(int, const char* const*) {} void Context::addFilter(const char*, const char*) {} void Context::clearFilters() {} +void Context::setOption(const char*, bool) {} void Context::setOption(const char*, int) {} void Context::setOption(const char*, const char*) {} bool Context::shouldExit() { return false; } void Context::setAsDefaultForAssertsOutOfTestCases() {} void Context::setAssertHandler(detail::assert_handler) {} +void Context::setCout(std::ostream* out) {} int Context::run() { return 0; } IReporter::~IReporter() = default; @@ -3420,7 +3828,7 @@ int registerReporter(const char*, int, IReporter*) { return 0; } namespace doctest_detail_test_suite_ns { // holds the current test suite doctest::detail::TestSuite& getCurrentTestSuite() { - static doctest::detail::TestSuite data; + static doctest::detail::TestSuite data{}; return data; } } // namespace doctest_detail_test_suite_ns @@ -3532,7 +3940,7 @@ namespace detail { Subcase::Subcase(const String& name, const char* file, int line) : m_signature({name, file, line}) { - ContextState* s = g_cs; + auto* s = g_cs; // check subcase filters if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) { @@ -3563,8 +3971,8 @@ namespace detail { DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); } - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") Subcase::~Subcase() { @@ -3574,7 +3982,7 @@ namespace detail { g_cs->subcasesPassed.insert(g_cs->subcasesStack); g_cs->subcasesStack.pop_back(); -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) if(std::uncaught_exceptions() > 0 #else if(std::uncaught_exception() @@ -3591,8 +3999,8 @@ namespace detail { } } - DOCTEST_CLANG_SUPPRESS_WARNING_POP - DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP Subcase::operator bool() const { return m_entered; } @@ -3606,13 +4014,6 @@ namespace detail { TestSuite& TestSuite::operator*(const char* in) { m_test_suite = in; - // clear state - m_description = nullptr; - m_skip = false; - m_may_fail = false; - m_should_fail = false; - m_expected_failures = 0; - m_timeout = 0; return *this; } @@ -3624,6 +4025,8 @@ namespace detail { m_test_suite = test_suite.m_test_suite; m_description = test_suite.m_description; m_skip = test_suite.m_skip; + m_no_breaks = test_suite.m_no_breaks; + m_no_output = test_suite.m_no_output; m_may_fail = test_suite.m_may_fail; m_should_fail = test_suite.m_should_fail; m_expected_failures = test_suite.m_expected_failures; @@ -3667,13 +4070,23 @@ namespace detail { } bool TestCase::operator<(const TestCase& other) const { + // this will be used only to differentiate between test cases - not relevant for sorting if(m_line != other.m_line) return m_line < other.m_line; + const int name_cmp = strcmp(m_name, other.m_name); + if(name_cmp != 0) + return name_cmp < 0; const int file_cmp = m_file.compare(other.m_file); if(file_cmp != 0) return file_cmp < 0; return m_template_id < other.m_template_id; } + + // all the registered tests + std::set& getRegisteredTests() { + static std::set data; + return data; + } } // namespace detail namespace { using namespace detail; @@ -3705,39 +4118,10 @@ namespace { return suiteOrderComparator(lhs, rhs); } - // all the registered tests - std::set& getRegisteredTests() { - static std::set data; - return data; - } - -#ifdef DOCTEST_CONFIG_COLORS_WINDOWS - HANDLE g_stdoutHandle; - WORD g_origFgAttrs; - WORD g_origBgAttrs; - bool g_attrsInitted = false; - - int colors_init() { - if(!g_attrsInitted) { - g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - g_attrsInitted = true; - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(g_stdoutHandle, &csbiInfo); - g_origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | - BACKGROUND_BLUE | BACKGROUND_INTENSITY); - g_origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | - FOREGROUND_BLUE | FOREGROUND_INTENSITY); - } - return 0; - } - - int dumy_init_console_colors = colors_init(); -#endif // DOCTEST_CONFIG_COLORS_WINDOWS - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") void color_to_stream(std::ostream& s, Color::Enum code) { - ((void)s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS - ((void)code); // for DOCTEST_CONFIG_COLORS_NONE + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE #ifdef DOCTEST_CONFIG_COLORS_ANSI if(g_no_colors || (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) @@ -3767,10 +4151,26 @@ namespace { #ifdef DOCTEST_CONFIG_COLORS_WINDOWS if(g_no_colors || - (isatty(fileno(stdout)) == false && getContextOptions()->force_colors == false)) + (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) return; -#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(g_stdoutHandle, x | g_origBgAttrs) + static struct ConsoleHelper { + HANDLE stdoutHandle; + WORD origFgAttrs; + WORD origBgAttrs; + + ConsoleHelper() { + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + } ch; + +#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) // clang-format off switch (code) { @@ -3787,7 +4187,7 @@ namespace { case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; case Color::None: case Color::Bright: // invalid - default: DOCTEST_SET_ATTR(g_origFgAttrs); + default: DOCTEST_SET_ATTR(ch.origFgAttrs); } // clang-format on #endif // DOCTEST_CONFIG_COLORS_WINDOWS @@ -3843,7 +4243,28 @@ namespace detail { #ifdef DOCTEST_IS_DEBUGGER_ACTIVE bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } #else // DOCTEST_IS_DEBUGGER_ACTIVE -#ifdef DOCTEST_PLATFORM_MAC +#ifdef DOCTEST_PLATFORM_LINUX + class ErrnoGuard { + public: + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + // See the comments in Catch2 for the reasoning behind this implementation: + // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 + bool isDebuggerActive() { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for(std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; + } +#elif defined(DOCTEST_PLATFORM_MAC) // The following function is taken directly from the following technical note: // https://developer.apple.com/library/archive/qa/qa1361/_index.html // Returns true if the current process is being debugged (either @@ -3910,15 +4331,23 @@ namespace detail { g_infoContexts.push_back(this); } - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) { + if (other.need_to_destroy) { + other.destroy(); + } + other.need_to_destroy = false; + g_infoContexts.push_back(this); + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // destroy cannot be inlined into the destructor because that would mean calling stringify after // ContextScope has been destroyed (base class destructors run after derived class destructors). // Instead, ContextScope calls this method directly from its destructor. void ContextScopeBase::destroy() { -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) if(std::uncaught_exceptions() > 0) { #else if(std::uncaught_exception()) { @@ -3930,8 +4359,8 @@ namespace detail { g_infoContexts.pop_back(); } - DOCTEST_CLANG_SUPPRESS_WARNING_POP - DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP } // namespace detail namespace { @@ -3940,7 +4369,9 @@ namespace { #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) struct FatalConditionHandler { - void reset() {} + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} }; #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH @@ -3957,26 +4388,45 @@ namespace { // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. SignalDefs signalDefs[] = { - {EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal"}, - {EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow"}, - {EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal"}, - {EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error"}, + {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), + "SIGILL - Illegal instruction signal"}, + {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast(EXCEPTION_ACCESS_VIOLATION), + "SIGSEGV - Segmentation violation signal"}, + {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, }; struct FatalConditionHandler { static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { - for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - break; + // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the + // console just once no matter how many threads have crashed. + static std::mutex mutex; + static bool execute = true; + { + std::lock_guard lock(mutex); + if(execute) { + bool reported = false; + for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } + } + if(reported == false) + reportFatal("Unhandled SEH exception caught"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); } + execute = false; } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; + std::exit(EXIT_FAILURE); } + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + FatalConditionHandler() { isSet = true; // 32k seems enough for doctest to handle stack overflow, @@ -3986,6 +4436,51 @@ namespace { previousTop = SetUnhandledExceptionFilter(handleException); // Pass in guarantee size to be filled SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() DOCTEST_NOEXCEPT { + reportFatal("Terminate handler called"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { + if(signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // 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. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); } static void reset() { @@ -3993,7 +4488,13 @@ namespace { // Unregister handler and restore the old guarantee SetUnhandledExceptionFilter(previousTop); SetThreadStackGuarantee(&guaranteeSize); - previousTop = nullptr; + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); + static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); isSet = false; } } @@ -4001,11 +4502,25 @@ namespace { ~FatalConditionHandler() { reset(); } private: + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void (DOCTEST_CDECL *prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; static bool isSet; static ULONG guaranteeSize; static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; }; + UINT FatalConditionHandler::prev_error_mode_1; + int FatalConditionHandler::prev_error_mode_2; + unsigned int FatalConditionHandler::prev_abort_behavior; + int FatalConditionHandler::prev_report_mode; + _HFILE FatalConditionHandler::prev_report_file; + void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; bool FatalConditionHandler::isSet = false; ULONG FatalConditionHandler::guaranteeSize = 0; LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; @@ -4029,7 +4544,8 @@ namespace { static bool isSet; static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; static stack_t oldSigStack; - static char altStackMem[4 * SIGSTKSZ]; + static size_t altStackSize; + static char* altStackMem; static void handleSignal(int sig) { const char* name = ""; @@ -4045,11 +4561,19 @@ namespace { raise(sig); } + static void allocateAltStackMem() { + altStackMem = new char[altStackSize]; + } + + static void freeAltStackMem() { + delete[] altStackMem; + } + FatalConditionHandler() { isSet = true; stack_t sigStack; sigStack.ss_sp = altStackMem; - sigStack.ss_size = sizeof(altStackMem); + sigStack.ss_size = altStackSize; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = {}; @@ -4074,10 +4598,11 @@ namespace { } }; - bool FatalConditionHandler::isSet = false; + bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; + char* FatalConditionHandler::altStackMem = nullptr; #endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH @@ -4167,7 +4692,7 @@ namespace detail { } if(m_exception.size()) - m_exception = String("\"") + m_exception + "\""; + m_exception = "\"" + m_exception + "\""; if(is_running_in_test) { addAssert(m_at); @@ -4179,8 +4704,8 @@ namespace detail { failed_out_of_a_testing_context(*this); } - return m_failed && isDebuggerActive() && - !getContextOptions()->no_breaks; // break into debugger + return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger } void ResultBuilder::react() const { @@ -4195,7 +4720,7 @@ namespace detail { std::abort(); } - void decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, + bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, Result result) { bool failed = !result.m_passed; @@ -4205,20 +4730,31 @@ namespace detail { // ################################################################################### DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + return !failed; } MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { - m_stream = getTlsOss(); + m_stream = tlssPush(); m_file = file; m_line = line; m_severity = severity; } + MessageBuilder::~MessageBuilder() { + if (!logged) + tlssPop(); + } + IExceptionTranslator::IExceptionTranslator() = default; IExceptionTranslator::~IExceptionTranslator() = default; bool MessageBuilder::log() { - m_string = getTlsOssResult(); + if (!logged) { + m_string = tlssPop(); + logged = true; + } + DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); const bool isWarn = m_severity & assertType::is_warn; @@ -4229,36 +4765,18 @@ namespace detail { addFailedAssert(m_severity); } - return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn; // break + return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger } void MessageBuilder::react() { if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional throwException(); } - - MessageBuilder::~MessageBuilder() = default; } // namespace detail namespace { using namespace detail; - template - DOCTEST_NORETURN void throw_exception(Ex const& e) { -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - throw e; -#else // DOCTEST_CONFIG_NO_EXCEPTIONS - std::cerr << "doctest will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; - std::terminate(); -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - } - -#ifndef DOCTEST_INTERNAL_ERROR -#define DOCTEST_INTERNAL_ERROR(msg) \ - throw_exception(std::logic_error( \ - __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) -#endif // DOCTEST_INTERNAL_ERROR - // clang-format off // ================================================================================================= @@ -4721,7 +5239,8 @@ namespace { xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) .writeAttribute("testsuite", in.data[i]->m_test_suite) .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) - .writeAttribute("line", line(in.data[i]->m_line)); + .writeAttribute("line", line(in.data[i]->m_line)) + .writeAttribute("skipped", in.data[i]->m_skip); } xml.scopedElement("OverallResultsTestCases") .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); @@ -4791,7 +5310,8 @@ namespace { xml.startElement("OverallResultsAsserts") .writeAttribute("successes", st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) - .writeAttribute("failures", st.numAssertsFailedCurrentTest); + .writeAttribute("failures", st.numAssertsFailedCurrentTest) + .writeAttribute("test_case_success", st.testCaseSuccess); if(opt.duration) xml.writeAttribute("duration", st.seconds); if(tc->m_expected_failures) @@ -4810,8 +5330,6 @@ namespace { } void subcase_start(const SubcaseSignature& in) override { - std::lock_guard lock(mutex); - xml.startElement("SubCase") .writeAttribute("name", in.m_name) .writeAttribute("filename", skipPathFromFilename(in.m_file)) @@ -4927,7 +5445,6 @@ namespace { } // TODO: - // - log_contexts() // - log_message() // - respond to queries // - honor remaining options @@ -4941,7 +5458,6 @@ namespace { struct JUnitTestCaseData { -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime static std::string getCurrentTimestamp() { // Beware, this is not reentrant because of backward compatibility issues // Also, UTC only, again because of backward compatibility (%z is C++11) @@ -4949,16 +5465,19 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime std::time(&rawtime); auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); + std::tm timeInfo; +#ifdef DOCTEST_PLATFORM_WINDOWS + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); +#endif // DOCTEST_PLATFORM_WINDOWS char timeStamp[timeStampSize]; const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); return std::string(timeStamp); } -DOCTEST_CLANG_SUPPRESS_WARNING_POP struct JUnitTestMessage { @@ -5106,7 +5625,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } void subcase_start(const SubcaseSignature& in) override { - std::lock_guard lock(mutex); deepestSubcaseStackNames.push_back(in.m_name); } @@ -5123,12 +5641,27 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; fulltext_log_assert_to_stream(os, rb); + log_contexts(os); testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); } void log_message(const MessageData&) override {} void test_case_skipped(const TestCaseData&) override {} + + void log_contexts(std::ostringstream& s) { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for(int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } }; DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); @@ -5257,9 +5790,11 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } void printIntro() { - printVersion(); - s << Color::Cyan << "[doctest] " << Color::None - << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + if(opt.no_intro == false) { + printVersion(); + s << Color::Cyan << "[doctest] " << Color::None + << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + } } void printHelp() { @@ -5321,7 +5856,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP << Whitespace(sizePrefixDisplay*1) << "output filename\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by= " << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n"; - s << Whitespace(sizePrefixDisplay*3) << " - by [file/suite/name/rand]\n"; + s << Whitespace(sizePrefixDisplay*3) << " - [file/suite/name/rand/none]\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed= " << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first= " @@ -5344,12 +5879,18 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration= " << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal= " + << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet= " + << Whitespace(sizePrefixDisplay*1) << "no console output\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw= " << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode= " << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run= " << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro= " + << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version= " << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n"; s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors= " @@ -5387,22 +5928,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP printReporters(getReporters(), "reporters"); } - void list_query_results() { - separator_to_stream(); - if(opt.count || opt.list_test_cases) { - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - } else if(opt.list_test_suites) { - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "test suites with unskipped test cases passing the current filters: " - << g_cs->numTestSuitesPassingFilters << "\n"; - } - } - // ========================================================================================= // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE // ========================================================================================= @@ -5448,31 +5973,40 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } } - void test_run_start() override { printIntro(); } + void test_run_start() override { + if(!opt.minimal) + printIntro(); + } void test_run_end(const TestRunStats& p) override { + if(opt.minimal && p.numTestCasesFailed == 0) + return; + separator_to_stream(); s << std::dec; + auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); + auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); + auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; - s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(6) + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) << p.numTestCasesPassingFilters << " | " << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(6) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) - << std::setw(6) << p.numTestCasesFailed << " failed" << Color::None << " | "; + << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; if(opt.no_skipped_summary == false) { const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; - s << (numSkipped == 0 ? Color::None : Color::Yellow) << std::setw(6) << numSkipped + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped << " skipped" << Color::None; } s << "\n"; - s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(6) + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) << p.numAsserts << " | " << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(6) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None - << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(6) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) << p.numAssertsFailed << " failed" << Color::None << " |\n"; s << Color::Cyan << "[doctest] " << Color::None << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) @@ -5491,6 +6025,9 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } void test_case_end(const CurrentTestCaseStats& st) override { + if(tc->m_no_output) + return; + // log the preamble of the test case only if there is something // else to print - something other than that an assert has failed if(opt.duration || @@ -5525,6 +6062,10 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } void test_case_exception(const TestCaseException& e) override { + std::lock_guard lock(mutex); + if(tc->m_no_output) + return; + logTestStart(); file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); @@ -5546,20 +6087,18 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } void subcase_start(const SubcaseSignature& subc) override { - std::lock_guard lock(mutex); subcasesStack.push_back(subc); ++currentSubcaseLevel; hasLoggedCurrentTestStart = false; } void subcase_end() override { - std::lock_guard lock(mutex); --currentSubcaseLevel; hasLoggedCurrentTestStart = false; } void log_assert(const AssertData& rb) override { - if(!rb.m_failed && !opt.success) + if((!rb.m_failed && !opt.success) || tc->m_no_output) return; std::lock_guard lock(mutex); @@ -5575,6 +6114,9 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP } void log_message(const MessageData& mb) override { + if(tc->m_no_output) + return; + std::lock_guard lock(mutex); logTestStart(); @@ -5605,8 +6147,10 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP bool with_col = g_no_colors; \ g_no_colors = false; \ ConsoleReporter::func(arg); \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ + if(oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ g_no_colors = with_col; \ } @@ -5684,18 +6228,42 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP std::vector& res) { String filtersString; if(parseOption(argc, argv, pattern, &filtersString)) { - // tokenize with "," as a separator - // cppcheck-suppress strtokCalled - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - auto pch = std::strtok(filtersString.c_str(), ","); // modifies the string - while(pch != nullptr) { - if(strlen(pch)) - res.push_back(pch); - // uses the strtok() internal state to go to the next token - // cppcheck-suppress strtokCalled - pch = std::strtok(nullptr, ","); + // tokenize with "," as a separator, unless escaped with backslash + std::ostringstream s; + auto flush = [&s, &res]() { + auto string = s.str(); + if(string.size() > 0) { + res.push_back(string.c_str()); + } + s.str(""); + }; + + bool seenBackslash = false; + const char* current = filtersString.c_str(); + const char* end = current + strlen(current); + while(current != end) { + char character = *current++; + if(seenBackslash) { + seenBackslash = false; + if(character == ',') { + s.put(','); + continue; + } + s.put('\\'); + } + if(character == '\\') { + seenBackslash = true; + } else if(character == ',') { + flush(); + } else { + s.put(character); + } } - DOCTEST_CLANG_SUPPRESS_WARNING_POP + + if(seenBackslash) { + s.put('\\'); + } + flush(); return true; } return false; @@ -5793,7 +6361,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ - p->var = !!intRes; \ + p->var = static_cast(intRes); \ else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ p->var = true; \ @@ -5828,9 +6396,12 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false); @@ -5839,6 +6410,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); // clang-format on @@ -5893,9 +6465,15 @@ void Context::clearFilters() { curr.clear(); } -// allows the user to override procedurally the int/bool options from the command line +// allows the user to override procedurally the bool options from the command line +void Context::setOption(const char* option, bool value) { + setOption(option, value ? "true" : "false"); +} + +// allows the user to override procedurally the int options from the command line void Context::setOption(const char* option, int value) { setOption(option, toString(value).c_str()); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) } // allows the user to override procedurally the string options from the command line @@ -5912,6 +6490,31 @@ void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } +void Context::setCout(std::ostream* out) { p->cout = out; } + +static class DiscardOStream : public std::ostream +{ +private: + class : public std::streambuf + { + private: + // allowing some buffering decreases the amount of calls to overflow + char buf[1024]; + + protected: + std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } + + int_type overflow(int_type ch) override { + setp(std::begin(buf), std::end(buf)); + return traits_type::not_eof(ch); + } + } discardBuf; + +public: + DiscardOStream() + : std::ostream(&discardBuf) {} +} discardOut; + // the main function that does all the filtering and test running int Context::run() { using namespace detail; @@ -5925,18 +6528,25 @@ int Context::run() { g_no_colors = p->no_colors; p->resetRunData(); - // stdout by default - p->cout = &std::cout; - p->cerr = &std::cerr; - - // or to a file if specified std::fstream fstr; - if(p->out.size()) { - fstr.open(p->out.c_str(), std::fstream::out); - p->cout = &fstr; + if(p->cout == nullptr) { + if(p->quiet) { + p->cout = &discardOut; + } else if(p->out.size()) { + // to a file if specified + fstr.open(p->out.c_str(), std::fstream::out); + p->cout = &fstr; + } else { + // stdout by default + p->cout = &std::cout; + } } + FatalConditionHandler::allocateAltStackMem(); + auto cleanup_and_return = [&]() { + FatalConditionHandler::freeAltStackMem(); + if(fstr.is_open()) fstr.close(); @@ -5971,7 +6581,7 @@ int Context::run() { p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); #ifdef DOCTEST_PLATFORM_WINDOWS - if(isDebuggerActive()) + if(isDebuggerActive() && p->no_debug_output == false) p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); #endif // DOCTEST_PLATFORM_WINDOWS @@ -6008,6 +6618,9 @@ int Context::run() { first[i] = first[idxToSwap]; first[idxToSwap] = temp; } + } else if(p->order_by.compare("none", true) == 0) { + // means no sorting - beneficial for death tests which call into the executable + // with a specific test case in mind - we don't want to slow down the startup times } } @@ -6107,10 +6720,13 @@ int Context::run() { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS try { #endif // DOCTEST_CONFIG_NO_EXCEPTIONS +// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable FatalConditionHandler fatalConditionHandler; // Handle signals // execute the test tc.m_test(); fatalConditionHandler.reset(); +DOCTEST_MSVC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS } catch(const TestFailureException&) { p->failure_flags |= TestCaseFailureReason::AssertFailure; @@ -6156,13 +6772,6 @@ int Context::run() { DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); } - // see these issues on the reasoning for this: - // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903 - // - https://github.com/onqtam/doctest/issues/126 - auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE - { std::cout << std::string(); }; - DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS(); - return cleanup_and_return(); } @@ -6201,5 +6810,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + #endif // DOCTEST_LIBRARY_IMPLEMENTATION #endif // DOCTEST_CONFIG_IMPLEMENT